Mention archiving.
[emacs.git] / src / window.c
blob4c68de2b9059abf4c9572cea90f797dad8d3ac48
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
4 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
5 Free Software Foundation, Inc.
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 #include <config.h>
23 #include <stdio.h>
25 #include "lisp.h"
26 #include "buffer.h"
27 #include "keyboard.h"
28 #include "keymap.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "commands.h"
32 #include "indent.h"
33 #include "termchar.h"
34 #include "disptab.h"
35 #include "dispextern.h"
36 #include "blockinput.h"
37 #include "intervals.h"
38 #include "termhooks.h" /* For FRAME_TERMINAL. */
40 #ifdef HAVE_X_WINDOWS
41 #include "xterm.h"
42 #endif /* HAVE_X_WINDOWS */
43 #ifdef WINDOWSNT
44 #include "w32term.h"
45 #endif
46 #ifdef MSDOS
47 #include "msdos.h"
48 #endif
49 #ifdef HAVE_NS
50 #include "nsterm.h"
51 #endif
54 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
55 Lisp_Object Qdisplay_buffer;
56 Lisp_Object Qscroll_up, Qscroll_down;
57 Lisp_Object Qwindow_size_fixed;
59 extern Lisp_Object Qleft_margin, Qright_margin;
61 static int displayed_window_lines P_ ((struct window *));
62 static struct window *decode_window P_ ((Lisp_Object));
63 static int count_windows P_ ((struct window *));
64 static int get_leaf_windows P_ ((struct window *, struct window **, int));
65 static void window_scroll P_ ((Lisp_Object, int, int, int));
66 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
67 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
68 static int window_min_size_1 P_ ((struct window *, int, int));
69 static int window_min_size_2 P_ ((struct window *, int, int));
70 static int window_min_size P_ ((struct window *, int, int, int, int *));
71 static void size_window P_ ((Lisp_Object, int, int, int, int, int));
72 static int freeze_window_start P_ ((struct window *, void *));
73 static int window_fixed_size_p P_ ((struct window *, int, int));
74 static void enlarge_window P_ ((Lisp_Object, int, int));
75 static Lisp_Object window_list P_ ((void));
76 static int add_window_to_list P_ ((struct window *, void *));
77 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
78 Lisp_Object));
79 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
80 Lisp_Object, int));
81 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
82 Lisp_Object *));
83 static int foreach_window_1 P_ ((struct window *,
84 int (* fn) (struct window *, void *),
85 void *));
86 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
88 /* This is the window in which the terminal's cursor should
89 be left when nothing is being done with it. This must
90 always be a leaf window, and its buffer is selected by
91 the top level editing loop at the end of each command.
93 This value is always the same as
94 FRAME_SELECTED_WINDOW (selected_frame). */
96 Lisp_Object selected_window;
98 /* A list of all windows for use by next_window and Fwindow_list.
99 Functions creating or deleting windows should invalidate this cache
100 by setting it to nil. */
102 Lisp_Object Vwindow_list;
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. */
109 Lisp_Object minibuf_window;
111 /* Non-nil means it is the window whose mode line should be
112 shown as the selected window when the minibuffer is selected. */
114 Lisp_Object minibuf_selected_window;
116 /* Non-nil means it is the window for C-M-v to scroll
117 when the mini-buffer is selected. */
119 Lisp_Object Vminibuf_scroll_window;
121 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
123 Lisp_Object Vother_window_scroll_buffer;
125 /* Non-nil means it's function to call to display temp buffers. */
127 Lisp_Object Vtemp_buffer_show_function;
129 /* Non-zero means line and page scrolling on tall lines (with images)
130 does partial scrolling by modifying window-vscroll. */
132 int auto_window_vscroll_p;
134 /* Non-zero means to use mode-line-inactive face in all windows but the
135 selected-window and the minibuffer-scroll-window when the
136 minibuffer is active. */
137 int mode_line_in_non_selected_windows;
139 /* If a window gets smaller than either of these, it is removed. */
141 EMACS_INT window_min_height;
142 EMACS_INT window_min_width;
144 /* Hook run at end of temp_output_buffer_show. */
146 Lisp_Object Qtemp_buffer_show_hook;
148 /* Number of lines of continuity in scrolling by screenfuls. */
150 EMACS_INT next_screen_context_lines;
152 /* Incremented for each window created. */
154 static int sequence_number;
156 /* Nonzero after init_window_once has finished. */
158 static int window_initialized;
160 /* Hook to run when window config changes. */
162 static Lisp_Object Qwindow_configuration_change_hook;
163 static Lisp_Object Vwindow_configuration_change_hook;
165 /* Non-nil means scroll commands try to put point
166 at the same screen height as previously. */
168 Lisp_Object Vscroll_preserve_screen_position;
170 /* Non-nil means that text is inserted before window's markers. */
172 Lisp_Object Vwindow_point_insertion_type;
174 /* Incremented by 1 whenever a window is deleted. */
176 int window_deletion_count;
178 /* Used by the function window_scroll_pixel_based */
180 static int window_scroll_pixel_based_preserve_x;
181 static int window_scroll_pixel_based_preserve_y;
183 /* Same for window_scroll_line_based. */
185 static int window_scroll_preserve_hpos;
186 static int window_scroll_preserve_vpos;
188 #if 0 /* This isn't used anywhere. */
189 /* Nonzero means we can split a frame even if it is "unsplittable". */
190 static int inhibit_frame_unsplittable;
191 #endif /* 0 */
193 extern EMACS_INT scroll_margin;
195 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
197 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
198 doc: /* Return t if OBJECT is a window. */)
199 (object)
200 Lisp_Object object;
202 return WINDOWP (object) ? Qt : Qnil;
205 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
206 doc: /* Return t if OBJECT is a window which is currently visible. */)
207 (object)
208 Lisp_Object object;
210 return WINDOW_LIVE_P (object) ? Qt : Qnil;
213 Lisp_Object
214 make_window ()
216 Lisp_Object val;
217 register struct window *p;
219 p = allocate_window ();
220 ++sequence_number;
221 XSETFASTINT (p->sequence_number, sequence_number);
222 XSETFASTINT (p->left_col, 0);
223 XSETFASTINT (p->top_line, 0);
224 XSETFASTINT (p->total_lines, 0);
225 XSETFASTINT (p->total_cols, 0);
226 XSETFASTINT (p->hscroll, 0);
227 XSETFASTINT (p->min_hscroll, 0);
228 p->orig_top_line = p->orig_total_lines = Qnil;
229 p->start = Fmake_marker ();
230 p->pointm = Fmake_marker ();
231 XSETFASTINT (p->use_time, 0);
232 p->frame = Qnil;
233 p->display_table = Qnil;
234 p->dedicated = Qnil;
235 p->window_parameters = Qnil;
236 p->pseudo_window_p = 0;
237 bzero (&p->cursor, sizeof (p->cursor));
238 bzero (&p->last_cursor, sizeof (p->last_cursor));
239 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
240 p->desired_matrix = p->current_matrix = 0;
241 p->nrows_scale_factor = p->ncols_scale_factor = 1;
242 p->phys_cursor_type = -1;
243 p->phys_cursor_width = -1;
244 p->must_be_updated_p = 0;
245 XSETFASTINT (p->window_end_vpos, 0);
246 XSETFASTINT (p->window_end_pos, 0);
247 p->window_end_valid = Qnil;
248 p->vscroll = 0;
249 XSETWINDOW (val, p);
250 XSETFASTINT (p->last_point, 0);
251 p->frozen_window_start_p = 0;
252 p->last_cursor_off_p = p->cursor_off_p = 0;
253 p->left_margin_cols = Qnil;
254 p->right_margin_cols = Qnil;
255 p->left_fringe_width = Qnil;
256 p->right_fringe_width = Qnil;
257 p->fringes_outside_margins = Qnil;
258 p->scroll_bar_width = Qnil;
259 p->vertical_scroll_bar_type = Qt;
260 p->resize_proportionally = Qnil;
262 Vwindow_list = Qnil;
263 return val;
266 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
267 doc: /* Return the window that the cursor now appears in and commands apply to. */)
270 return selected_window;
273 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
274 doc: /* Return the window used now for minibuffers.
275 If the optional argument FRAME is specified, return the minibuffer window
276 used by that frame. */)
277 (frame)
278 Lisp_Object frame;
280 if (NILP (frame))
281 frame = selected_frame;
282 CHECK_LIVE_FRAME (frame);
283 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
286 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
287 doc: /* Return non-nil if WINDOW is a minibuffer window.
288 WINDOW defaults to the selected window. */)
289 (window)
290 Lisp_Object window;
292 struct window *w = decode_window (window);
293 return MINI_WINDOW_P (w) ? Qt : Qnil;
297 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
298 Spos_visible_in_window_p, 0, 3, 0,
299 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
300 Return nil if that position is scrolled vertically out of view.
301 If a character is only partially visible, nil is returned, unless the
302 optional argument PARTIALLY is non-nil.
303 If POS is only out of view because of horizontal scrolling, return non-nil.
304 If POS is t, it specifies the position of the last visible glyph in WINDOW.
305 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
307 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
308 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
309 where X and Y are the pixel coordinates relative to the top left corner
310 of the window. The remaining elements are omitted if the character after
311 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
312 off-window at the top and bottom of the row, ROWH is the height of the
313 display row, and VPOS is the row number (0-based) containing POS. */)
314 (pos, window, partially)
315 Lisp_Object pos, window, partially;
317 register struct window *w;
318 register int posint;
319 register struct buffer *buf;
320 struct text_pos top;
321 Lisp_Object in_window = Qnil;
322 int rtop, rbot, rowh, vpos, fully_p = 1;
323 int x, y;
325 w = decode_window (window);
326 buf = XBUFFER (w->buffer);
327 SET_TEXT_POS_FROM_MARKER (top, w->start);
329 if (EQ (pos, Qt))
330 posint = -1;
331 else if (!NILP (pos))
333 CHECK_NUMBER_COERCE_MARKER (pos);
334 posint = XINT (pos);
336 else if (w == XWINDOW (selected_window))
337 posint = PT;
338 else
339 posint = XMARKER (w->pointm)->charpos;
341 /* If position is above window start or outside buffer boundaries,
342 or if window start is out of range, position is not visible. */
343 if ((EQ (pos, Qt)
344 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
345 && CHARPOS (top) >= BUF_BEGV (buf)
346 && CHARPOS (top) <= BUF_ZV (buf)
347 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
348 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
349 in_window = Qt;
351 if (!NILP (in_window) && !NILP (partially))
353 Lisp_Object part = Qnil;
354 if (!fully_p)
355 part = list4 (make_number (rtop), make_number (rbot),
356 make_number (rowh), make_number (vpos));
357 in_window = Fcons (make_number (x),
358 Fcons (make_number (y), part));
361 return in_window;
364 DEFUN ("window-line-height", Fwindow_line_height,
365 Swindow_line_height, 0, 2, 0,
366 doc: /* Return height in pixels of text line LINE in window WINDOW.
367 If WINDOW is nil or omitted, use selected window.
369 Return height of current line if LINE is omitted or nil. Return height of
370 header or mode line if LINE is `header-line' and `mode-line'.
371 Otherwise, LINE is a text line number starting from 0. A negative number
372 counts from the end of the window.
374 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
375 in pixels of the visible part of the line, VPOS and YPOS are the
376 vertical position in lines and pixels of the line, relative to the top
377 of the first text line, and OFFBOT is the number of off-window pixels at
378 the bottom of the text line. If there are off-window pixels at the top
379 of the (first) text line, YPOS is negative.
381 Return nil if window display is not up-to-date. In that case, use
382 `pos-visible-in-window-p' to obtain the information. */)
383 (line, window)
384 Lisp_Object line, window;
386 register struct window *w;
387 register struct buffer *b;
388 struct glyph_row *row, *end_row;
389 int max_y, crop, i, n;
391 w = decode_window (window);
393 if (noninteractive
394 || w->pseudo_window_p)
395 return Qnil;
397 CHECK_BUFFER (w->buffer);
398 b = XBUFFER (w->buffer);
400 /* Fail if current matrix is not up-to-date. */
401 if (NILP (w->window_end_valid)
402 || current_buffer->clip_changed
403 || current_buffer->prevent_redisplay_optimizations_p
404 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
405 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
406 return Qnil;
408 if (NILP (line))
410 i = w->cursor.vpos;
411 if (i < 0 || i >= w->current_matrix->nrows
412 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
413 return Qnil;
414 max_y = window_text_bottom_y (w);
415 goto found_row;
418 if (EQ (line, Qheader_line))
420 if (!WINDOW_WANTS_HEADER_LINE_P (w))
421 return Qnil;
422 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
423 if (!row->enabled_p)
424 return Qnil;
425 return list4 (make_number (row->height),
426 make_number (0), make_number (0),
427 make_number (0));
430 if (EQ (line, Qmode_line))
432 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
433 if (!row->enabled_p)
434 return Qnil;
435 return list4 (make_number (row->height),
436 make_number (0), /* not accurate */
437 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
438 + window_text_bottom_y (w)),
439 make_number (0));
442 CHECK_NUMBER (line);
443 n = XINT (line);
445 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
446 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
447 max_y = window_text_bottom_y (w);
448 i = 0;
450 while ((n < 0 || i < n)
451 && row <= end_row && row->enabled_p
452 && row->y + row->height < max_y)
453 row++, i++;
455 if (row > end_row || !row->enabled_p)
456 return Qnil;
458 if (++n < 0)
460 if (-n > i)
461 return Qnil;
462 row += n;
463 i += n;
466 found_row:
467 crop = max (0, (row->y + row->height) - max_y);
468 return list4 (make_number (row->height + min (0, row->y) - crop),
469 make_number (i),
470 make_number (row->y),
471 make_number (crop));
476 static struct window *
477 decode_window (window)
478 register Lisp_Object window;
480 if (NILP (window))
481 return XWINDOW (selected_window);
483 CHECK_LIVE_WINDOW (window);
484 return XWINDOW (window);
487 static struct window *
488 decode_any_window (window)
489 register Lisp_Object window;
491 if (NILP (window))
492 return XWINDOW (selected_window);
494 CHECK_WINDOW (window);
495 return XWINDOW (window);
498 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
499 doc: /* Return the buffer that WINDOW is displaying.
500 WINDOW defaults to the selected window. */)
501 (window)
502 Lisp_Object window;
504 return decode_window (window)->buffer;
507 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
508 doc: /* Return the number of lines in WINDOW.
509 WINDOW defaults to the selected window.
511 The return value includes WINDOW's mode line and header line, if any. */)
512 (window)
513 Lisp_Object window;
515 return decode_any_window (window)->total_lines;
518 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
519 doc: /* Return the number of display columns in WINDOW.
520 WINDOW defaults to the selected window.
522 Note: The return value is the number of columns available for text in
523 WINDOW. If you want to find out how many columns WINDOW takes up, use
524 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
525 (window)
526 Lisp_Object window;
528 return make_number (window_box_text_cols (decode_any_window (window)));
531 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
532 doc: /* Return t if WINDOW is as wide as its frame.
533 WINDOW defaults to the selected window. */)
534 (window)
535 Lisp_Object window;
537 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
540 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
541 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
542 WINDOW defaults to the selected window. */)
543 (window)
544 Lisp_Object window;
546 return decode_window (window)->hscroll;
549 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
550 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
551 Return NCOL. NCOL should be zero or positive.
553 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
554 window so that the location of point moves off-window. */)
555 (window, ncol)
556 Lisp_Object window, ncol;
558 struct window *w = decode_window (window);
559 int hscroll;
561 CHECK_NUMBER (ncol);
562 hscroll = max (0, XINT (ncol));
564 /* Prevent redisplay shortcuts when changing the hscroll. */
565 if (XINT (w->hscroll) != hscroll)
566 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
568 w->hscroll = make_number (hscroll);
569 return ncol;
572 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
573 Swindow_redisplay_end_trigger, 0, 1, 0,
574 doc: /* Return WINDOW's redisplay end trigger value.
575 WINDOW defaults to the selected window.
576 See `set-window-redisplay-end-trigger' for more information. */)
577 (window)
578 Lisp_Object window;
580 return decode_window (window)->redisplay_end_trigger;
583 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
584 Sset_window_redisplay_end_trigger, 2, 2, 0,
585 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
586 VALUE should be a buffer position (typically a marker) or nil.
587 If it is a buffer position, then if redisplay in WINDOW reaches a position
588 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
589 with two arguments: WINDOW, and the end trigger value.
590 Afterwards the end-trigger value is reset to nil. */)
591 (window, value)
592 register Lisp_Object window, value;
594 register struct window *w;
596 w = decode_window (window);
597 w->redisplay_end_trigger = value;
598 return value;
601 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
602 doc: /* Return a list of the edge coordinates of WINDOW.
603 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
604 RIGHT is one more than the rightmost column occupied by WINDOW,
605 and BOTTOM is one more than the bottommost row occupied by WINDOW.
606 The edges include the space used by the window's scroll bar,
607 display margins, fringes, header line, and mode line, if it has them.
608 To get the edges of the actual text area, use `window-inside-edges'. */)
609 (window)
610 Lisp_Object window;
612 register struct window *w = decode_any_window (window);
614 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
615 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
616 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
617 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
618 Qnil))));
621 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
622 doc: /* Return a list of the edge pixel coordinates of WINDOW.
623 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
624 RIGHT is one more than the rightmost x position occupied by WINDOW,
625 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
626 The pixel edges include the space used by the window's scroll bar,
627 display margins, fringes, header line, and mode line, if it has them.
628 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
629 (window)
630 Lisp_Object window;
632 register struct window *w = decode_any_window (window);
634 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
635 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
636 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
637 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
638 Qnil))));
641 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
642 doc: /* Return a list of the edge coordinates of WINDOW.
643 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
644 RIGHT is one more than the rightmost column used by text in WINDOW,
645 and BOTTOM is one more than the bottommost row used by text in WINDOW.
646 The inside edges do not include the space used by the window's scroll bar,
647 display margins, fringes, header line, and/or mode line. */)
648 (window)
649 Lisp_Object window;
651 register struct window *w = decode_any_window (window);
653 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
654 + WINDOW_LEFT_MARGIN_COLS (w)
655 + WINDOW_LEFT_FRINGE_COLS (w)),
656 make_number (WINDOW_TOP_EDGE_LINE (w)
657 + WINDOW_HEADER_LINE_LINES (w)),
658 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
659 - WINDOW_RIGHT_MARGIN_COLS (w)
660 - WINDOW_RIGHT_FRINGE_COLS (w)),
661 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
662 - WINDOW_MODE_LINE_LINES (w)));
665 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
666 doc: /* Return a list of the edge pixel coordinates of WINDOW.
667 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
668 RIGHT is one more than the rightmost x position used by text in WINDOW,
669 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
670 The inside edges do not include the space used by the window's scroll bar,
671 display margins, fringes, header line, and/or mode line. */)
672 (window)
673 Lisp_Object window;
675 register struct window *w = decode_any_window (window);
677 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
678 + WINDOW_LEFT_MARGIN_WIDTH (w)
679 + WINDOW_LEFT_FRINGE_WIDTH (w)),
680 make_number (WINDOW_TOP_EDGE_Y (w)
681 + WINDOW_HEADER_LINE_HEIGHT (w)),
682 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
683 - WINDOW_RIGHT_MARGIN_WIDTH (w)
684 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
685 make_number (WINDOW_BOTTOM_EDGE_Y (w)
686 - WINDOW_MODE_LINE_HEIGHT (w)));
689 /* Test if the character at column *X, row *Y is within window W.
690 If it is not, return ON_NOTHING;
691 if it is in the window's text area,
692 set *x and *y to its location relative to the upper left corner
693 of the window, and
694 return ON_TEXT;
695 if it is on the window's modeline, return ON_MODE_LINE;
696 if it is on the border between the window and its right sibling,
697 return ON_VERTICAL_BORDER.
698 if it is on a scroll bar,
699 return ON_SCROLL_BAR.
700 if it is on the window's top line, return ON_HEADER_LINE;
701 if it is in left or right fringe of the window,
702 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
703 to window-relative coordinates;
704 if it is in the marginal area to the left/right of the window,
705 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
706 to window-relative coordinates.
708 X and Y are frame relative pixel coordinates. */
710 static enum window_part
711 coordinates_in_window (w, x, y)
712 register struct window *w;
713 register int *x, *y;
715 struct frame *f = XFRAME (WINDOW_FRAME (w));
716 int left_x, right_x, top_y, bottom_y;
717 enum window_part part;
718 int ux = FRAME_COLUMN_WIDTH (f);
719 int x0 = WINDOW_LEFT_EDGE_X (w);
720 int x1 = WINDOW_RIGHT_EDGE_X (w);
721 /* The width of the area where the vertical line can be dragged.
722 (Between mode lines for instance. */
723 int grabbable_width = ux;
724 int lmargin_width, rmargin_width, text_left, text_right;
726 /* In what's below, we subtract 1 when computing right_x because we
727 want the rightmost pixel, which is given by left_pixel+width-1. */
728 if (w->pseudo_window_p)
730 left_x = 0;
731 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
732 top_y = WINDOW_TOP_EDGE_Y (w);
733 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
735 else
737 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
738 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
739 top_y = WINDOW_TOP_EDGE_Y (w);
740 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
743 /* Outside any interesting row? */
744 if (*y < top_y || *y >= bottom_y)
745 return ON_NOTHING;
747 /* On the mode line or header line? If it's near the start of
748 the mode or header line of window that's has a horizontal
749 sibling, say it's on the vertical line. That's to be able
750 to resize windows horizontally in case we're using toolkit
751 scroll bars. */
753 if (WINDOW_WANTS_MODELINE_P (w)
754 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
756 part = ON_MODE_LINE;
758 header_vertical_border_check:
759 /* We're somewhere on the mode line. We consider the place
760 between mode lines of horizontally adjacent mode lines
761 as the vertical border. If scroll bars on the left,
762 return the right window. */
763 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
764 || WINDOW_RIGHTMOST_P (w))
766 if (!WINDOW_LEFTMOST_P (w) && eabs (*x - x0) < grabbable_width)
768 /* Convert X and Y to window relative coordinates.
769 Vertical border is at the left edge of window. */
770 *x = max (0, *x - x0);
771 *y -= top_y;
772 return ON_VERTICAL_BORDER;
775 else
777 /* Make sure we're not at the rightmost position of a
778 mode-/header-line and there's yet another window on
779 the right. (Bug#1372) */
780 if ((WINDOW_RIGHTMOST_P (w) || *x < x1)
781 && eabs (*x - x1) < grabbable_width)
783 /* Convert X and Y to window relative coordinates.
784 Vertical border is at the right edge of window. */
785 *x = min (x1, *x) - x0;
786 *y -= top_y;
787 return ON_VERTICAL_BORDER;
791 if (*x < x0 || *x >= x1)
792 return ON_NOTHING;
794 /* Convert X and Y to window relative coordinates.
795 Mode line starts at left edge of window. */
796 *x -= x0;
797 *y -= top_y;
798 return part;
801 if (WINDOW_WANTS_HEADER_LINE_P (w)
802 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
804 part = ON_HEADER_LINE;
805 goto header_vertical_border_check;
808 if (*x < x0 || *x >= x1)
809 return ON_NOTHING;
811 /* Outside any interesting column? */
812 if (*x < left_x || *x > right_x)
814 *y -= top_y;
815 return ON_SCROLL_BAR;
818 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
819 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
821 text_left = window_box_left (w, TEXT_AREA);
822 text_right = text_left + window_box_width (w, TEXT_AREA);
824 if (FRAME_WINDOW_P (f))
826 if (!w->pseudo_window_p
827 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
828 && !WINDOW_RIGHTMOST_P (w)
829 && (eabs (*x - right_x) < grabbable_width))
831 /* Convert X and Y to window relative coordinates.
832 Vertical border is at the right edge of window. */
833 *x = min (right_x, *x) - left_x;
834 *y -= top_y;
835 return ON_VERTICAL_BORDER;
838 else
840 /* Need to say "*x > right_x" rather than >=, since on character
841 terminals, the vertical line's x coordinate is right_x. */
842 if (!w->pseudo_window_p
843 && !WINDOW_RIGHTMOST_P (w)
844 && *x > right_x - ux)
846 /* On the border on the right side of the window? Assume that
847 this area begins at RIGHT_X minus a canonical char width. */
848 *x = min (right_x, *x) - left_x;
849 *y -= top_y;
850 return ON_VERTICAL_BORDER;
854 if (*x < text_left)
856 if (lmargin_width > 0
857 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
858 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
859 : (*x < left_x + lmargin_width)))
861 *x -= left_x;
862 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
863 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
864 *y -= top_y;
865 return ON_LEFT_MARGIN;
868 /* Convert X and Y to window-relative pixel coordinates. */
869 *x -= left_x;
870 *y -= top_y;
871 return ON_LEFT_FRINGE;
874 if (*x >= text_right)
876 if (rmargin_width > 0
877 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
878 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
879 : (*x >= right_x - rmargin_width)))
881 *x -= right_x - rmargin_width;
882 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
883 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
884 *y -= top_y;
885 return ON_RIGHT_MARGIN;
888 /* Convert X and Y to window-relative pixel coordinates. */
889 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
890 *y -= top_y;
891 return ON_RIGHT_FRINGE;
894 /* Everything special ruled out - must be on text area */
895 *x -= text_left;
896 *y -= top_y;
897 return ON_TEXT;
901 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
902 Scoordinates_in_window_p, 2, 2, 0,
903 doc: /* Return non-nil if COORDINATES are in WINDOW.
904 COORDINATES is a cons of the form (X . Y), X and Y being distances
905 measured in characters from the upper-left corner of the frame.
906 \(0 . 0) denotes the character in the upper left corner of the
907 frame.
908 If COORDINATES are in the text portion of WINDOW,
909 the coordinates relative to the window are returned.
910 If they are in the mode line of WINDOW, `mode-line' is returned.
911 If they are in the top mode line of WINDOW, `header-line' is returned.
912 If they are in the left fringe of WINDOW, `left-fringe' is returned.
913 If they are in the right fringe of WINDOW, `right-fringe' is returned.
914 If they are on the border between WINDOW and its right sibling,
915 `vertical-line' is returned.
916 If they are in the windows's left or right marginal areas, `left-margin'\n\
917 or `right-margin' is returned. */)
918 (coordinates, window)
919 register Lisp_Object coordinates, window;
921 struct window *w;
922 struct frame *f;
923 int x, y;
924 Lisp_Object lx, ly;
926 CHECK_WINDOW (window);
927 w = XWINDOW (window);
928 f = XFRAME (w->frame);
929 CHECK_CONS (coordinates);
930 lx = Fcar (coordinates);
931 ly = Fcdr (coordinates);
932 CHECK_NUMBER_OR_FLOAT (lx);
933 CHECK_NUMBER_OR_FLOAT (ly);
934 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
935 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
937 switch (coordinates_in_window (w, &x, &y))
939 case ON_NOTHING:
940 return Qnil;
942 case ON_TEXT:
943 /* X and Y are now window relative pixel coordinates. Convert
944 them to canonical char units before returning them. */
945 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
946 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
948 case ON_MODE_LINE:
949 return Qmode_line;
951 case ON_VERTICAL_BORDER:
952 return Qvertical_line;
954 case ON_HEADER_LINE:
955 return Qheader_line;
957 case ON_LEFT_FRINGE:
958 return Qleft_fringe;
960 case ON_RIGHT_FRINGE:
961 return Qright_fringe;
963 case ON_LEFT_MARGIN:
964 return Qleft_margin;
966 case ON_RIGHT_MARGIN:
967 return Qright_margin;
969 case ON_SCROLL_BAR:
970 /* Historically we are supposed to return nil in this case. */
971 return Qnil;
973 default:
974 abort ();
979 /* Callback for foreach_window, used in window_from_coordinates.
980 Check if window W contains coordinates specified by USER_DATA which
981 is actually a pointer to a struct check_window_data CW.
983 Check if window W contains coordinates *CW->x and *CW->y. If it
984 does, return W in *CW->window, as Lisp_Object, and return in
985 *CW->part the part of the window under coordinates *X,*Y. Return
986 zero from this function to stop iterating over windows. */
988 struct check_window_data
990 Lisp_Object *window;
991 int *x, *y;
992 enum window_part *part;
995 static int
996 check_window_containing (w, user_data)
997 struct window *w;
998 void *user_data;
1000 struct check_window_data *cw = (struct check_window_data *) user_data;
1001 enum window_part found;
1002 int continue_p = 1;
1004 found = coordinates_in_window (w, cw->x, cw->y);
1005 if (found != ON_NOTHING)
1007 *cw->part = found;
1008 XSETWINDOW (*cw->window, w);
1009 continue_p = 0;
1012 return continue_p;
1016 /* Find the window containing frame-relative pixel position X/Y and
1017 return it as a Lisp_Object.
1019 If X, Y is on one of the window's special `window_part' elements,
1020 set *PART to the id of that element, and return X and Y converted
1021 to window relative coordinates in WX and WY.
1023 If there is no window under X, Y return nil and leave *PART
1024 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1026 This function was previously implemented with a loop cycling over
1027 windows with Fnext_window, and starting with the frame's selected
1028 window. It turned out that this doesn't work with an
1029 implementation of next_window using Vwindow_list, because
1030 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1031 tree of F when this function is called asynchronously from
1032 note_mouse_highlight. The original loop didn't terminate in this
1033 case. */
1035 Lisp_Object
1036 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1037 struct frame *f;
1038 int x, y;
1039 enum window_part *part;
1040 int *wx, *wy;
1041 int tool_bar_p;
1043 Lisp_Object window;
1044 struct check_window_data cw;
1045 enum window_part dummy;
1047 if (part == 0)
1048 part = &dummy;
1050 window = Qnil;
1051 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1052 foreach_window (f, check_window_containing, &cw);
1054 /* If not found above, see if it's in the tool bar window, if a tool
1055 bar exists. */
1056 if (NILP (window)
1057 && tool_bar_p
1058 && WINDOWP (f->tool_bar_window)
1059 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1060 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1061 != ON_NOTHING))
1063 *part = ON_TEXT;
1064 window = f->tool_bar_window;
1067 if (wx) *wx = x;
1068 if (wy) *wy = y;
1070 return window;
1073 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1074 doc: /* Return window containing coordinates X and Y on FRAME.
1075 If omitted, FRAME defaults to the currently selected frame.
1076 The top left corner of the frame is considered to be row 0,
1077 column 0. */)
1078 (x, y, frame)
1079 Lisp_Object x, y, frame;
1081 struct frame *f;
1083 if (NILP (frame))
1084 frame = selected_frame;
1085 CHECK_LIVE_FRAME (frame);
1086 f = XFRAME (frame);
1088 /* Check that arguments are integers or floats. */
1089 CHECK_NUMBER_OR_FLOAT (x);
1090 CHECK_NUMBER_OR_FLOAT (y);
1092 return window_from_coordinates (f,
1093 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1094 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1095 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1096 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1097 0, 0, 0, 0);
1100 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1101 doc: /* Return current value of point in WINDOW.
1102 WINDOW defaults to the selected window.
1104 For a nonselected window, this is the value point would have
1105 if that window were selected.
1107 Note that, when WINDOW is the selected window and its buffer
1108 is also currently selected, the value returned is the same as (point).
1109 It would be more strictly correct to return the `top-level' value
1110 of point, outside of any save-excursion forms.
1111 But that is hard to define. */)
1112 (window)
1113 Lisp_Object window;
1115 register struct window *w = decode_window (window);
1117 if (w == XWINDOW (selected_window)
1118 && current_buffer == XBUFFER (w->buffer))
1119 return Fpoint ();
1120 return Fmarker_position (w->pointm);
1123 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1124 doc: /* Return position at which display currently starts in WINDOW.
1125 WINDOW defaults to the selected window.
1126 This is updated by redisplay or by calling `set-window-start'. */)
1127 (window)
1128 Lisp_Object window;
1130 return Fmarker_position (decode_window (window)->start);
1133 /* This is text temporarily removed from the doc string below.
1135 This function returns nil if the position is not currently known.
1136 That happens when redisplay is preempted and doesn't finish.
1137 If in that case you want to compute where the end of the window would
1138 have been if redisplay had finished, do this:
1139 (save-excursion
1140 (goto-char (window-start window))
1141 (vertical-motion (1- (window-height window)) window)
1142 (point))") */
1144 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1145 doc: /* Return position at which display currently ends in WINDOW.
1146 WINDOW defaults to the selected window.
1147 This is updated by redisplay, when it runs to completion.
1148 Simply changing the buffer text or setting `window-start'
1149 does not update this value.
1150 Return nil if there is no recorded value. \(This can happen if the
1151 last redisplay of WINDOW was preempted, and did not finish.)
1152 If UPDATE is non-nil, compute the up-to-date position
1153 if it isn't already recorded. */)
1154 (window, update)
1155 Lisp_Object window, update;
1157 Lisp_Object value;
1158 struct window *w = decode_window (window);
1159 Lisp_Object buf;
1160 struct buffer *b;
1162 buf = w->buffer;
1163 CHECK_BUFFER (buf);
1164 b = XBUFFER (buf);
1166 #if 0 /* This change broke some things. We should make it later. */
1167 /* If we don't know the end position, return nil.
1168 The user can compute it with vertical-motion if he wants to.
1169 It would be nicer to do it automatically,
1170 but that's so slow that it would probably bother people. */
1171 if (NILP (w->window_end_valid))
1172 return Qnil;
1173 #endif
1175 if (! NILP (update)
1176 && ! (! NILP (w->window_end_valid)
1177 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1178 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1179 && !noninteractive)
1181 struct text_pos startp;
1182 struct it it;
1183 struct buffer *old_buffer = NULL;
1185 /* Cannot use Fvertical_motion because that function doesn't
1186 cope with variable-height lines. */
1187 if (b != current_buffer)
1189 old_buffer = current_buffer;
1190 set_buffer_internal (b);
1193 /* In case W->start is out of the range, use something
1194 reasonable. This situation occurred when loading a file with
1195 `-l' containing a call to `rmail' with subsequent other
1196 commands. At the end, W->start happened to be BEG, while
1197 rmail had already narrowed the buffer. */
1198 if (XMARKER (w->start)->charpos < BEGV)
1199 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1200 else if (XMARKER (w->start)->charpos > ZV)
1201 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1202 else
1203 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1205 start_display (&it, w, startp);
1206 move_it_vertically (&it, window_box_height (w));
1207 if (it.current_y < it.last_visible_y)
1208 move_it_past_eol (&it);
1209 value = make_number (IT_CHARPOS (it));
1211 if (old_buffer)
1212 set_buffer_internal (old_buffer);
1214 else
1215 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1217 return value;
1220 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1221 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1222 Return POS. */)
1223 (window, pos)
1224 Lisp_Object window, pos;
1226 register struct window *w = decode_window (window);
1228 CHECK_NUMBER_COERCE_MARKER (pos);
1229 if (w == XWINDOW (selected_window)
1230 && XBUFFER (w->buffer) == current_buffer)
1231 Fgoto_char (pos);
1232 else
1233 set_marker_restricted (w->pointm, pos, w->buffer);
1235 /* We have to make sure that redisplay updates the window to show
1236 the new value of point. */
1237 if (!EQ (window, selected_window))
1238 ++windows_or_buffers_changed;
1240 return pos;
1243 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1244 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1245 WINDOW defaults to the selected window. Return POS.
1246 Optional third arg NOFORCE non-nil inhibits next redisplay from
1247 overriding motion of point in order to display at this exact start. */)
1248 (window, pos, noforce)
1249 Lisp_Object window, pos, noforce;
1251 register struct window *w = decode_window (window);
1253 CHECK_NUMBER_COERCE_MARKER (pos);
1254 set_marker_restricted (w->start, pos, w->buffer);
1255 /* this is not right, but much easier than doing what is right. */
1256 w->start_at_line_beg = Qnil;
1257 if (NILP (noforce))
1258 w->force_start = Qt;
1259 w->update_mode_line = Qt;
1260 XSETFASTINT (w->last_modified, 0);
1261 XSETFASTINT (w->last_overlay_modified, 0);
1262 if (!EQ (window, selected_window))
1263 windows_or_buffers_changed++;
1265 return pos;
1269 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1270 0, 1, 0,
1271 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1272 More precisely, return the value assigned by the last call of
1273 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1274 never called with WINDOW as its argument, or the value set by that
1275 function was internally reset since its last call. WINDOW defaults to
1276 the selected window.
1278 When a window is dedicated to its buffer, `display-buffer' will refrain
1279 from displaying another buffer in it. `get-lru-window' and
1280 `get-largest-window' treat dedicated windows specially.
1281 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1282 `kill-buffer' can delete a dedicated window and the containing frame.
1284 Functions like `set-window-buffer' may change the buffer displayed by a
1285 window, unless that window is "strongly" dedicated to its buffer, that
1286 is the value returned by `window-dedicated-p' is t. */)
1287 (window)
1288 Lisp_Object window;
1290 return decode_window (window)->dedicated;
1293 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1294 Sset_window_dedicated_p, 2, 2, 0,
1295 doc: /* Mark WINDOW as dedicated according to FLAG.
1296 WINDOW defaults to the selected window. FLAG non-nil means mark WINDOW
1297 as dedicated to its buffer. FLAG nil means mark WINDOW as non-dedicated.
1298 Return FLAG.
1300 When a window is dedicated to its buffer, `display-buffer' will refrain
1301 from displaying another buffer in it. `get-lru-window' and
1302 `get-largest-window' treat dedicated windows specially.
1303 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1304 `kill-buffer' can delete a dedicated window and the containing
1305 frame.
1307 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1308 its buffer. Functions like `set-window-buffer' may change the buffer
1309 displayed by a window, unless that window is strongly dedicated to its
1310 buffer. If and when `set-window-buffer' displays another buffer in a
1311 window, it also makes sure that the window is not marked as dedicated. */)
1312 (window, flag)
1313 Lisp_Object window, flag;
1315 register struct window *w = decode_window (window);
1317 w->dedicated = flag;
1318 return w->dedicated;
1322 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1323 0, 1, 0,
1324 doc: /* Return the parameters of WINDOW and their values.
1325 WINDOW defaults to the selected window. The return value is a list of
1326 elements of the form (PARAMETER . VALUE). */)
1327 (window)
1328 Lisp_Object window;
1330 return Fcopy_alist (decode_window (window)->window_parameters);
1333 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1334 2, 2, 0,
1335 doc: /* Return WINDOW's value for PARAMETER.
1336 WINDOW defaults to the selected window. */)
1337 (window, parameter)
1338 Lisp_Object window, parameter;
1340 Lisp_Object result;
1342 result = Fassq (parameter, decode_window (window)->window_parameters);
1343 return CDR_SAFE (result);
1346 DEFUN ("set-window-parameter", Fset_window_parameter,
1347 Sset_window_parameter, 3, 3, 0,
1348 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1349 WINDOW defaults to the selected window. Return VALUE. */)
1350 (window, parameter, value)
1351 Lisp_Object window, parameter, value;
1353 register struct window *w = decode_window (window);
1354 Lisp_Object old_alist_elt;
1356 old_alist_elt = Fassq (parameter, w->window_parameters);
1357 if (NILP (old_alist_elt))
1358 w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
1359 else
1360 Fsetcdr (old_alist_elt, value);
1361 return value;
1365 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1366 0, 1, 0,
1367 doc: /* Return the display-table that WINDOW is using.
1368 WINDOW defaults to the selected window. */)
1369 (window)
1370 Lisp_Object window;
1372 return decode_window (window)->display_table;
1375 /* Get the display table for use on window W. This is either W's
1376 display table or W's buffer's display table. Ignore the specified
1377 tables if they are not valid; if no valid table is specified,
1378 return 0. */
1380 struct Lisp_Char_Table *
1381 window_display_table (w)
1382 struct window *w;
1384 struct Lisp_Char_Table *dp = NULL;
1386 if (DISP_TABLE_P (w->display_table))
1387 dp = XCHAR_TABLE (w->display_table);
1388 else if (BUFFERP (w->buffer))
1390 struct buffer *b = XBUFFER (w->buffer);
1392 if (DISP_TABLE_P (b->display_table))
1393 dp = XCHAR_TABLE (b->display_table);
1394 else if (DISP_TABLE_P (Vstandard_display_table))
1395 dp = XCHAR_TABLE (Vstandard_display_table);
1398 return dp;
1401 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1402 doc: /* Set WINDOW's display-table to TABLE. */)
1403 (window, table)
1404 register Lisp_Object window, table;
1406 register struct window *w;
1408 w = decode_window (window);
1409 w->display_table = table;
1410 return table;
1413 /* Record info on buffer window w is displaying
1414 when it is about to cease to display that buffer. */
1415 static void
1416 unshow_buffer (w)
1417 register struct window *w;
1419 Lisp_Object buf;
1420 struct buffer *b;
1422 buf = w->buffer;
1423 b = XBUFFER (buf);
1424 if (b != XMARKER (w->pointm)->buffer)
1425 abort ();
1427 #if 0
1428 if (w == XWINDOW (selected_window)
1429 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1430 /* Do this except when the selected window's buffer
1431 is being removed from some other window. */
1432 #endif
1433 /* last_window_start records the start position that this buffer
1434 had in the last window to be disconnected from it.
1435 Now that this statement is unconditional,
1436 it is possible for the buffer to be displayed in the
1437 selected window, while last_window_start reflects another
1438 window which was recently showing the same buffer.
1439 Some people might say that might be a good thing. Let's see. */
1440 b->last_window_start = marker_position (w->start);
1442 /* Point in the selected window's buffer
1443 is actually stored in that buffer, and the window's pointm isn't used.
1444 So don't clobber point in that buffer. */
1445 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1446 /* This line helps to fix Horsley's testbug.el bug. */
1447 && !(WINDOWP (b->last_selected_window)
1448 && w != XWINDOW (b->last_selected_window)
1449 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1450 temp_set_point_both (b,
1451 clip_to_bounds (BUF_BEGV (b),
1452 XMARKER (w->pointm)->charpos,
1453 BUF_ZV (b)),
1454 clip_to_bounds (BUF_BEGV_BYTE (b),
1455 marker_byte_position (w->pointm),
1456 BUF_ZV_BYTE (b)));
1458 if (WINDOWP (b->last_selected_window)
1459 && w == XWINDOW (b->last_selected_window))
1460 b->last_selected_window = Qnil;
1463 /* Put replacement into the window structure in place of old. */
1464 static void
1465 replace_window (old, replacement)
1466 Lisp_Object old, replacement;
1468 register Lisp_Object tem;
1469 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1471 /* If OLD is its frame's root_window, then replacement is the new
1472 root_window for that frame. */
1474 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1475 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1477 p->left_col = o->left_col;
1478 p->top_line = o->top_line;
1479 p->total_cols = o->total_cols;
1480 p->total_lines = o->total_lines;
1481 p->desired_matrix = p->current_matrix = 0;
1482 p->vscroll = 0;
1483 bzero (&p->cursor, sizeof (p->cursor));
1484 bzero (&p->last_cursor, sizeof (p->last_cursor));
1485 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1486 p->phys_cursor_type = -1;
1487 p->phys_cursor_width = -1;
1488 p->must_be_updated_p = 0;
1489 p->pseudo_window_p = 0;
1490 XSETFASTINT (p->window_end_vpos, 0);
1491 XSETFASTINT (p->window_end_pos, 0);
1492 p->window_end_valid = Qnil;
1493 p->frozen_window_start_p = 0;
1494 p->orig_top_line = p->orig_total_lines = Qnil;
1496 p->next = tem = o->next;
1497 if (!NILP (tem))
1498 XWINDOW (tem)->prev = replacement;
1500 p->prev = tem = o->prev;
1501 if (!NILP (tem))
1502 XWINDOW (tem)->next = replacement;
1504 p->parent = tem = o->parent;
1505 if (!NILP (tem))
1507 if (EQ (XWINDOW (tem)->vchild, old))
1508 XWINDOW (tem)->vchild = replacement;
1509 if (EQ (XWINDOW (tem)->hchild, old))
1510 XWINDOW (tem)->hchild = replacement;
1513 /*** Here, if replacement is a vertical combination
1514 and so is its new parent, we should make replacement's
1515 children be children of that parent instead. ***/
1518 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1519 doc: /* Remove WINDOW from its frame.
1520 WINDOW defaults to the selected window. Return nil.
1521 Signal an error when WINDOW is the only window on its frame. */)
1522 (window)
1523 register Lisp_Object window;
1525 struct frame *f;
1526 if (NILP (window))
1527 window = selected_window;
1528 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1529 delete_window (window);
1531 run_window_configuration_change_hook (f);
1533 return Qnil;
1536 void
1537 delete_window (window)
1538 register Lisp_Object window;
1540 register Lisp_Object tem, parent, sib;
1541 register struct window *p;
1542 register struct window *par;
1543 struct frame *f;
1545 /* Because this function is called by other C code on non-leaf
1546 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1547 so we can't decode_window here. */
1548 CHECK_WINDOW (window);
1549 p = XWINDOW (window);
1551 /* It's a no-op to delete an already-deleted window. */
1552 if (NILP (p->buffer)
1553 && NILP (p->hchild)
1554 && NILP (p->vchild))
1555 return;
1557 parent = p->parent;
1558 if (NILP (parent))
1559 error ("Attempt to delete minibuffer or sole ordinary window");
1560 par = XWINDOW (parent);
1562 windows_or_buffers_changed++;
1563 Vwindow_list = Qnil;
1564 f = XFRAME (WINDOW_FRAME (p));
1565 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1567 /* Are we trying to delete any frame's selected window? */
1569 Lisp_Object swindow, pwindow;
1571 /* See if the frame's selected window is either WINDOW
1572 or any subwindow of it, by finding all that window's parents
1573 and comparing each one with WINDOW. */
1574 swindow = FRAME_SELECTED_WINDOW (f);
1576 while (1)
1578 pwindow = swindow;
1579 while (!NILP (pwindow))
1581 if (EQ (window, pwindow))
1582 break;
1583 pwindow = XWINDOW (pwindow)->parent;
1586 /* If the window being deleted is not a parent of SWINDOW,
1587 then SWINDOW is ok as the new selected window. */
1588 if (!EQ (window, pwindow))
1589 break;
1590 /* Otherwise, try another window for SWINDOW. */
1591 swindow = Fnext_window (swindow, Qlambda, Qnil);
1593 /* If we get back to the frame's selected window,
1594 it means there was no acceptable alternative,
1595 so we cannot delete. */
1596 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1597 error ("Cannot delete window");
1600 /* If we need to change SWINDOW, do it. */
1601 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1603 /* If we're about to delete the selected window on the
1604 selected frame, then we should use Fselect_window to select
1605 the new window. On the other hand, if we're about to
1606 delete the selected window on any other frame, we shouldn't do
1607 anything but set the frame's selected_window slot. */
1608 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1609 Fselect_window (swindow, Qnil);
1610 else
1611 FRAME_SELECTED_WINDOW (f) = swindow;
1615 /* Now we know we can delete this one. */
1616 window_deletion_count++;
1618 tem = p->buffer;
1619 /* tem is null for dummy parent windows
1620 (which have inferiors but not any contents themselves) */
1621 if (!NILP (tem))
1623 unshow_buffer (p);
1624 unchain_marker (XMARKER (p->pointm));
1625 unchain_marker (XMARKER (p->start));
1628 /* Free window glyph matrices. It is sure that they are allocated
1629 again when ADJUST_GLYPHS is called. Block input so that expose
1630 events and other events that access glyph matrices are not
1631 processed while we are changing them. */
1632 BLOCK_INPUT;
1633 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1635 tem = p->next;
1636 if (!NILP (tem))
1637 XWINDOW (tem)->prev = p->prev;
1639 tem = p->prev;
1640 if (!NILP (tem))
1641 XWINDOW (tem)->next = p->next;
1643 if (EQ (window, par->hchild))
1644 par->hchild = p->next;
1645 if (EQ (window, par->vchild))
1646 par->vchild = p->next;
1648 /* Find one of our siblings to give our space to. */
1649 sib = p->prev;
1650 if (NILP (sib))
1652 /* If p gives its space to its next sibling, that sibling needs
1653 to have its top/left side pulled back to where p's is.
1654 set_window_{height,width} will re-position the sibling's
1655 children. */
1656 sib = p->next;
1657 XWINDOW (sib)->top_line = p->top_line;
1658 XWINDOW (sib)->left_col = p->left_col;
1661 /* Stretch that sibling. */
1662 if (!NILP (par->vchild))
1663 set_window_height (sib,
1664 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1666 if (!NILP (par->hchild))
1667 set_window_width (sib,
1668 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1671 /* If parent now has only one child,
1672 put the child into the parent's place. */
1673 tem = par->hchild;
1674 if (NILP (tem))
1675 tem = par->vchild;
1676 if (NILP (XWINDOW (tem)->next)) {
1677 replace_window (parent, tem);
1678 par = XWINDOW (tem);
1681 /* Since we may be deleting combination windows, we must make sure that
1682 not only p but all its children have been marked as deleted. */
1683 if (! NILP (p->hchild))
1684 delete_all_subwindows (XWINDOW (p->hchild));
1685 else if (! NILP (p->vchild))
1686 delete_all_subwindows (XWINDOW (p->vchild));
1688 /* Mark this window as deleted. */
1689 p->buffer = p->hchild = p->vchild = Qnil;
1691 if (! NILP (par->parent))
1692 par = XWINDOW (par->parent);
1694 /* Check if we have a v/hchild with a v/hchild. In that case remove
1695 one of them. */
1697 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1699 p = XWINDOW (par->vchild);
1700 par->vchild = p->vchild;
1701 tem = p->vchild;
1703 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1705 p = XWINDOW (par->hchild);
1706 par->hchild = p->hchild;
1707 tem = p->hchild;
1709 else
1710 p = 0;
1712 if (p)
1714 while (! NILP (tem)) {
1715 XWINDOW (tem)->parent = p->parent;
1716 if (NILP (XWINDOW (tem)->next))
1717 break;
1718 tem = XWINDOW (tem)->next;
1720 if (! NILP (tem)) {
1721 /* The next of the v/hchild we are removing is now the next of the
1722 last child for the v/hchild:
1723 Before v/hchild -> v/hchild -> next1 -> next2
1725 -> next3
1726 After: v/hchild -> next1 -> next2 -> next3
1728 XWINDOW (tem)->next = p->next;
1729 if (! NILP (p->next))
1730 XWINDOW (p->next)->prev = tem;
1732 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1736 /* Adjust glyph matrices. */
1737 adjust_glyphs (f);
1738 UNBLOCK_INPUT;
1743 /***********************************************************************
1744 Window List
1745 ***********************************************************************/
1747 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1748 pointer. This is a callback function for foreach_window, used in
1749 function window_list. */
1751 static int
1752 add_window_to_list (w, user_data)
1753 struct window *w;
1754 void *user_data;
1756 Lisp_Object *list = (Lisp_Object *) user_data;
1757 Lisp_Object window;
1758 XSETWINDOW (window, w);
1759 *list = Fcons (window, *list);
1760 return 1;
1764 /* Return a list of all windows, for use by next_window. If
1765 Vwindow_list is a list, return that list. Otherwise, build a new
1766 list, cache it in Vwindow_list, and return that. */
1768 static Lisp_Object
1769 window_list ()
1771 if (!CONSP (Vwindow_list))
1773 Lisp_Object tail;
1775 Vwindow_list = Qnil;
1776 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1778 Lisp_Object args[2];
1780 /* We are visiting windows in canonical order, and add
1781 new windows at the front of args[1], which means we
1782 have to reverse this list at the end. */
1783 args[1] = Qnil;
1784 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1785 args[0] = Vwindow_list;
1786 args[1] = Fnreverse (args[1]);
1787 Vwindow_list = Fnconc (2, args);
1791 return Vwindow_list;
1795 /* Value is non-zero if WINDOW satisfies the constraints given by
1796 OWINDOW, MINIBUF and ALL_FRAMES.
1798 MINIBUF t means WINDOW may be minibuffer windows.
1799 `lambda' means WINDOW may not be a minibuffer window.
1800 a window means a specific minibuffer window
1802 ALL_FRAMES t means search all frames,
1803 nil means search just current frame,
1804 `visible' means search just visible frames,
1805 0 means search visible and iconified frames,
1806 a window means search the frame that window belongs to,
1807 a frame means consider windows on that frame, only. */
1809 static int
1810 candidate_window_p (window, owindow, minibuf, all_frames)
1811 Lisp_Object window, owindow, minibuf, all_frames;
1813 struct window *w = XWINDOW (window);
1814 struct frame *f = XFRAME (w->frame);
1815 int candidate_p = 1;
1817 if (!BUFFERP (w->buffer))
1818 candidate_p = 0;
1819 else if (MINI_WINDOW_P (w)
1820 && (EQ (minibuf, Qlambda)
1821 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1823 /* If MINIBUF is `lambda' don't consider any mini-windows.
1824 If it is a window, consider only that one. */
1825 candidate_p = 0;
1827 else if (EQ (all_frames, Qt))
1828 candidate_p = 1;
1829 else if (NILP (all_frames))
1831 xassert (WINDOWP (owindow));
1832 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1834 else if (EQ (all_frames, Qvisible))
1836 FRAME_SAMPLE_VISIBILITY (f);
1837 candidate_p = FRAME_VISIBLE_P (f)
1838 && (FRAME_TERMINAL (XFRAME (w->frame))
1839 == FRAME_TERMINAL (XFRAME (selected_frame)));
1842 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1844 FRAME_SAMPLE_VISIBILITY (f);
1845 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
1846 #ifdef HAVE_X_WINDOWS
1847 /* Yuck!! If we've just created the frame and the
1848 window-manager requested the user to place it
1849 manually, the window may still not be considered
1850 `visible'. I'd argue it should be at least
1851 something like `iconified', but don't know how to do
1852 that yet. --Stef */
1853 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
1854 && !f->output_data.x->has_been_visible)
1855 #endif
1857 && (FRAME_TERMINAL (XFRAME (w->frame))
1858 == FRAME_TERMINAL (XFRAME (selected_frame)));
1860 else if (WINDOWP (all_frames))
1861 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1862 || EQ (XWINDOW (all_frames)->frame, w->frame)
1863 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1864 else if (FRAMEP (all_frames))
1865 candidate_p = EQ (all_frames, w->frame);
1867 return candidate_p;
1871 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1872 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1873 ALL_FRAMES. */
1875 static void
1876 decode_next_window_args (window, minibuf, all_frames)
1877 Lisp_Object *window, *minibuf, *all_frames;
1879 if (NILP (*window))
1880 *window = selected_window;
1881 else
1882 CHECK_LIVE_WINDOW (*window);
1884 /* MINIBUF nil may or may not include minibuffers. Decide if it
1885 does. */
1886 if (NILP (*minibuf))
1887 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1888 else if (!EQ (*minibuf, Qt))
1889 *minibuf = Qlambda;
1891 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1892 => count none of them, or a specific minibuffer window (the
1893 active one) to count. */
1895 /* ALL_FRAMES nil doesn't specify which frames to include. */
1896 if (NILP (*all_frames))
1897 *all_frames = (!EQ (*minibuf, Qlambda)
1898 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1899 : Qnil);
1900 else if (EQ (*all_frames, Qvisible))
1902 else if (EQ (*all_frames, make_number (0)))
1904 else if (FRAMEP (*all_frames))
1906 else if (!EQ (*all_frames, Qt))
1907 *all_frames = Qnil;
1909 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1910 search just current frame, `visible' meaning search just visible
1911 frames, 0 meaning search visible and iconified frames, or a
1912 window, meaning search the frame that window belongs to, or a
1913 frame, meaning consider windows on that frame, only. */
1917 /* Return the next or previous window of WINDOW in cyclic ordering
1918 of windows. NEXT_P non-zero means return the next window. See the
1919 documentation string of next-window for the meaning of MINIBUF and
1920 ALL_FRAMES. */
1922 static Lisp_Object
1923 next_window (window, minibuf, all_frames, next_p)
1924 Lisp_Object window, minibuf, all_frames;
1925 int next_p;
1927 decode_next_window_args (&window, &minibuf, &all_frames);
1929 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1930 return the first window on the frame. */
1931 if (FRAMEP (all_frames)
1932 && !EQ (all_frames, XWINDOW (window)->frame))
1933 return Fframe_first_window (all_frames);
1935 if (next_p)
1937 Lisp_Object list;
1939 /* Find WINDOW in the list of all windows. */
1940 list = Fmemq (window, window_list ());
1942 /* Scan forward from WINDOW to the end of the window list. */
1943 if (CONSP (list))
1944 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1945 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1946 break;
1948 /* Scan from the start of the window list up to WINDOW. */
1949 if (!CONSP (list))
1950 for (list = Vwindow_list;
1951 CONSP (list) && !EQ (XCAR (list), window);
1952 list = XCDR (list))
1953 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1954 break;
1956 if (CONSP (list))
1957 window = XCAR (list);
1959 else
1961 Lisp_Object candidate, list;
1963 /* Scan through the list of windows for candidates. If there are
1964 candidate windows in front of WINDOW, the last one of these
1965 is the one we want. If there are candidates following WINDOW
1966 in the list, again the last one of these is the one we want. */
1967 candidate = Qnil;
1968 for (list = window_list (); CONSP (list); list = XCDR (list))
1970 if (EQ (XCAR (list), window))
1972 if (WINDOWP (candidate))
1973 break;
1975 else if (candidate_window_p (XCAR (list), window, minibuf,
1976 all_frames))
1977 candidate = XCAR (list);
1980 if (WINDOWP (candidate))
1981 window = candidate;
1984 return window;
1988 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1989 doc: /* Return window following WINDOW in cyclic ordering of windows.
1990 WINDOW defaults to the selected window. The optional arguments
1991 MINIBUF and ALL-FRAMES specify the set of windows to consider.
1993 MINIBUF t means consider the minibuffer window even if the
1994 minibuffer is not active. MINIBUF nil or omitted means consider
1995 the minibuffer window only if the minibuffer is active. Any
1996 other value means do not consider the minibuffer window even if
1997 the minibuffer is active.
1999 Several frames may share a single minibuffer; if the minibuffer
2000 is active, all windows on all frames that share that minibuffer
2001 are considered too. Therefore, if you are using a separate
2002 minibuffer frame and the minibuffer is active and MINIBUF says it
2003 counts, `next-window' considers the windows in the frame from
2004 which you entered the minibuffer, as well as the minibuffer
2005 window.
2007 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
2008 frame, plus the minibuffer window if specified by the MINIBUF
2009 argument, see above. If the minibuffer counts, consider all
2010 windows on all frames that share that minibuffer too.
2011 ALL-FRAMES t means consider all windows on all existing frames.
2012 ALL-FRAMES `visible' means consider all windows on all visible
2013 frames.
2014 ALL-FRAMES 0 means consider all windows on all visible and
2015 iconified frames.
2016 ALL-FRAMES a frame means consider all windows on that frame only.
2017 Anything else means consider all windows on WINDOW's frame and no
2018 others.
2020 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2021 `next-window' to iterate through the entire cycle of acceptable
2022 windows, eventually ending up back at the window you started with.
2023 `previous-window' traverses the same cycle, in the reverse order. */)
2024 (window, minibuf, all_frames)
2025 Lisp_Object window, minibuf, all_frames;
2027 return next_window (window, minibuf, all_frames, 1);
2031 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2032 doc: /* Return window preceding WINDOW in cyclic ordering of windows.
2033 WINDOW defaults to the selected window. The optional arguments
2034 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2035 For the precise meaning of these arguments see `next-window'.
2037 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2038 use `previous-window' to iterate through the entire cycle of
2039 acceptable windows, eventually ending up back at the window you
2040 started with. `next-window' traverses the same cycle, in the
2041 reverse order. */)
2042 (window, minibuf, all_frames)
2043 Lisp_Object window, minibuf, all_frames;
2045 return next_window (window, minibuf, all_frames, 0);
2049 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2050 doc: /* Select another window in cyclic ordering of windows.
2051 COUNT specifies the number of windows to skip, starting with the
2052 selected window, before making the selection. If COUNT is
2053 positive, skip COUNT windows forwards. If COUNT is negative,
2054 skip -COUNT windows backwards. COUNT zero means do not skip any
2055 window, so select the selected window. In an interactive call,
2056 COUNT is the numeric prefix argument. Return nil.
2058 This function uses `next-window' for finding the window to select.
2059 The argument ALL-FRAMES has the same meaning as in `next-window',
2060 but the MINIBUF argument of `next-window' is always effectively
2061 nil. */)
2062 (count, all_frames)
2063 Lisp_Object count, all_frames;
2065 Lisp_Object window;
2066 int i;
2068 CHECK_NUMBER (count);
2069 window = selected_window;
2071 for (i = XINT (count); i > 0; --i)
2072 window = Fnext_window (window, Qnil, all_frames);
2073 for (; i < 0; ++i)
2074 window = Fprevious_window (window, Qnil, all_frames);
2076 Fselect_window (window, Qnil);
2077 return Qnil;
2081 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2082 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2083 FRAME nil or omitted means use the selected frame.
2084 WINDOW nil or omitted means use the selected window.
2085 MINIBUF t means include the minibuffer window, even if it isn't active.
2086 MINIBUF nil or omitted means include the minibuffer window only
2087 if it's active.
2088 MINIBUF neither nil nor t means never include the minibuffer window. */)
2089 (frame, minibuf, window)
2090 Lisp_Object frame, minibuf, window;
2092 if (NILP (window))
2093 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2094 CHECK_WINDOW (window);
2095 if (NILP (frame))
2096 frame = selected_frame;
2098 if (!EQ (frame, XWINDOW (window)->frame))
2099 error ("Window is on a different frame");
2101 return window_list_1 (window, minibuf, frame);
2105 /* Return a list of windows in cyclic ordering. Arguments are like
2106 for `next-window'. */
2108 static Lisp_Object
2109 window_list_1 (window, minibuf, all_frames)
2110 Lisp_Object window, minibuf, all_frames;
2112 Lisp_Object tail, list, rest;
2114 decode_next_window_args (&window, &minibuf, &all_frames);
2115 list = Qnil;
2117 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2118 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2119 list = Fcons (XCAR (tail), list);
2121 /* Rotate the list to start with WINDOW. */
2122 list = Fnreverse (list);
2123 rest = Fmemq (window, list);
2124 if (!NILP (rest) && !EQ (rest, list))
2126 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2128 XSETCDR (tail, Qnil);
2129 list = nconc2 (rest, list);
2131 return list;
2136 /* Look at all windows, performing an operation specified by TYPE
2137 with argument OBJ.
2138 If FRAMES is Qt, look at all frames;
2139 Qnil, look at just the selected frame;
2140 Qvisible, look at visible frames;
2141 a frame, just look at windows on that frame.
2142 If MINI is non-zero, perform the operation on minibuffer windows too. */
2144 enum window_loop
2146 WINDOW_LOOP_UNUSED,
2147 GET_BUFFER_WINDOW, /* Arg is buffer */
2148 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2149 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2150 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2151 GET_LARGEST_WINDOW,
2152 UNSHOW_BUFFER, /* Arg is buffer */
2153 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2154 CHECK_ALL_WINDOWS
2157 static Lisp_Object
2158 window_loop (type, obj, mini, frames)
2159 enum window_loop type;
2160 Lisp_Object obj, frames;
2161 int mini;
2163 Lisp_Object window, windows, best_window, frame_arg;
2164 struct frame *f;
2165 struct gcpro gcpro1;
2167 /* If we're only looping through windows on a particular frame,
2168 frame points to that frame. If we're looping through windows
2169 on all frames, frame is 0. */
2170 if (FRAMEP (frames))
2171 f = XFRAME (frames);
2172 else if (NILP (frames))
2173 f = SELECTED_FRAME ();
2174 else
2175 f = NULL;
2177 if (f)
2178 frame_arg = Qlambda;
2179 else if (EQ (frames, make_number (0)))
2180 frame_arg = frames;
2181 else if (EQ (frames, Qvisible))
2182 frame_arg = frames;
2183 else
2184 frame_arg = Qt;
2186 /* frame_arg is Qlambda to stick to one frame,
2187 Qvisible to consider all visible frames,
2188 or Qt otherwise. */
2190 /* Pick a window to start with. */
2191 if (WINDOWP (obj))
2192 window = obj;
2193 else if (f)
2194 window = FRAME_SELECTED_WINDOW (f);
2195 else
2196 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2198 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2199 GCPRO1 (windows);
2200 best_window = Qnil;
2202 for (; CONSP (windows); windows = XCDR (windows))
2204 struct window *w;
2206 window = XCAR (windows);
2207 w = XWINDOW (window);
2209 /* Note that we do not pay attention here to whether the frame
2210 is visible, since Fwindow_list skips non-visible frames if
2211 that is desired, under the control of frame_arg. */
2212 if (!MINI_WINDOW_P (w)
2213 /* For UNSHOW_BUFFER, we must always consider all windows. */
2214 || type == UNSHOW_BUFFER
2215 || (mini && minibuf_level > 0))
2216 switch (type)
2218 case GET_BUFFER_WINDOW:
2219 if (EQ (w->buffer, obj)
2220 /* Don't find any minibuffer window
2221 except the one that is currently in use. */
2222 && (MINI_WINDOW_P (w)
2223 ? EQ (window, minibuf_window)
2224 : 1))
2226 if (NILP (best_window))
2227 best_window = window;
2228 else if (EQ (window, selected_window))
2229 /* Prefer to return selected-window. */
2230 RETURN_UNGCPRO (window);
2231 else if (EQ (Fwindow_frame (window), selected_frame))
2232 /* Prefer windows on the current frame. */
2233 best_window = window;
2235 break;
2237 case GET_LRU_WINDOW:
2238 /* `obj' is an integer encoding a bitvector.
2239 `obj & 1' means consider only full-width windows.
2240 `obj & 2' means consider also dedicated windows. */
2241 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2242 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2243 /* Minibuffer windows are always ignored. */
2244 || MINI_WINDOW_P (w))
2245 break;
2246 if (NILP (best_window)
2247 || (XFASTINT (XWINDOW (best_window)->use_time)
2248 > XFASTINT (w->use_time)))
2249 best_window = window;
2250 break;
2252 case DELETE_OTHER_WINDOWS:
2253 if (!EQ (window, obj))
2254 Fdelete_window (window);
2255 break;
2257 case DELETE_BUFFER_WINDOWS:
2258 if (EQ (w->buffer, obj))
2260 struct frame *f = XFRAME (WINDOW_FRAME (w));
2262 /* If this window is dedicated, and in a frame of its own,
2263 kill the frame. */
2264 if (EQ (window, FRAME_ROOT_WINDOW (f))
2265 && !NILP (w->dedicated)
2266 && other_visible_frames (f))
2268 /* Skip the other windows on this frame.
2269 There might be one, the minibuffer! */
2270 while (CONSP (XCDR (windows))
2271 && EQ (XWINDOW (XCAR (windows))->frame,
2272 XWINDOW (XCAR (XCDR (windows)))->frame))
2273 windows = XCDR (windows);
2275 /* Now we can safely delete the frame. */
2276 delete_frame (w->frame, Qnil);
2278 else if (NILP (w->parent))
2280 /* If we're deleting the buffer displayed in the
2281 only window on the frame, find a new buffer to
2282 display there. */
2283 Lisp_Object buffer;
2284 buffer = Fother_buffer (obj, Qnil, w->frame);
2285 /* Reset dedicated state of window. */
2286 w->dedicated = Qnil;
2287 Fset_window_buffer (window, buffer, Qnil);
2288 if (EQ (window, selected_window))
2289 Fset_buffer (w->buffer);
2291 else
2292 Fdelete_window (window);
2294 break;
2296 case GET_LARGEST_WINDOW:
2297 { /* nil `obj' means to ignore dedicated windows. */
2298 /* Ignore dedicated windows and minibuffers. */
2299 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2300 break;
2302 if (NILP (best_window))
2303 best_window = window;
2304 else
2306 struct window *b = XWINDOW (best_window);
2307 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2308 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2309 best_window = window;
2312 break;
2314 case UNSHOW_BUFFER:
2315 if (EQ (w->buffer, obj))
2317 Lisp_Object buffer;
2318 struct frame *f = XFRAME (w->frame);
2320 /* Find another buffer to show in this window. */
2321 buffer = Fother_buffer (obj, Qnil, w->frame);
2323 /* If this window is dedicated, and in a frame of its own,
2324 kill the frame. */
2325 if (EQ (window, FRAME_ROOT_WINDOW (f))
2326 && !NILP (w->dedicated)
2327 && other_visible_frames (f))
2329 /* Skip the other windows on this frame.
2330 There might be one, the minibuffer! */
2331 while (CONSP (XCDR (windows))
2332 && EQ (XWINDOW (XCAR (windows))->frame,
2333 XWINDOW (XCAR (XCDR (windows)))->frame))
2334 windows = XCDR (windows);
2336 /* Now we can safely delete the frame. */
2337 delete_frame (w->frame, Qnil);
2339 else if (!NILP (w->dedicated) && !NILP (w->parent))
2341 Lisp_Object window;
2342 XSETWINDOW (window, w);
2343 /* If this window is dedicated and not the only window
2344 in its frame, then kill it. */
2345 Fdelete_window (window);
2347 else
2349 /* Otherwise show a different buffer in the window. */
2350 w->dedicated = Qnil;
2351 Fset_window_buffer (window, buffer, Qnil);
2352 if (EQ (window, selected_window))
2353 Fset_buffer (w->buffer);
2356 break;
2358 case REDISPLAY_BUFFER_WINDOWS:
2359 if (EQ (w->buffer, obj))
2361 mark_window_display_accurate (window, 0);
2362 w->update_mode_line = Qt;
2363 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2364 ++update_mode_lines;
2365 best_window = window;
2367 break;
2369 /* Check for a window that has a killed buffer. */
2370 case CHECK_ALL_WINDOWS:
2371 if (! NILP (w->buffer)
2372 && NILP (XBUFFER (w->buffer)->name))
2373 abort ();
2374 break;
2376 case WINDOW_LOOP_UNUSED:
2377 break;
2381 UNGCPRO;
2382 return best_window;
2385 /* Used for debugging. Abort if any window has a dead buffer. */
2387 void
2388 check_all_windows ()
2390 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2393 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2394 doc: /* Return the window least recently selected or used for display.
2395 \(LRU means Least Recently Used.)
2397 Return a full-width window if possible.
2398 A minibuffer window is never a candidate.
2399 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2400 so if all windows are dedicated, the value is nil.
2401 If optional argument FRAME is `visible', search all visible frames.
2402 If FRAME is 0, search all visible and iconified frames.
2403 If FRAME is t, search all frames.
2404 If FRAME is nil, search only the selected frame.
2405 If FRAME is a frame, search only that frame. */)
2406 (frame, dedicated)
2407 Lisp_Object frame, dedicated;
2409 register Lisp_Object w;
2410 /* First try for a window that is full-width */
2411 w = window_loop (GET_LRU_WINDOW,
2412 NILP (dedicated) ? make_number (1) : make_number (3),
2413 0, frame);
2414 if (!NILP (w) && !EQ (w, selected_window))
2415 return w;
2416 /* If none of them, try the rest */
2417 return window_loop (GET_LRU_WINDOW,
2418 NILP (dedicated) ? make_number (0) : make_number (2),
2419 0, frame);
2422 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2423 doc: /* Return the largest window in area.
2424 A minibuffer window is never a candidate.
2425 A dedicated window is never a candidate unless DEDICATED is non-nil,
2426 so if all windows are dedicated, the value is nil.
2427 If optional argument FRAME is `visible', search all visible frames.
2428 If FRAME is 0, search all visible and iconified frames.
2429 If FRAME is t, search all frames.
2430 If FRAME is nil, search only the selected frame.
2431 If FRAME is a frame, search only that frame. */)
2432 (frame, dedicated)
2433 Lisp_Object frame, dedicated;
2435 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2436 frame);
2439 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2440 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2441 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
2442 current buffer.
2443 If optional argument FRAME is `visible', search all visible frames.
2444 If optional argument FRAME is 0, search all visible and iconified frames.
2445 If FRAME is t, search all frames.
2446 If FRAME is nil, search only the selected frame.
2447 If FRAME is a frame, search only that frame. */)
2448 (buffer_or_name, frame)
2449 Lisp_Object buffer_or_name, frame;
2451 Lisp_Object buffer;
2453 if (NILP (buffer_or_name))
2454 buffer = Fcurrent_buffer ();
2455 else
2456 buffer = Fget_buffer (buffer_or_name);
2458 if (BUFFERP (buffer))
2459 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2460 else
2461 return Qnil;
2464 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2465 0, 1, "",
2466 doc: /* Make WINDOW (or the selected window) fill its frame.
2467 Only the frame WINDOW is on is affected.
2468 This function tries to reduce display jumps by keeping the text
2469 previously visible in WINDOW in the same place on the frame. Doing this
2470 depends on the value of (window-start WINDOW), so if calling this
2471 function in a program gives strange scrolling, make sure the
2472 window-start value is reasonable when this function is called. */)
2473 (window)
2474 Lisp_Object window;
2476 struct window *w;
2477 int startpos;
2478 int top, new_top;
2480 if (NILP (window))
2481 window = selected_window;
2482 else
2483 CHECK_LIVE_WINDOW (window);
2484 w = XWINDOW (window);
2486 startpos = marker_position (w->start);
2487 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2489 if (MINI_WINDOW_P (w) && top > 0)
2490 error ("Can't expand minibuffer to full frame");
2492 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2494 /* Try to minimize scrolling, by setting the window start to the point
2495 will cause the text at the old window start to be at the same place
2496 on the frame. But don't try to do this if the window start is
2497 outside the visible portion (as might happen when the display is
2498 not current, due to typeahead). */
2499 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2500 if (new_top != top
2501 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2502 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2504 struct position pos;
2505 struct buffer *obuf = current_buffer;
2507 Fset_buffer (w->buffer);
2508 /* This computation used to temporarily move point, but that can
2509 have unwanted side effects due to text properties. */
2510 pos = *vmotion (startpos, -top, w);
2512 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2513 w->window_end_valid = Qnil;
2514 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2515 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2516 : Qnil);
2517 /* We need to do this, so that the window-scroll-functions
2518 get called. */
2519 w->optional_new_start = Qt;
2521 set_buffer_internal (obuf);
2524 return Qnil;
2527 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2528 0, 2, "bDelete windows on (buffer): ",
2529 doc: /* Delete all windows showing BUFFER-OR-NAME.
2530 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2531 defaults to the current buffer.
2533 Optional second argument FRAME controls which frames are affected.
2534 If optional argument FRAME is `visible', search all visible frames.
2535 If FRAME is 0, search all visible and iconified frames.
2536 If FRAME is nil, search all frames.
2537 If FRAME is t, search only the selected frame.
2538 If FRAME is a frame, search only that frame.
2539 When a window showing BUFFER-OR-NAME is dedicated and the only window of
2540 its frame, that frame is deleted when there are other frames left. */)
2541 (buffer_or_name, frame)
2542 Lisp_Object buffer_or_name, frame;
2544 Lisp_Object buffer;
2546 /* FRAME uses t and nil to mean the opposite of what window_loop
2547 expects. */
2548 if (NILP (frame))
2549 frame = Qt;
2550 else if (EQ (frame, Qt))
2551 frame = Qnil;
2553 if (NILP (buffer_or_name))
2554 buffer = Fcurrent_buffer ();
2555 else
2557 buffer = Fget_buffer (buffer_or_name);
2558 CHECK_BUFFER (buffer);
2561 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2563 return Qnil;
2566 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2567 Sreplace_buffer_in_windows,
2568 0, 1, "bReplace buffer in windows: ",
2569 doc: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2570 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2571 defaults to the current buffer.
2573 When a window showing BUFFER-OR-NAME is dedicated that window is
2574 deleted. If that window is the only window on its frame, that frame is
2575 deleted too when there are other frames left. If there are no other
2576 frames left, some other buffer is displayed in that window. */)
2577 (buffer_or_name)
2578 Lisp_Object buffer_or_name;
2580 Lisp_Object buffer;
2582 if (NILP (buffer_or_name))
2583 buffer = Fcurrent_buffer ();
2584 else
2586 buffer = Fget_buffer (buffer_or_name);
2587 CHECK_BUFFER (buffer);
2590 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2592 return Qnil;
2595 /* Replace BUFFER with some other buffer in all windows
2596 of all frames, even those on other keyboards. */
2598 void
2599 replace_buffer_in_all_windows (buffer)
2600 Lisp_Object buffer;
2602 Lisp_Object tail, frame;
2604 /* A single call to window_loop won't do the job
2605 because it only considers frames on the current keyboard.
2606 So loop manually over frames, and handle each one. */
2607 FOR_EACH_FRAME (tail, frame)
2608 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2611 /* Set the height of WINDOW and all its inferiors. */
2613 /* The smallest acceptable dimensions for a window. Anything smaller
2614 might crash Emacs. */
2616 #define MIN_SAFE_WINDOW_WIDTH (2)
2617 #define MIN_SAFE_WINDOW_HEIGHT (1)
2619 /* For wp non-zero the total number of columns of window w. Otherwise
2620 the total number of lines of w. */
2622 #define WINDOW_TOTAL_SIZE(w, wp) \
2623 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2625 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2626 minimum allowable size. */
2628 void
2629 check_frame_size (frame, rows, cols)
2630 FRAME_PTR frame;
2631 int *rows, *cols;
2633 /* For height, we have to see:
2634 how many windows the frame has at minimum (one or two),
2635 and whether it has a menu bar or other special stuff at the top. */
2636 int min_height
2637 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2638 ? MIN_SAFE_WINDOW_HEIGHT
2639 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2641 if (FRAME_TOP_MARGIN (frame) > 0)
2642 min_height += FRAME_TOP_MARGIN (frame);
2644 if (*rows < min_height)
2645 *rows = min_height;
2646 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2647 *cols = MIN_SAFE_WINDOW_WIDTH;
2650 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2651 check if W's width can be changed, otherwise check W's height.
2652 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2653 siblings, too. If none of the siblings is resizable, WINDOW isn't
2654 either. */
2656 static int
2657 window_fixed_size_p (w, width_p, check_siblings_p)
2658 struct window *w;
2659 int width_p, check_siblings_p;
2661 int fixed_p;
2662 struct window *c;
2664 if (!NILP (w->hchild))
2666 c = XWINDOW (w->hchild);
2668 if (width_p)
2670 /* A horizontal combination is fixed-width if all of if its
2671 children are. */
2672 while (c && window_fixed_size_p (c, width_p, 0))
2673 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2674 fixed_p = c == NULL;
2676 else
2678 /* A horizontal combination is fixed-height if one of if its
2679 children is. */
2680 while (c && !window_fixed_size_p (c, width_p, 0))
2681 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2682 fixed_p = c != NULL;
2685 else if (!NILP (w->vchild))
2687 c = XWINDOW (w->vchild);
2689 if (width_p)
2691 /* A vertical combination is fixed-width if one of if its
2692 children is. */
2693 while (c && !window_fixed_size_p (c, width_p, 0))
2694 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2695 fixed_p = c != NULL;
2697 else
2699 /* A vertical combination is fixed-height if all of if its
2700 children are. */
2701 while (c && window_fixed_size_p (c, width_p, 0))
2702 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2703 fixed_p = c == NULL;
2706 else if (BUFFERP (w->buffer))
2708 struct buffer *old = current_buffer;
2709 Lisp_Object val;
2711 current_buffer = XBUFFER (w->buffer);
2712 val = find_symbol_value (Qwindow_size_fixed);
2713 current_buffer = old;
2715 fixed_p = 0;
2716 if (!EQ (val, Qunbound))
2718 fixed_p = !NILP (val);
2720 if (fixed_p
2721 && ((EQ (val, Qheight) && width_p)
2722 || (EQ (val, Qwidth) && !width_p)))
2723 fixed_p = 0;
2726 /* Can't tell if this one is resizable without looking at
2727 siblings. If all siblings are fixed-size this one is too. */
2728 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2730 Lisp_Object child;
2732 for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev)
2733 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2734 break;
2736 if (NILP (child))
2737 for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next)
2738 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2739 break;
2741 if (NILP (child))
2742 fixed_p = 1;
2745 else
2746 fixed_p = 1;
2748 return fixed_p;
2751 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2752 the minimum width of W, WIDTH_P zero means return the minimum height
2753 of W. SAFE_P non-zero means ignore window-min-height|width but just
2754 return values that won't crash Emacs and don't hide components like
2755 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2756 minibuffer window, always return 1. */
2758 static int
2759 window_min_size_2 (w, width_p, safe_p)
2760 struct window *w;
2761 int width_p, safe_p;
2763 /* We should consider buffer-local values of window_min_height and
2764 window_min_width here. */
2765 if (width_p)
2767 int safe_size = (MIN_SAFE_WINDOW_WIDTH
2768 + WINDOW_FRINGE_COLS (w)
2769 + WINDOW_SCROLL_BAR_COLS (w));
2771 return safe_p ? safe_size : max (window_min_width, safe_size);
2773 else if (MINI_WINDOW_P (w))
2774 return 1;
2775 else
2777 int safe_size = (MIN_SAFE_WINDOW_HEIGHT
2778 + ((BUFFERP (w->buffer)
2779 && !NILP (XBUFFER (w->buffer)->mode_line_format))
2780 ? 1 : 0));
2782 return safe_p ? safe_size : max (window_min_height, safe_size);
2786 /* Return minimum size of window W, not taking fixed-width windows into
2787 account. WIDTH_P non-zero means return the minimum width, otherwise
2788 return the minimum height. SAFE_P non-zero means ignore
2789 window-min-height|width but just return values that won't crash Emacs
2790 and don't hide components like fringes, scrollbars, or modelines. If
2791 W is a combination window, compute the minimum size from the minimum
2792 sizes of W's children. */
2794 static int
2795 window_min_size_1 (w, width_p, safe_p)
2796 struct window *w;
2797 int width_p, safe_p;
2799 struct window *c;
2800 int size;
2802 if (!NILP (w->hchild))
2804 /* W is a horizontal combination. */
2805 c = XWINDOW (w->hchild);
2806 size = 0;
2808 if (width_p)
2810 /* The minimum width of a horizontal combination is the sum of
2811 the minimum widths of its children. */
2812 while (c)
2814 size += window_min_size_1 (c, 1, safe_p);
2815 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2818 else
2820 /* The minimum height of a horizontal combination is the
2821 maximum of the minimum heights of its children. */
2822 while (c)
2824 size = max (window_min_size_1 (c, 0, safe_p), size);
2825 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2829 else if (!NILP (w->vchild))
2831 /* W is a vertical combination. */
2832 c = XWINDOW (w->vchild);
2833 size = 0;
2835 if (width_p)
2837 /* The minimum width of a vertical combination is the maximum
2838 of the minimum widths of its children. */
2839 while (c)
2841 size = max (window_min_size_1 (c, 1, safe_p), size);
2842 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2845 else
2847 /* The minimum height of a vertical combination is the sum of
2848 the minimum height of its children. */
2849 while (c)
2851 size += window_min_size_1 (c, 0, safe_p);
2852 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2856 else
2857 /* W is a leaf window. */
2858 size = window_min_size_2 (w, width_p, safe_p);
2860 return size;
2863 /* Return the minimum size of window W, taking fixed-size windows into
2864 account. WIDTH_P non-zero means return the minimum width, otherwise
2865 return the minimum height. SAFE_P non-zero means ignore
2866 window-min-height|width but just return values that won't crash Emacs
2867 and don't hide components like fringes, scrollbars, or modelines.
2868 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2869 to 1 if W is fixed-size unless FIXED is null. */
2871 static int
2872 window_min_size (w, width_p, safe_p, ignore_fixed_p, fixed)
2873 struct window *w;
2874 int width_p, safe_p, ignore_fixed_p, *fixed;
2876 int size, fixed_p;
2878 if (ignore_fixed_p)
2879 fixed_p = 0;
2880 else
2881 fixed_p = window_fixed_size_p (w, width_p, 1);
2883 if (fixed)
2884 *fixed = fixed_p;
2886 if (fixed_p)
2887 size = WINDOW_TOTAL_SIZE (w, width_p);
2888 else
2889 size = window_min_size_1 (w, width_p, safe_p);
2891 return size;
2895 /* Adjust the margins of window W if text area is too small.
2896 Return 1 if window width is ok after adjustment; 0 if window
2897 is still too narrow. */
2899 static int
2900 adjust_window_margins (w)
2901 struct window *w;
2903 int box_cols = (WINDOW_TOTAL_COLS (w)
2904 - WINDOW_FRINGE_COLS (w)
2905 - WINDOW_SCROLL_BAR_COLS (w));
2906 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2907 + WINDOW_RIGHT_MARGIN_COLS (w));
2909 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2910 return 1;
2912 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2913 return 0;
2915 /* Window's text area is too narrow, but reducing the window
2916 margins will fix that. */
2917 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2918 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2920 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2921 w->left_margin_cols = w->right_margin_cols
2922 = make_number (margin_cols/2);
2923 else
2924 w->right_margin_cols = make_number (margin_cols);
2926 else
2927 w->left_margin_cols = make_number (margin_cols);
2928 return 1;
2931 /* Calculate new sizes for windows in the list FORWARD when their
2932 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2933 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2934 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2935 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2936 shrink columns, otherwise shrink lines.
2938 SAFE_P zero means windows may be sized down to window-min-height
2939 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2940 non-zero means windows may be sized down to their minimum safe sizes
2941 taking into account the space needed to display modelines, fringes,
2942 and scrollbars.
2944 This function returns an allocated array of new sizes that the caller
2945 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2946 zero. A size zero means the window shall be deleted. Array index 0
2947 refers to the first window in FORWARD, 1 to the second, and so on.
2949 This function resizes windows proportionally to their size. It also
2950 tries to preserve smaller windows by resizing larger windows before
2951 resizing any window to zero. If resize_proportionally is non-nil for
2952 a specific window, it will attempt to strictly resize that window
2953 proportionally, even at the expense of deleting smaller windows. */
2954 static int *
2955 shrink_windows (total, size, nchildren, shrinkable, resize_fixed_p,
2956 forward, width_p, safe_p)
2957 int total, size, nchildren, shrinkable;
2958 int resize_fixed_p, width_p, safe_p;
2959 Lisp_Object forward;
2961 int available_resize = 0;
2962 int *new_sizes, *min_sizes;
2963 struct window *c;
2964 Lisp_Object child;
2965 int smallest = total;
2966 int total_removed = 0;
2967 int total_shrink = total - size;
2968 int i;
2970 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2971 min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
2973 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2975 int child_size;
2977 c = XWINDOW (child);
2978 child_size = WINDOW_TOTAL_SIZE (c, width_p);
2980 if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2981 new_sizes[i] = -1;
2982 else
2984 new_sizes[i] = child_size;
2985 min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
2986 if (child_size > min_sizes[i]
2987 && NILP (c->resize_proportionally))
2988 available_resize += child_size - min_sizes[i];
2991 /* We might need to shrink some windows to zero. Find the smallest
2992 windows and set them to 0 until we can fulfil the new size. */
2994 while (shrinkable > 1 && size + available_resize < total)
2996 for (i = 0; i < nchildren; ++i)
2997 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2998 smallest = new_sizes[i];
3000 for (i = 0; i < nchildren; ++i)
3001 if (new_sizes[i] == smallest)
3003 /* Resize this window down to zero. */
3004 new_sizes[i] = 0;
3005 if (smallest > min_sizes[i])
3006 available_resize -= smallest - min_sizes[i];
3007 available_resize += smallest;
3008 --shrinkable;
3009 total_removed += smallest;
3011 /* We don't know what the smallest is now. */
3012 smallest = total;
3014 /* Out of for, just remove one window at the time and
3015 check again if we have enough space. */
3016 break;
3020 /* Now, calculate the new sizes. Try to shrink each window
3021 proportional to its size. */
3022 for (i = 0; i < nchildren; ++i)
3024 if (new_sizes[i] > min_sizes[i])
3026 int to_shrink = total_shrink * new_sizes[i] / total;
3028 if (new_sizes[i] - to_shrink < min_sizes[i])
3029 to_shrink = new_sizes[i] - min_sizes[i];
3030 new_sizes[i] -= to_shrink;
3031 total_removed += to_shrink;
3035 /* Any reminder due to rounding, we just subtract from windows
3036 that are left and still can be shrunk. */
3037 while (total_shrink > total_removed)
3039 int nonzero_sizes = 0;
3040 int nonzero_idx = -1;
3042 for (i = 0; i < nchildren; ++i)
3043 if (new_sizes[i] > 0)
3045 ++nonzero_sizes;
3046 nonzero_idx = i;
3049 for (i = 0; i < nchildren; ++i)
3050 if (new_sizes[i] > min_sizes[i])
3052 --new_sizes[i];
3053 ++total_removed;
3055 /* Out of for, just shrink one window at the time and
3056 check again if we have enough space. */
3057 break;
3060 /* Special case, only one window left. */
3061 if (nonzero_sizes == 1)
3062 break;
3065 /* Any surplus due to rounding, we add to windows that are left. */
3066 while (total_shrink < total_removed)
3068 for (i = 0; i < nchildren; ++i)
3070 if (new_sizes[i] != 0 && total_shrink < total_removed)
3072 ++new_sizes[i];
3073 --total_removed;
3074 break;
3079 xfree (min_sizes);
3081 return new_sizes;
3084 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3085 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3086 their proportionate size relative to WINDOW.
3088 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3089 they are in series. If LAST_ONLY is 1, change only the last of
3090 WINDOW's children when they are in series.
3092 Propagate WINDOW's top or left edge position to children. Delete
3093 windows that become too small unless NODELETE_P is 1. When
3094 NODELETE_P equals 2 do not honor settings for window-min-height and
3095 window-min-width when resizing windows but use safe defaults instead.
3096 This should give better behavior when resizing frames. */
3098 static void
3099 size_window (window, size, width_p, nodelete_p, first_only, last_only)
3100 Lisp_Object window;
3101 int size, width_p, nodelete_p;
3102 int first_only, last_only;
3104 struct window *w = XWINDOW (window);
3105 struct window *c;
3106 Lisp_Object child, *forward, *sideward;
3107 int old_size = WINDOW_TOTAL_SIZE (w, width_p);
3109 size = max (0, size);
3111 /* Delete WINDOW if it's too small. */
3112 if (nodelete_p != 1 && !NILP (w->parent)
3113 && size < window_min_size_1 (w, width_p, nodelete_p == 2))
3115 delete_window (window);
3116 return;
3119 /* Set redisplay hints. */
3120 w->last_modified = make_number (0);
3121 w->last_overlay_modified = make_number (0);
3122 windows_or_buffers_changed++;
3123 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3125 if (width_p)
3127 sideward = &w->vchild;
3128 forward = &w->hchild;
3129 w->total_cols = make_number (size);
3130 adjust_window_margins (w);
3132 else
3134 sideward = &w->hchild;
3135 forward = &w->vchild;
3136 w->total_lines = make_number (size);
3137 w->orig_total_lines = Qnil;
3140 if (!NILP (*sideward))
3142 /* We have a chain of parallel siblings whose size should all change. */
3143 for (child = *sideward; !NILP (child); child = c->next)
3145 c = XWINDOW (child);
3146 if (width_p)
3147 c->left_col = w->left_col;
3148 else
3149 c->top_line = w->top_line;
3150 size_window (child, size, width_p, nodelete_p,
3151 first_only, last_only);
3154 else if (!NILP (*forward) && last_only)
3156 /* Change the last in a series of siblings. */
3157 Lisp_Object last_child;
3158 int child_size;
3160 for (child = *forward; !NILP (child); child = c->next)
3162 c = XWINDOW (child);
3163 last_child = child;
3166 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3167 size_window (last_child, size - old_size + child_size,
3168 width_p, nodelete_p, first_only, last_only);
3170 else if (!NILP (*forward) && first_only)
3172 /* Change the first in a series of siblings. */
3173 int child_size;
3175 child = *forward;
3176 c = XWINDOW (child);
3178 if (width_p)
3179 c->left_col = w->left_col;
3180 else
3181 c->top_line = w->top_line;
3183 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3184 size_window (child, size - old_size + child_size,
3185 width_p, nodelete_p, first_only, last_only);
3187 else if (!NILP (*forward))
3189 int fixed_size, each, extra, n;
3190 int resize_fixed_p, nfixed;
3191 int last_pos, first_pos, nchildren, total;
3192 int *new_sizes = NULL;
3194 /* Determine the fixed-size portion of this window, and the
3195 number of child windows. */
3196 fixed_size = nchildren = nfixed = total = 0;
3197 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3199 int child_size;
3201 c = XWINDOW (child);
3202 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3203 total += child_size;
3205 if (window_fixed_size_p (c, width_p, 0))
3207 fixed_size += child_size;
3208 ++nfixed;
3212 /* If the new size is smaller than fixed_size, or if there
3213 aren't any resizable windows, allow resizing fixed-size
3214 windows. */
3215 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3217 /* Compute how many lines/columns to add/remove to each child. The
3218 value of extra takes care of rounding errors. */
3219 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3220 if (size < total && n > 1)
3221 new_sizes = shrink_windows (total, size, nchildren, n,
3222 resize_fixed_p, *forward, width_p,
3223 nodelete_p == 2);
3224 else
3226 each = (size - total) / n;
3227 extra = (size - total) - n * each;
3230 /* Compute new children heights and edge positions. */
3231 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3232 last_pos = first_pos;
3233 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3235 int new_size, old_size;
3237 c = XWINDOW (child);
3238 old_size = WINDOW_TOTAL_SIZE (c, width_p);
3239 new_size = old_size;
3241 /* The top or left edge position of this child equals the
3242 bottom or right edge of its predecessor. */
3243 if (width_p)
3244 c->left_col = make_number (last_pos);
3245 else
3246 c->top_line = make_number (last_pos);
3248 /* If this child can be resized, do it. */
3249 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3251 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3252 extra = 0;
3255 /* Set new size. Note that size_window also propagates
3256 edge positions to children, so it's not a no-op if we
3257 didn't change the child's size. */
3258 size_window (child, new_size, width_p, 1, first_only, last_only);
3260 /* Remember the bottom/right edge position of this child; it
3261 will be used to set the top/left edge of the next child. */
3262 last_pos += new_size;
3265 xfree (new_sizes);
3267 /* We should have covered the parent exactly with child windows. */
3268 xassert (size == last_pos - first_pos);
3270 /* Now delete any children that became too small. */
3271 if (nodelete_p != 1)
3272 for (child = *forward; !NILP (child); child = c->next)
3274 int child_size;
3276 c = XWINDOW (child);
3277 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3278 size_window (child, child_size, width_p, nodelete_p,
3279 first_only, last_only);
3284 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3285 WINDOW's children. NODELETE zero means windows that have become
3286 smaller than window-min-height in the process may be deleted.
3287 NODELETE 1 means never delete windows that become too small in the
3288 process. (The caller should check later and do so if appropriate.)
3289 NODELETE 2 means delete only windows that have become too small to be
3290 displayed correctly. */
3292 void
3293 set_window_height (window, height, nodelete)
3294 Lisp_Object window;
3295 int height;
3296 int nodelete;
3298 size_window (window, height, 0, nodelete, 0, 0);
3301 /* Set WINDOW's width to WIDTH, and recursively change the width of
3302 WINDOW's children. NODELETE zero means windows that have become
3303 smaller than window-min-width in the process may be deleted.
3304 NODELETE 1 means never delete windows that become too small in the
3305 process. (The caller should check later and do so if appropriate.)
3306 NODELETE 2 means delete only windows that have become too small to be
3307 displayed correctly. */
3309 void
3310 set_window_width (window, width, nodelete)
3311 Lisp_Object window;
3312 int width;
3313 int nodelete;
3315 size_window (window, width, 1, nodelete, 0, 0);
3318 /* Change window heights in windows rooted in WINDOW by N lines. */
3320 void
3321 change_window_heights (window, n)
3322 Lisp_Object window;
3323 int n;
3325 struct window *w = XWINDOW (window);
3327 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3328 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3330 if (INTEGERP (w->orig_top_line))
3331 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3332 if (INTEGERP (w->orig_total_lines))
3333 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3335 /* Handle just the top child in a vertical split. */
3336 if (!NILP (w->vchild))
3337 change_window_heights (w->vchild, n);
3339 /* Adjust all children in a horizontal split. */
3340 for (window = w->hchild; !NILP (window); window = w->next)
3342 w = XWINDOW (window);
3343 change_window_heights (window, n);
3348 int window_select_count;
3350 EXFUN (Fset_window_fringes, 4);
3351 EXFUN (Fset_window_scroll_bars, 4);
3353 static void
3354 run_funs (Lisp_Object funs)
3356 for (; CONSP (funs); funs = XCDR (funs))
3357 if (!EQ (XCAR (funs), Qt))
3358 call0 (XCAR (funs));
3361 static Lisp_Object select_window_norecord (Lisp_Object window);
3362 static Lisp_Object select_frame_norecord (Lisp_Object frame);
3364 void
3365 run_window_configuration_change_hook (struct frame *f)
3367 int count = SPECPDL_INDEX ();
3368 Lisp_Object frame, global_wcch
3369 = Fdefault_value (Qwindow_configuration_change_hook);
3370 XSETFRAME (frame, f);
3372 if (NILP (Vrun_hooks))
3373 return;
3375 if (SELECTED_FRAME () != f)
3377 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3378 Fselect_frame (frame, Qt);
3381 /* Use the right buffer. Matters when running the local hooks. */
3382 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3384 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3385 Fset_buffer (Fwindow_buffer (Qnil));
3388 /* Look for buffer-local values. */
3390 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3391 for (; CONSP (windows); windows = XCDR (windows))
3393 Lisp_Object window = XCAR (windows);
3394 Lisp_Object buffer = Fwindow_buffer (window);
3395 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3396 buffer)))
3398 int count = SPECPDL_INDEX ();
3399 record_unwind_protect (select_window_norecord, Fselected_window ());
3400 select_window_norecord (window);
3401 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3402 buffer));
3403 unbind_to (count, Qnil);
3408 run_funs (global_wcch);
3409 unbind_to (count, Qnil);
3412 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3413 means it's allowed to run hooks. See make_frame for a case where
3414 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3415 margins, fringes, and scroll-bar settings of the window are not
3416 reset from the buffer's local settings. */
3418 void
3419 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3420 Lisp_Object window, buffer;
3421 int run_hooks_p, keep_margins_p;
3423 struct window *w = XWINDOW (window);
3424 struct buffer *b = XBUFFER (buffer);
3425 int count = SPECPDL_INDEX ();
3426 int samebuf = EQ (buffer, w->buffer);
3428 w->buffer = buffer;
3430 if (EQ (window, selected_window))
3431 b->last_selected_window = window;
3433 /* Let redisplay errors through. */
3434 b->display_error_modiff = 0;
3436 /* Update time stamps of buffer display. */
3437 if (INTEGERP (b->display_count))
3438 XSETINT (b->display_count, XINT (b->display_count) + 1);
3439 b->display_time = Fcurrent_time ();
3441 XSETFASTINT (w->window_end_pos, 0);
3442 XSETFASTINT (w->window_end_vpos, 0);
3443 bzero (&w->last_cursor, sizeof w->last_cursor);
3444 w->window_end_valid = Qnil;
3445 if (!(keep_margins_p && samebuf))
3446 { /* If we're not actually changing the buffer, don't reset hscroll and
3447 vscroll. This case happens for example when called from
3448 change_frame_size_1, where we use a dummy call to
3449 Fset_window_buffer on the frame's selected window (and no other)
3450 just in order to run window-configuration-change-hook.
3451 Resetting hscroll and vscroll here is problematic for things like
3452 image-mode and doc-view-mode since it resets the image's position
3453 whenever we resize the frame. */
3454 w->hscroll = w->min_hscroll = make_number (0);
3455 w->vscroll = 0;
3456 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3457 set_marker_restricted (w->start,
3458 make_number (b->last_window_start),
3459 buffer);
3460 w->start_at_line_beg = Qnil;
3461 w->force_start = Qnil;
3462 XSETFASTINT (w->last_modified, 0);
3463 XSETFASTINT (w->last_overlay_modified, 0);
3465 /* Maybe we could move this into the `if' but it's not obviously safe and
3466 I doubt it's worth the trouble. */
3467 windows_or_buffers_changed++;
3469 /* We must select BUFFER for running the window-scroll-functions. */
3470 /* We can't check ! NILP (Vwindow_scroll_functions) here
3471 because that might itself be a local variable. */
3472 if (window_initialized)
3474 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3475 Fset_buffer (buffer);
3478 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3480 if (!keep_margins_p)
3482 /* Set left and right marginal area width etc. from buffer. */
3484 /* This may call adjust_window_margins three times, so
3485 temporarily disable window margins. */
3486 Lisp_Object save_left = w->left_margin_cols;
3487 Lisp_Object save_right = w->right_margin_cols;
3489 w->left_margin_cols = w->right_margin_cols = Qnil;
3491 Fset_window_fringes (window,
3492 b->left_fringe_width, b->right_fringe_width,
3493 b->fringes_outside_margins);
3495 Fset_window_scroll_bars (window,
3496 b->scroll_bar_width,
3497 b->vertical_scroll_bar_type, Qnil);
3499 w->left_margin_cols = save_left;
3500 w->right_margin_cols = save_right;
3502 Fset_window_margins (window,
3503 b->left_margin_cols, b->right_margin_cols);
3506 if (run_hooks_p)
3508 if (! NILP (Vwindow_scroll_functions))
3509 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3510 Fmarker_position (w->start));
3511 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3514 unbind_to (count, Qnil);
3518 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3519 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3520 WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
3521 or the name of an existing buffer. Optional third argument KEEP-MARGINS
3522 non-nil means that WINDOW's current display margins, fringe widths, and
3523 scroll bar settings are preserved; the default is to reset these from
3524 the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
3526 This function throws an error when WINDOW is strongly dedicated to its
3527 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3528 already display BUFFER-OR-NAME.
3530 This function runs `window-scroll-functions' before running
3531 `window-configuration-change-hook'. */)
3532 (window, buffer_or_name, keep_margins)
3533 register Lisp_Object window, buffer_or_name, keep_margins;
3535 register Lisp_Object tem, buffer;
3536 register struct window *w = decode_window (window);
3538 XSETWINDOW (window, w);
3539 buffer = Fget_buffer (buffer_or_name);
3540 CHECK_BUFFER (buffer);
3541 if (NILP (XBUFFER (buffer)->name))
3542 error ("Attempt to display deleted buffer");
3544 tem = w->buffer;
3545 if (NILP (tem))
3546 error ("Window is deleted");
3547 else if (!EQ (tem, Qt))
3548 /* w->buffer is t when the window is first being set up. */
3550 if (!EQ (tem, buffer))
3551 if (EQ (w->dedicated, Qt))
3552 error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem)->name));
3553 else
3554 w->dedicated = Qnil;
3556 unshow_buffer (w);
3559 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3560 return Qnil;
3563 /* Note that selected_window can be nil when this is called from
3564 Fset_window_configuration. */
3566 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3567 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3568 If WINDOW is not already selected, make WINDOW's buffer current
3569 and make WINDOW the frame's selected window. Return WINDOW.
3570 Optional second arg NORECORD non-nil means do not put this buffer
3571 at the front of the list of recently selected ones and do not
3572 make this window the most recently selected one.
3574 Note that the main editor command loop selects the buffer of the
3575 selected window before each command. */)
3576 (window, norecord)
3577 register Lisp_Object window, norecord;
3579 register struct window *w;
3580 register struct window *ow;
3581 struct frame *sf;
3583 CHECK_LIVE_WINDOW (window);
3585 w = XWINDOW (window);
3586 w->frozen_window_start_p = 0;
3588 if (NILP (norecord))
3590 ++window_select_count;
3591 XSETFASTINT (w->use_time, window_select_count);
3594 if (EQ (window, selected_window))
3595 return window;
3597 sf = SELECTED_FRAME ();
3598 if (XFRAME (WINDOW_FRAME (w)) != sf)
3600 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3601 /* Use this rather than Fhandle_switch_frame
3602 so that FRAME_FOCUS_FRAME is moved appropriately as we
3603 move around in the state where a minibuffer in a separate
3604 frame is active. */
3605 Fselect_frame (WINDOW_FRAME (w), norecord);
3606 /* Fselect_frame called us back so we've done all the work already. */
3607 eassert (EQ (window, selected_window));
3608 return window;
3610 else
3611 sf->selected_window = window;
3613 /* Store the current buffer's actual point into the
3614 old selected window. It belongs to that window,
3615 and when the window is not selected, must be in the window. */
3616 if (!NILP (selected_window))
3618 ow = XWINDOW (selected_window);
3619 if (! NILP (ow->buffer))
3620 set_marker_both (ow->pointm, ow->buffer,
3621 BUF_PT (XBUFFER (ow->buffer)),
3622 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3625 selected_window = window;
3627 if (NILP (norecord))
3628 record_buffer (w->buffer);
3629 Fset_buffer (w->buffer);
3631 XBUFFER (w->buffer)->last_selected_window = window;
3633 /* Go to the point recorded in the window.
3634 This is important when the buffer is in more
3635 than one window. It also matters when
3636 redisplay_window has altered point after scrolling,
3637 because it makes the change only in the window. */
3639 register int new_point = marker_position (w->pointm);
3640 if (new_point < BEGV)
3641 SET_PT (BEGV);
3642 else if (new_point > ZV)
3643 SET_PT (ZV);
3644 else
3645 SET_PT (new_point);
3648 windows_or_buffers_changed++;
3649 return window;
3652 static Lisp_Object
3653 select_window_norecord (window)
3654 Lisp_Object window;
3656 return WINDOW_LIVE_P (window)
3657 ? Fselect_window (window, Qt) : selected_window;
3660 static Lisp_Object
3661 select_frame_norecord (frame)
3662 Lisp_Object frame;
3664 return FRAME_LIVE_P (XFRAME (frame))
3665 ? Fselect_frame (frame, Qt) : selected_frame;
3668 Lisp_Object
3669 display_buffer (buffer, not_this_window_p, override_frame)
3670 Lisp_Object buffer, not_this_window_p, override_frame;
3672 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3675 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3676 0, 1, 0,
3677 doc: /* Force all windows to be updated on next redisplay.
3678 If optional arg OBJECT is a window, force redisplay of that window only.
3679 If OBJECT is a buffer or buffer name, force redisplay of all windows
3680 displaying that buffer. */)
3681 (object)
3682 Lisp_Object object;
3684 if (NILP (object))
3686 windows_or_buffers_changed++;
3687 update_mode_lines++;
3688 return Qt;
3691 if (WINDOWP (object))
3693 struct window *w = XWINDOW (object);
3694 mark_window_display_accurate (object, 0);
3695 w->update_mode_line = Qt;
3696 if (BUFFERP (w->buffer))
3697 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3698 ++update_mode_lines;
3699 return Qt;
3702 if (STRINGP (object))
3703 object = Fget_buffer (object);
3704 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3706 /* Walk all windows looking for buffer, and force update
3707 of each of those windows. */
3709 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3710 return NILP (object) ? Qnil : Qt;
3713 /* If nothing suitable was found, just return.
3714 We could signal an error, but this feature will typically be used
3715 asynchronously in timers or process sentinels, so we don't. */
3716 return Qnil;
3720 void
3721 temp_output_buffer_show (buf)
3722 register Lisp_Object buf;
3724 register struct buffer *old = current_buffer;
3725 register Lisp_Object window;
3726 register struct window *w;
3728 XBUFFER (buf)->directory = current_buffer->directory;
3730 Fset_buffer (buf);
3731 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3732 BEGV = BEG;
3733 ZV = Z;
3734 SET_PT (BEG);
3735 #if 0 /* rms: there should be no reason for this. */
3736 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3737 #endif
3738 set_buffer_internal (old);
3740 if (!NILP (Vtemp_buffer_show_function))
3741 call1 (Vtemp_buffer_show_function, buf);
3742 else
3744 window = display_buffer (buf, Qnil, Qnil);
3746 if (!EQ (XWINDOW (window)->frame, selected_frame))
3747 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3748 Vminibuf_scroll_window = window;
3749 w = XWINDOW (window);
3750 XSETFASTINT (w->hscroll, 0);
3751 XSETFASTINT (w->min_hscroll, 0);
3752 set_marker_restricted_both (w->start, buf, BEG, BEG);
3753 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3755 /* Run temp-buffer-show-hook, with the chosen window selected
3756 and its buffer current. */
3758 if (!NILP (Vrun_hooks)
3759 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3760 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3762 int count = SPECPDL_INDEX ();
3763 Lisp_Object prev_window, prev_buffer;
3764 prev_window = selected_window;
3765 XSETBUFFER (prev_buffer, old);
3767 /* Select the window that was chosen, for running the hook.
3768 Note: Both Fselect_window and select_window_norecord may
3769 set-buffer to the buffer displayed in the window,
3770 so we need to save the current buffer. --stef */
3771 record_unwind_protect (Fset_buffer, prev_buffer);
3772 record_unwind_protect (select_window_norecord, prev_window);
3773 Fselect_window (window, Qt);
3774 Fset_buffer (w->buffer);
3775 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3776 unbind_to (count, Qnil);
3781 static void
3782 make_dummy_parent (window)
3783 Lisp_Object window;
3785 Lisp_Object new;
3786 register struct window *o, *p;
3787 int i;
3789 o = XWINDOW (window);
3790 p = allocate_window ();
3791 for (i = 0; i < VECSIZE (struct window); ++i)
3792 ((struct Lisp_Vector *) p)->contents[i]
3793 = ((struct Lisp_Vector *)o)->contents[i];
3794 XSETWINDOW (new, p);
3796 ++sequence_number;
3797 XSETFASTINT (p->sequence_number, sequence_number);
3799 /* Put new into window structure in place of window */
3800 replace_window (window, new);
3802 o->next = Qnil;
3803 o->prev = Qnil;
3804 o->vchild = Qnil;
3805 o->hchild = Qnil;
3806 o->parent = new;
3808 p->start = Qnil;
3809 p->pointm = Qnil;
3810 p->buffer = Qnil;
3813 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3814 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3815 WINDOW defaults to selected one and SIZE to half its size.
3816 If optional third arg HORIZONTAL is non-nil, split side by side and put
3817 SIZE columns in the first of the pair. In that case, SIZE includes that
3818 window's scroll bar, or the divider column to its right.
3819 Interactively, all arguments are nil.
3820 Returns the newly created window (which is the lower or rightmost one).
3821 The upper or leftmost window is the original one, and remains selected
3822 if it was selected before.
3824 See Info node `(elisp)Splitting Windows' for more details and examples. */)
3825 (window, size, horizontal)
3826 Lisp_Object window, size, horizontal;
3828 register Lisp_Object new;
3829 register struct window *o, *p;
3830 FRAME_PTR fo;
3831 register int size_int;
3833 if (NILP (window))
3834 window = selected_window;
3835 else
3836 CHECK_LIVE_WINDOW (window);
3838 o = XWINDOW (window);
3839 fo = XFRAME (WINDOW_FRAME (o));
3841 if (NILP (size))
3843 if (!NILP (horizontal))
3844 /* Calculate the size of the left-hand window, by dividing
3845 the usable space in columns by two.
3846 We round up, since the left-hand window may include
3847 a dividing line, while the right-hand may not. */
3848 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3849 else
3850 size_int = XFASTINT (o->total_lines) >> 1;
3852 else
3854 CHECK_NUMBER (size);
3855 size_int = XINT (size);
3858 if (MINI_WINDOW_P (o))
3859 error ("Attempt to split minibuffer window");
3860 else if (window_fixed_size_p (o, !NILP (horizontal), 0))
3861 error ("Attempt to split fixed-size window");
3863 if (NILP (horizontal))
3865 int window_safe_height = window_min_size_2 (o, 0, 0);
3867 if (size_int < window_safe_height)
3868 error ("Window height %d too small (after splitting)", size_int);
3869 if (size_int + window_safe_height > XFASTINT (o->total_lines))
3870 error ("Window height %d too small (after splitting)",
3871 XFASTINT (o->total_lines) - size_int);
3872 if (NILP (o->parent)
3873 || NILP (XWINDOW (o->parent)->vchild))
3875 make_dummy_parent (window);
3876 new = o->parent;
3877 XWINDOW (new)->vchild = window;
3880 else
3882 int window_safe_width = window_min_size_2 (o, 1, 0);
3884 if (size_int < window_safe_width)
3885 error ("Window width %d too small (after splitting)", size_int);
3886 if (size_int + window_safe_width > XFASTINT (o->total_cols))
3887 error ("Window width %d too small (after splitting)",
3888 XFASTINT (o->total_cols) - size_int);
3889 if (NILP (o->parent)
3890 || NILP (XWINDOW (o->parent)->hchild))
3892 make_dummy_parent (window);
3893 new = o->parent;
3894 XWINDOW (new)->hchild = window;
3898 /* Now we know that window's parent is a vertical combination
3899 if we are dividing vertically, or a horizontal combination
3900 if we are making side-by-side windows */
3902 windows_or_buffers_changed++;
3903 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3904 new = make_window ();
3905 p = XWINDOW (new);
3907 p->frame = o->frame;
3908 p->next = o->next;
3909 if (!NILP (p->next))
3910 XWINDOW (p->next)->prev = new;
3911 p->prev = window;
3912 o->next = new;
3913 p->parent = o->parent;
3914 p->buffer = Qt;
3915 p->window_end_valid = Qnil;
3916 bzero (&p->last_cursor, sizeof p->last_cursor);
3918 /* Duplicate special geometry settings. */
3920 p->left_margin_cols = o->left_margin_cols;
3921 p->right_margin_cols = o->right_margin_cols;
3922 p->left_fringe_width = o->left_fringe_width;
3923 p->right_fringe_width = o->right_fringe_width;
3924 p->fringes_outside_margins = o->fringes_outside_margins;
3925 p->scroll_bar_width = o->scroll_bar_width;
3926 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3928 /* Apportion the available frame space among the two new windows */
3930 if (!NILP (horizontal))
3932 p->total_lines = o->total_lines;
3933 p->top_line = o->top_line;
3934 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3935 XSETFASTINT (o->total_cols, size_int);
3936 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3937 adjust_window_margins (p);
3938 adjust_window_margins (o);
3940 else
3942 p->left_col = o->left_col;
3943 p->total_cols = o->total_cols;
3944 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3945 XSETFASTINT (o->total_lines, size_int);
3946 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3949 /* Adjust glyph matrices. */
3950 adjust_glyphs (fo);
3952 Fset_window_buffer (new, o->buffer, Qt);
3953 return new;
3956 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3957 doc: /* Make selected window SIZE lines taller.
3958 Interactively, if no argument is given, make the selected window one
3959 line taller. If optional argument HORIZONTAL is non-nil, make selected
3960 window wider by SIZE columns. If SIZE is negative, shrink the window by
3961 -SIZE lines or columns. Return nil.
3963 This function can delete windows if they get too small. The size of
3964 fixed size windows is not altered by this function. */)
3965 (size, horizontal)
3966 Lisp_Object size, horizontal;
3968 CHECK_NUMBER (size);
3969 enlarge_window (selected_window, XINT (size), !NILP (horizontal));
3971 run_window_configuration_change_hook (SELECTED_FRAME ());
3973 return Qnil;
3976 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3977 doc: /* Make selected window SIZE lines smaller.
3978 Interactively, if no argument is given, make the selected window one
3979 line smaller. If optional argument HORIZONTAL is non-nil, make the
3980 window narrower by SIZE columns. If SIZE is negative, enlarge selected
3981 window by -SIZE lines or columns. Return nil.
3983 This function can delete windows if they get too small. The size of
3984 fixed size windows is not altered by this function. */)
3985 (size, horizontal)
3986 Lisp_Object size, horizontal;
3988 CHECK_NUMBER (size);
3989 enlarge_window (selected_window, -XINT (size), !NILP (horizontal));
3991 run_window_configuration_change_hook (SELECTED_FRAME ());
3993 return Qnil;
3997 window_height (window)
3998 Lisp_Object window;
4000 register struct window *p = XWINDOW (window);
4001 return WINDOW_TOTAL_LINES (p);
4005 window_width (window)
4006 Lisp_Object window;
4008 register struct window *p = XWINDOW (window);
4009 return WINDOW_TOTAL_COLS (p);
4013 #define CURBEG(w) \
4014 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4016 #define CURSIZE(w) \
4017 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4020 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4021 horizontally; zero means do it vertically.
4023 Siblings of the selected window are resized to fulfill the size
4024 request. If they become too small in the process, they may be
4025 deleted. */
4027 static void
4028 enlarge_window (window, delta, horiz_flag)
4029 Lisp_Object window;
4030 int delta, horiz_flag;
4032 Lisp_Object parent, next, prev;
4033 struct window *p;
4034 Lisp_Object *sizep;
4035 int maximum;
4036 int (*sizefun) P_ ((Lisp_Object))
4037 = horiz_flag ? window_width : window_height;
4038 void (*setsizefun) P_ ((Lisp_Object, int, int))
4039 = (horiz_flag ? set_window_width : set_window_height);
4041 /* Give up if this window cannot be resized. */
4042 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4043 error ("Window is not resizable");
4045 /* Find the parent of the selected window. */
4046 while (1)
4048 p = XWINDOW (window);
4049 parent = p->parent;
4051 if (NILP (parent))
4053 if (horiz_flag)
4054 error ("No other window to side of this one");
4055 break;
4058 if (horiz_flag
4059 ? !NILP (XWINDOW (parent)->hchild)
4060 : !NILP (XWINDOW (parent)->vchild))
4061 break;
4063 window = parent;
4066 sizep = &CURSIZE (window);
4069 register int maxdelta;
4071 /* Compute the maximum size increment this window can have. */
4073 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4074 /* This is a main window followed by a minibuffer. */
4075 : !NILP (p->next) ? ((*sizefun) (p->next)
4076 - window_min_size (XWINDOW (p->next),
4077 horiz_flag, 0, 0, 0))
4078 /* This is a minibuffer following a main window. */
4079 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4080 - window_min_size (XWINDOW (p->prev),
4081 horiz_flag, 0, 0, 0))
4082 /* This is a frame with only one window, a minibuffer-only
4083 or a minibufferless frame. */
4084 : (delta = 0));
4086 if (delta > maxdelta)
4087 /* This case traps trying to make the minibuffer
4088 the full frame, or make the only window aside from the
4089 minibuffer the full frame. */
4090 delta = maxdelta;
4093 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
4094 horiz_flag, 0, 0, 0))
4096 delete_window (window);
4097 return;
4100 if (delta == 0)
4101 return;
4103 /* Find the total we can get from other siblings without deleting them. */
4104 maximum = 0;
4105 for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
4106 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4107 horiz_flag, 0, 0, 0);
4108 for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
4109 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4110 horiz_flag, 0, 0, 0);
4112 /* If we can get it all from them without deleting them, do so. */
4113 if (delta <= maximum)
4115 Lisp_Object first_unaffected;
4116 Lisp_Object first_affected;
4117 int fixed_p;
4119 next = p->next;
4120 prev = p->prev;
4121 first_affected = window;
4122 /* Look at one sibling at a time,
4123 moving away from this window in both directions alternately,
4124 and take as much as we can get without deleting that sibling. */
4125 while (delta != 0
4126 && (!NILP (next) || !NILP (prev)))
4128 if (! NILP (next))
4130 int this_one = ((*sizefun) (next)
4131 - window_min_size (XWINDOW (next), horiz_flag,
4132 0, 0, &fixed_p));
4133 if (!fixed_p)
4135 if (this_one > delta)
4136 this_one = delta;
4138 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4139 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4141 delta -= this_one;
4144 next = XWINDOW (next)->next;
4147 if (delta == 0)
4148 break;
4150 if (! NILP (prev))
4152 int this_one = ((*sizefun) (prev)
4153 - window_min_size (XWINDOW (prev), horiz_flag,
4154 0, 0, &fixed_p));
4155 if (!fixed_p)
4157 if (this_one > delta)
4158 this_one = delta;
4160 first_affected = prev;
4162 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4163 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4165 delta -= this_one;
4168 prev = XWINDOW (prev)->prev;
4172 xassert (delta == 0);
4174 /* Now recalculate the edge positions of all the windows affected,
4175 based on the new sizes. */
4176 first_unaffected = next;
4177 prev = first_affected;
4178 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4179 prev = next, next = XWINDOW (next)->next)
4181 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4182 /* This does not change size of NEXT,
4183 but it propagates the new top edge to its children */
4184 (*setsizefun) (next, (*sizefun) (next), 0);
4187 else
4189 register int delta1;
4190 register int opht = (*sizefun) (parent);
4192 if (opht <= XINT (*sizep) + delta)
4194 /* If trying to grow this window to or beyond size of the parent,
4195 just delete all the sibling windows. */
4196 Lisp_Object start, tem, next;
4198 start = XWINDOW (parent)->vchild;
4199 if (NILP (start))
4200 start = XWINDOW (parent)->hchild;
4202 /* Delete any siblings that come after WINDOW. */
4203 tem = XWINDOW (window)->next;
4204 while (! NILP (tem))
4206 next = XWINDOW (tem)->next;
4207 delete_window (tem);
4208 tem = next;
4211 /* Delete any siblings that come after WINDOW.
4212 Note that if START is not WINDOW, then WINDOW still
4213 has siblings, so WINDOW has not yet replaced its parent. */
4214 tem = start;
4215 while (! EQ (tem, window))
4217 next = XWINDOW (tem)->next;
4218 delete_window (tem);
4219 tem = next;
4222 else
4224 /* Otherwise, make delta1 just right so that if we add
4225 delta1 lines to this window and to the parent, and then
4226 shrink the parent back to its original size, the new
4227 proportional size of this window will increase by delta.
4229 The function size_window will compute the new height h'
4230 of the window from delta1 as:
4232 e = delta1/n
4233 x = delta1 - delta1/n * n for the 1st resizable child
4234 h' = h + e + x
4236 where n is the number of children that can be resized.
4237 We can ignore x by choosing a delta1 that is a multiple of
4238 n. We want the height of this window to come out as
4240 h' = h + delta
4242 So, delta1 must be
4244 h + e = h + delta
4245 delta1/n = delta
4246 delta1 = n * delta.
4248 The number of children n equals the number of resizable
4249 children of this window + 1 because we know window itself
4250 is resizable (otherwise we would have signaled an error).
4252 This reasoning is not correct when other windows become too
4253 small and shrink_windows refuses to delete them. Below we
4254 use resize_proportionally to work around this problem. */
4256 struct window *w = XWINDOW (window);
4257 Lisp_Object s;
4258 int n = 1;
4260 for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next)
4261 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4262 ++n;
4263 for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev)
4264 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4265 ++n;
4267 delta1 = n * delta;
4269 /* Add delta1 lines or columns to this window, and to the parent,
4270 keeping things consistent while not affecting siblings. */
4271 XSETINT (CURSIZE (parent), opht + delta1);
4272 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4274 /* Squeeze out delta1 lines or columns from our parent,
4275 shrinking this window and siblings proportionately. This
4276 brings parent back to correct size. Delta1 was calculated
4277 so this makes this window the desired size, taking it all
4278 out of the siblings.
4280 Temporarily set resize_proportionally to Qt to assure that,
4281 if necessary, shrink_windows deletes smaller windows rather
4282 than shrink this window. */
4283 w->resize_proportionally = Qt;
4284 (*setsizefun) (parent, opht, 0);
4285 w->resize_proportionally = Qnil;
4289 XSETFASTINT (p->last_modified, 0);
4290 XSETFASTINT (p->last_overlay_modified, 0);
4292 /* Adjust glyph matrices. */
4293 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4297 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4298 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4299 zero means adjust the height, moving the bottom edge.
4301 Following siblings of the selected window are resized to fulfill
4302 the size request. If they become too small in the process, they
4303 are not deleted; instead, we signal an error. */
4305 static void
4306 adjust_window_trailing_edge (window, delta, horiz_flag)
4307 Lisp_Object window;
4308 int delta, horiz_flag;
4310 Lisp_Object parent, child;
4311 struct window *p;
4312 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4313 int delcount = window_deletion_count;
4315 CHECK_WINDOW (window);
4317 /* Give up if this window cannot be resized. */
4318 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4319 error ("Window is not resizable");
4321 while (1)
4323 Lisp_Object first_parallel = Qnil;
4325 if (NILP (window))
4327 /* This happens if WINDOW on the previous iteration was
4328 at top level of the window tree. */
4329 Fset_window_configuration (old_config);
4330 error ("Specified window edge is fixed");
4333 p = XWINDOW (window);
4334 parent = p->parent;
4336 /* See if this level has windows in parallel in the specified
4337 direction. If so, set FIRST_PARALLEL to the first one. */
4338 if (horiz_flag)
4340 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4341 first_parallel = XWINDOW (parent)->vchild;
4342 else if (NILP (parent) && !NILP (p->next))
4344 /* Handle the vertical chain of main window and minibuffer
4345 which has no parent. */
4346 first_parallel = window;
4347 while (! NILP (XWINDOW (first_parallel)->prev))
4348 first_parallel = XWINDOW (first_parallel)->prev;
4351 else
4353 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4354 first_parallel = XWINDOW (parent)->hchild;
4357 /* If this level's succession is in the desired dimension,
4358 and this window is the last one, and there is no higher level,
4359 its trailing edge is fixed. */
4360 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4361 && NILP (parent))
4363 Fset_window_configuration (old_config);
4364 error ("Specified window edge is fixed");
4367 /* Don't make this window too small. */
4368 if (XINT (CURSIZE (window)) + delta
4369 < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
4371 Fset_window_configuration (old_config);
4372 error ("Cannot adjust window size as specified");
4375 /* Clear out some redisplay caches. */
4376 XSETFASTINT (p->last_modified, 0);
4377 XSETFASTINT (p->last_overlay_modified, 0);
4379 /* Adjust this window's edge. */
4380 XSETINT (CURSIZE (window),
4381 XINT (CURSIZE (window)) + delta);
4383 /* If this window has following siblings in the desired dimension,
4384 make them smaller, and exit the loop.
4386 (If we reach the top of the tree and can never do this,
4387 we will fail and report an error, above.) */
4388 if (NILP (first_parallel))
4390 if (!NILP (p->next))
4392 /* This may happen for the minibuffer. In that case
4393 the window_deletion_count check below does not work. */
4394 if (XINT (CURSIZE (p->next)) - delta <= 0)
4396 Fset_window_configuration (old_config);
4397 error ("Cannot adjust window size as specified");
4400 XSETINT (CURBEG (p->next),
4401 XINT (CURBEG (p->next)) + delta);
4402 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4403 horiz_flag, 0, 1, 0);
4404 break;
4407 else
4408 /* Here we have a chain of parallel siblings, in the other dimension.
4409 Change the size of the other siblings. */
4410 for (child = first_parallel;
4411 ! NILP (child);
4412 child = XWINDOW (child)->next)
4413 if (! EQ (child, window))
4414 size_window (child, XINT (CURSIZE (child)) + delta,
4415 horiz_flag, 0, 0, 1);
4417 window = parent;
4420 /* If we made a window so small it got deleted,
4421 we failed. Report failure. */
4422 if (delcount != window_deletion_count)
4424 Fset_window_configuration (old_config);
4425 error ("Cannot adjust window size as specified");
4428 /* Adjust glyph matrices. */
4429 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4432 #undef CURBEG
4433 #undef CURSIZE
4435 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4436 Sadjust_window_trailing_edge, 3, 3, 0,
4437 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4438 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4439 Otherwise, adjust the height, moving the bottom edge.
4441 Following siblings of the selected window are resized to fulfill
4442 the size request. If they become too small in the process, they
4443 are not deleted; instead, we signal an error. */)
4444 (window, delta, horizontal)
4445 Lisp_Object window, delta, horizontal;
4447 CHECK_NUMBER (delta);
4448 if (NILP (window))
4449 window = selected_window;
4450 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4452 run_window_configuration_change_hook
4453 (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4455 return Qnil;
4460 /***********************************************************************
4461 Resizing Mini-Windows
4462 ***********************************************************************/
4464 static void shrink_window_lowest_first P_ ((struct window *, int));
4466 enum save_restore_action
4468 CHECK_ORIG_SIZES,
4469 SAVE_ORIG_SIZES,
4470 RESTORE_ORIG_SIZES
4473 static int save_restore_orig_size P_ ((struct window *,
4474 enum save_restore_action));
4476 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4477 from lowest windows first. */
4479 static void
4480 shrink_window_lowest_first (w, height)
4481 struct window *w;
4482 int height;
4484 struct window *c;
4485 Lisp_Object child;
4486 int old_height;
4488 xassert (!MINI_WINDOW_P (w));
4490 /* Set redisplay hints. */
4491 XSETFASTINT (w->last_modified, 0);
4492 XSETFASTINT (w->last_overlay_modified, 0);
4493 windows_or_buffers_changed++;
4494 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4496 old_height = XFASTINT (w->total_lines);
4497 XSETFASTINT (w->total_lines, height);
4499 if (!NILP (w->hchild))
4501 for (child = w->hchild; !NILP (child); child = c->next)
4503 c = XWINDOW (child);
4504 c->top_line = w->top_line;
4505 shrink_window_lowest_first (c, height);
4508 else if (!NILP (w->vchild))
4510 Lisp_Object last_child;
4511 int delta = old_height - height;
4512 int last_top;
4514 last_child = Qnil;
4516 /* Find the last child. We are taking space from lowest windows
4517 first, so we iterate over children from the last child
4518 backwards. */
4519 for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
4520 last_child = child;
4522 /* Size children down to their safe heights. */
4523 for (child = last_child; delta && !NILP (child); child = c->prev)
4525 int this_one;
4527 c = XWINDOW (child);
4528 this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
4530 if (this_one > delta)
4531 this_one = delta;
4533 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4534 delta -= this_one;
4537 /* Compute new positions. */
4538 last_top = XINT (w->top_line);
4539 for (child = w->vchild; !NILP (child); child = c->next)
4541 c = XWINDOW (child);
4542 c->top_line = make_number (last_top);
4543 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4544 last_top += XFASTINT (c->total_lines);
4550 /* Save, restore, or check positions and sizes in the window tree
4551 rooted at W. ACTION says what to do.
4553 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4554 orig_total_lines members are valid for all windows in the window
4555 tree. Value is non-zero if they are valid.
4557 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4558 orig_top_line and orig_total_lines for all windows in the tree.
4560 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4561 stored in orig_top_line and orig_total_lines for all windows. */
4563 static int
4564 save_restore_orig_size (w, action)
4565 struct window *w;
4566 enum save_restore_action action;
4568 int success_p = 1;
4570 while (w)
4572 if (!NILP (w->hchild))
4574 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4575 success_p = 0;
4577 else if (!NILP (w->vchild))
4579 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4580 success_p = 0;
4583 switch (action)
4585 case CHECK_ORIG_SIZES:
4586 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4587 return 0;
4588 break;
4590 case SAVE_ORIG_SIZES:
4591 w->orig_top_line = w->top_line;
4592 w->orig_total_lines = w->total_lines;
4593 XSETFASTINT (w->last_modified, 0);
4594 XSETFASTINT (w->last_overlay_modified, 0);
4595 break;
4597 case RESTORE_ORIG_SIZES:
4598 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4599 w->top_line = w->orig_top_line;
4600 w->total_lines = w->orig_total_lines;
4601 w->orig_total_lines = w->orig_top_line = Qnil;
4602 XSETFASTINT (w->last_modified, 0);
4603 XSETFASTINT (w->last_overlay_modified, 0);
4604 break;
4606 default:
4607 abort ();
4610 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4613 return success_p;
4617 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4618 without deleting other windows. */
4620 void
4621 grow_mini_window (w, delta)
4622 struct window *w;
4623 int delta;
4625 struct frame *f = XFRAME (w->frame);
4626 struct window *root;
4628 xassert (MINI_WINDOW_P (w));
4629 xassert (delta >= 0);
4631 /* Compute how much we can enlarge the mini-window without deleting
4632 other windows. */
4633 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4634 if (delta)
4636 int min_height = window_min_size (root, 0, 0, 0, 0);
4637 if (XFASTINT (root->total_lines) - delta < min_height)
4638 /* Note that the root window may already be smaller than
4639 min_height. */
4640 delta = max (0, XFASTINT (root->total_lines) - min_height);
4643 if (delta)
4645 /* Save original window sizes and positions, if not already done. */
4646 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4647 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4649 /* Shrink other windows. */
4650 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4652 /* Grow the mini-window. */
4653 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4654 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4655 XSETFASTINT (w->last_modified, 0);
4656 XSETFASTINT (w->last_overlay_modified, 0);
4658 adjust_glyphs (f);
4663 /* Shrink mini-window W. If there is recorded info about window sizes
4664 before a call to grow_mini_window, restore recorded window sizes.
4665 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4666 line. */
4668 void
4669 shrink_mini_window (w)
4670 struct window *w;
4672 struct frame *f = XFRAME (w->frame);
4673 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4675 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4677 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4678 adjust_glyphs (f);
4679 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4680 windows_or_buffers_changed = 1;
4682 else if (XFASTINT (w->total_lines) > 1)
4684 /* Distribute the additional lines of the mini-window
4685 among the other windows. */
4686 Lisp_Object window;
4687 XSETWINDOW (window, w);
4688 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4694 /* Mark window cursors off for all windows in the window tree rooted
4695 at W by setting their phys_cursor_on_p flag to zero. Called from
4696 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4697 the frame are cleared. */
4699 void
4700 mark_window_cursors_off (w)
4701 struct window *w;
4703 while (w)
4705 if (!NILP (w->hchild))
4706 mark_window_cursors_off (XWINDOW (w->hchild));
4707 else if (!NILP (w->vchild))
4708 mark_window_cursors_off (XWINDOW (w->vchild));
4709 else
4710 w->phys_cursor_on_p = 0;
4712 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4717 /* Return number of lines of text (not counting mode lines) in W. */
4720 window_internal_height (w)
4721 struct window *w;
4723 int ht = XFASTINT (w->total_lines);
4725 if (!MINI_WINDOW_P (w))
4727 if (!NILP (w->parent)
4728 || !NILP (w->vchild)
4729 || !NILP (w->hchild)
4730 || !NILP (w->next)
4731 || !NILP (w->prev)
4732 || WINDOW_WANTS_MODELINE_P (w))
4733 --ht;
4735 if (WINDOW_WANTS_HEADER_LINE_P (w))
4736 --ht;
4739 return ht;
4743 /* Return the number of columns in W.
4744 Don't count columns occupied by scroll bars or the vertical bar
4745 separating W from the sibling to its right. */
4748 window_box_text_cols (w)
4749 struct window *w;
4751 struct frame *f = XFRAME (WINDOW_FRAME (w));
4752 int width = XINT (w->total_cols);
4754 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4755 /* Scroll bars occupy a few columns. */
4756 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4757 else if (!FRAME_WINDOW_P (f)
4758 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4759 /* The column of `|' characters separating side-by-side windows
4760 occupies one column only. */
4761 width -= 1;
4763 if (FRAME_WINDOW_P (f))
4764 /* On window-systems, fringes and display margins cannot be
4765 used for normal text. */
4766 width -= (WINDOW_FRINGE_COLS (w)
4767 + WINDOW_LEFT_MARGIN_COLS (w)
4768 + WINDOW_RIGHT_MARGIN_COLS (w));
4770 return width;
4774 /************************************************************************
4775 Window Scrolling
4776 ***********************************************************************/
4778 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4779 N screen-fulls, which is defined as the height of the window minus
4780 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4781 instead. Negative values of N mean scroll down. NOERROR non-zero
4782 means don't signal an error if we try to move over BEGV or ZV,
4783 respectively. */
4785 static void
4786 window_scroll (window, n, whole, noerror)
4787 Lisp_Object window;
4788 int n;
4789 int whole;
4790 int noerror;
4792 immediate_quit = 1;
4794 /* If we must, use the pixel-based version which is much slower than
4795 the line-based one but can handle varying line heights. */
4796 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4797 window_scroll_pixel_based (window, n, whole, noerror);
4798 else
4799 window_scroll_line_based (window, n, whole, noerror);
4801 immediate_quit = 0;
4805 /* Implementation of window_scroll that works based on pixel line
4806 heights. See the comment of window_scroll for parameter
4807 descriptions. */
4809 static void
4810 window_scroll_pixel_based (window, n, whole, noerror)
4811 Lisp_Object window;
4812 int n;
4813 int whole;
4814 int noerror;
4816 struct it it;
4817 struct window *w = XWINDOW (window);
4818 struct text_pos start;
4819 int this_scroll_margin;
4820 /* True if we fiddled the window vscroll field without really scrolling. */
4821 int vscrolled = 0;
4822 int x, y, rtop, rbot, rowh, vpos;
4824 SET_TEXT_POS_FROM_MARKER (start, w->start);
4826 /* If PT is not visible in WINDOW, move back one half of
4827 the screen. Allow PT to be partially visible, otherwise
4828 something like (scroll-down 1) with PT in the line before
4829 the partially visible one would recenter. */
4831 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4833 /* Move backward half the height of the window. Performance note:
4834 vmotion used here is about 10% faster, but would give wrong
4835 results for variable height lines. */
4836 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4837 it.current_y = it.last_visible_y;
4838 move_it_vertically_backward (&it, window_box_height (w) / 2);
4840 /* The function move_iterator_vertically may move over more than
4841 the specified y-distance. If it->w is small, e.g. a
4842 mini-buffer window, we may end up in front of the window's
4843 display area. This is the case when Start displaying at the
4844 start of the line containing PT in this case. */
4845 if (it.current_y <= 0)
4847 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4848 move_it_vertically_backward (&it, 0);
4849 it.current_y = 0;
4852 start = it.current.pos;
4854 else if (auto_window_vscroll_p)
4856 if (rtop || rbot) /* partially visible */
4858 int px;
4859 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4860 if (whole)
4861 dy = max ((window_box_height (w)
4862 - next_screen_context_lines * dy),
4863 dy);
4864 dy *= n;
4866 if (n < 0)
4868 /* Only vscroll backwards if already vscrolled forwards. */
4869 if (w->vscroll < 0 && rtop > 0)
4871 px = max (0, -w->vscroll - min (rtop, -dy));
4872 Fset_window_vscroll (window, make_number (px), Qt);
4873 return;
4876 if (n > 0)
4878 /* Do vscroll if already vscrolled or only display line. */
4879 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4881 px = max (0, -w->vscroll + min (rbot, dy));
4882 Fset_window_vscroll (window, make_number (px), Qt);
4883 return;
4886 /* Maybe modify window start instead of scrolling. */
4887 if (rbot > 0 || w->vscroll < 0)
4889 int spos;
4891 Fset_window_vscroll (window, make_number (0), Qt);
4892 /* If there are other text lines above the current row,
4893 move window start to current row. Else to next row. */
4894 if (rbot > 0)
4895 spos = XINT (Fline_beginning_position (Qnil));
4896 else
4897 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4898 set_marker_restricted (w->start, make_number (spos),
4899 w->buffer);
4900 w->start_at_line_beg = Qt;
4901 w->update_mode_line = Qt;
4902 XSETFASTINT (w->last_modified, 0);
4903 XSETFASTINT (w->last_overlay_modified, 0);
4904 /* Set force_start so that redisplay_window will run the
4905 window-scroll-functions. */
4906 w->force_start = Qt;
4907 return;
4911 /* Cancel previous vscroll. */
4912 Fset_window_vscroll (window, make_number (0), Qt);
4915 /* If scroll_preserve_screen_position is non-nil, we try to set
4916 point in the same window line as it is now, so get that line. */
4917 if (!NILP (Vscroll_preserve_screen_position))
4919 /* We preserve the goal pixel coordinate across consecutive
4920 calls to scroll-up or scroll-down. This avoids the
4921 possibility of point becoming "stuck" on a tall line when
4922 scrolling by one line. */
4923 if (window_scroll_pixel_based_preserve_y < 0
4924 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
4925 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
4927 start_display (&it, w, start);
4928 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4929 window_scroll_pixel_based_preserve_y = it.current_y;
4930 window_scroll_pixel_based_preserve_x = it.current_x;
4933 else
4934 window_scroll_pixel_based_preserve_y
4935 = window_scroll_pixel_based_preserve_x = -1;
4937 /* Move iterator it from start the specified distance forward or
4938 backward. The result is the new window start. */
4939 start_display (&it, w, start);
4940 if (whole)
4942 int start_pos = IT_CHARPOS (it);
4943 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4944 dy = max ((window_box_height (w)
4945 - next_screen_context_lines * dy),
4946 dy) * n;
4948 /* Note that move_it_vertically always moves the iterator to the
4949 start of a line. So, if the last line doesn't have a newline,
4950 we would end up at the start of the line ending at ZV. */
4951 if (dy <= 0)
4953 move_it_vertically_backward (&it, -dy);
4954 /* Ensure we actually do move, e.g. in case we are currently
4955 looking at an image that is taller that the window height. */
4956 while (start_pos == IT_CHARPOS (it)
4957 && start_pos > BEGV)
4958 move_it_by_lines (&it, -1, 1);
4960 else if (dy > 0)
4962 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4963 MOVE_TO_POS | MOVE_TO_Y);
4964 /* Ensure we actually do move, e.g. in case we are currently
4965 looking at an image that is taller that the window height. */
4966 while (start_pos == IT_CHARPOS (it)
4967 && start_pos < ZV)
4968 move_it_by_lines (&it, 1, 1);
4971 else
4972 move_it_by_lines (&it, n, 1);
4974 /* We failed if we find ZV is already on the screen (scrolling up,
4975 means there's nothing past the end), or if we can't start any
4976 earlier (scrolling down, means there's nothing past the top). */
4977 if ((n > 0 && IT_CHARPOS (it) == ZV)
4978 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4980 if (IT_CHARPOS (it) == ZV)
4982 if (it.current_y < it.last_visible_y
4983 && (it.current_y + it.max_ascent + it.max_descent
4984 > it.last_visible_y))
4986 /* The last line was only partially visible, make it fully
4987 visible. */
4988 w->vscroll = (it.last_visible_y
4989 - it.current_y + it.max_ascent + it.max_descent);
4990 adjust_glyphs (it.f);
4992 else if (noerror)
4993 return;
4994 else if (n < 0) /* could happen with empty buffers */
4995 xsignal0 (Qbeginning_of_buffer);
4996 else
4997 xsignal0 (Qend_of_buffer);
4999 else
5001 if (w->vscroll != 0)
5002 /* The first line was only partially visible, make it fully
5003 visible. */
5004 w->vscroll = 0;
5005 else if (noerror)
5006 return;
5007 else
5008 xsignal0 (Qbeginning_of_buffer);
5011 /* If control gets here, then we vscrolled. */
5013 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5015 /* Don't try to change the window start below. */
5016 vscrolled = 1;
5019 if (! vscrolled)
5021 int pos = IT_CHARPOS (it);
5022 int bytepos;
5024 /* If in the middle of a multi-glyph character move forward to
5025 the next character. */
5026 if (in_display_vector_p (&it))
5028 ++pos;
5029 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5032 /* Set the window start, and set up the window for redisplay. */
5033 set_marker_restricted (w->start, make_number (pos),
5034 w->buffer);
5035 bytepos = XMARKER (w->start)->bytepos;
5036 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5037 ? Qt : Qnil);
5038 w->update_mode_line = Qt;
5039 XSETFASTINT (w->last_modified, 0);
5040 XSETFASTINT (w->last_overlay_modified, 0);
5041 /* Set force_start so that redisplay_window will run the
5042 window-scroll-functions. */
5043 w->force_start = Qt;
5046 /* The rest of this function uses current_y in a nonstandard way,
5047 not including the height of the header line if any. */
5048 it.current_y = it.vpos = 0;
5050 /* Move PT out of scroll margins.
5051 This code wants current_y to be zero at the window start position
5052 even if there is a header line. */
5053 this_scroll_margin = max (0, scroll_margin);
5054 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5055 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5057 if (n > 0)
5059 /* We moved the window start towards ZV, so PT may be now
5060 in the scroll margin at the top. */
5061 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5062 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5063 && (NILP (Vscroll_preserve_screen_position)
5064 || EQ (Vscroll_preserve_screen_position, Qt)))
5065 /* We found PT at a legitimate height. Leave it alone. */
5067 else if (window_scroll_pixel_based_preserve_y >= 0)
5069 /* If we have a header line, take account of it.
5070 This is necessary because we set it.current_y to 0, above. */
5071 move_it_to (&it, -1,
5072 window_scroll_pixel_based_preserve_x,
5073 window_scroll_pixel_based_preserve_y
5074 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5075 -1, MOVE_TO_Y | MOVE_TO_X);
5076 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5078 else
5080 while (it.current_y < this_scroll_margin)
5082 int prev = it.current_y;
5083 move_it_by_lines (&it, 1, 1);
5084 if (prev == it.current_y)
5085 break;
5087 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5090 else if (n < 0)
5092 int charpos, bytepos;
5093 int partial_p;
5095 /* Save our position, for the
5096 window_scroll_pixel_based_preserve_y case. */
5097 charpos = IT_CHARPOS (it);
5098 bytepos = IT_BYTEPOS (it);
5100 /* We moved the window start towards BEGV, so PT may be now
5101 in the scroll margin at the bottom. */
5102 move_it_to (&it, PT, -1,
5103 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5104 - this_scroll_margin - 1),
5106 MOVE_TO_POS | MOVE_TO_Y);
5108 /* Save our position, in case it's correct. */
5109 charpos = IT_CHARPOS (it);
5110 bytepos = IT_BYTEPOS (it);
5112 /* See if point is on a partially visible line at the end. */
5113 if (it.what == IT_EOB)
5114 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5115 else
5117 move_it_by_lines (&it, 1, 1);
5118 partial_p = it.current_y > it.last_visible_y;
5121 if (charpos == PT && !partial_p
5122 && (NILP (Vscroll_preserve_screen_position)
5123 || EQ (Vscroll_preserve_screen_position, Qt)))
5124 /* We found PT before we found the display margin, so PT is ok. */
5126 else if (window_scroll_pixel_based_preserve_y >= 0)
5128 SET_TEXT_POS_FROM_MARKER (start, w->start);
5129 start_display (&it, w, start);
5130 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5131 here because we called start_display again and did not
5132 alter it.current_y this time. */
5133 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5134 window_scroll_pixel_based_preserve_y, -1,
5135 MOVE_TO_Y | MOVE_TO_X);
5136 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5138 else
5140 if (partial_p)
5141 /* The last line was only partially visible, so back up two
5142 lines to make sure we're on a fully visible line. */
5144 move_it_by_lines (&it, -2, 0);
5145 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5147 else
5148 /* No, the position we saved is OK, so use it. */
5149 SET_PT_BOTH (charpos, bytepos);
5155 /* Implementation of window_scroll that works based on screen lines.
5156 See the comment of window_scroll for parameter descriptions. */
5158 static void
5159 window_scroll_line_based (window, n, whole, noerror)
5160 Lisp_Object window;
5161 int n;
5162 int whole;
5163 int noerror;
5165 register struct window *w = XWINDOW (window);
5166 register int opoint = PT, opoint_byte = PT_BYTE;
5167 register int pos, pos_byte;
5168 register int ht = window_internal_height (w);
5169 register Lisp_Object tem;
5170 int lose;
5171 Lisp_Object bolp;
5172 int startpos;
5173 Lisp_Object original_pos = Qnil;
5175 /* If scrolling screen-fulls, compute the number of lines to
5176 scroll from the window's height. */
5177 if (whole)
5178 n *= max (1, ht - next_screen_context_lines);
5180 startpos = marker_position (w->start);
5182 if (!NILP (Vscroll_preserve_screen_position))
5184 if (window_scroll_preserve_vpos <= 0
5185 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5186 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5188 struct position posit
5189 = *compute_motion (startpos, 0, 0, 0,
5190 PT, ht, 0,
5191 -1, XINT (w->hscroll),
5192 0, w);
5193 window_scroll_preserve_vpos = posit.vpos;
5194 window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
5197 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5198 make_number (window_scroll_preserve_vpos));
5201 XSETFASTINT (tem, PT);
5202 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5204 if (NILP (tem))
5206 Fvertical_motion (make_number (- (ht / 2)), window);
5207 startpos = PT;
5210 SET_PT (startpos);
5211 lose = n < 0 && PT == BEGV;
5212 Fvertical_motion (make_number (n), window);
5213 pos = PT;
5214 pos_byte = PT_BYTE;
5215 bolp = Fbolp ();
5216 SET_PT_BOTH (opoint, opoint_byte);
5218 if (lose)
5220 if (noerror)
5221 return;
5222 else
5223 xsignal0 (Qbeginning_of_buffer);
5226 if (pos < ZV)
5228 int this_scroll_margin = scroll_margin;
5230 /* Don't use a scroll margin that is negative or too large. */
5231 if (this_scroll_margin < 0)
5232 this_scroll_margin = 0;
5234 if (XINT (w->total_lines) < 4 * scroll_margin)
5235 this_scroll_margin = XINT (w->total_lines) / 4;
5237 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5238 w->start_at_line_beg = bolp;
5239 w->update_mode_line = Qt;
5240 XSETFASTINT (w->last_modified, 0);
5241 XSETFASTINT (w->last_overlay_modified, 0);
5242 /* Set force_start so that redisplay_window will run
5243 the window-scroll-functions. */
5244 w->force_start = Qt;
5246 if (!NILP (Vscroll_preserve_screen_position)
5247 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5249 SET_PT_BOTH (pos, pos_byte);
5250 Fvertical_motion (original_pos, window);
5252 /* If we scrolled forward, put point enough lines down
5253 that it is outside the scroll margin. */
5254 else if (n > 0)
5256 int top_margin;
5258 if (this_scroll_margin > 0)
5260 SET_PT_BOTH (pos, pos_byte);
5261 Fvertical_motion (make_number (this_scroll_margin), window);
5262 top_margin = PT;
5264 else
5265 top_margin = pos;
5267 if (top_margin <= opoint)
5268 SET_PT_BOTH (opoint, opoint_byte);
5269 else if (!NILP (Vscroll_preserve_screen_position))
5271 SET_PT_BOTH (pos, pos_byte);
5272 Fvertical_motion (original_pos, window);
5274 else
5275 SET_PT (top_margin);
5277 else if (n < 0)
5279 int bottom_margin;
5281 /* If we scrolled backward, put point near the end of the window
5282 but not within the scroll margin. */
5283 SET_PT_BOTH (pos, pos_byte);
5284 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5285 if (XFASTINT (tem) == ht - this_scroll_margin)
5286 bottom_margin = PT;
5287 else
5288 bottom_margin = PT + 1;
5290 if (bottom_margin > opoint)
5291 SET_PT_BOTH (opoint, opoint_byte);
5292 else
5294 if (!NILP (Vscroll_preserve_screen_position))
5296 SET_PT_BOTH (pos, pos_byte);
5297 Fvertical_motion (original_pos, window);
5299 else
5300 Fvertical_motion (make_number (-1), window);
5304 else
5306 if (noerror)
5307 return;
5308 else
5309 xsignal0 (Qend_of_buffer);
5314 /* Scroll selected_window up or down. If N is nil, scroll a
5315 screen-full which is defined as the height of the window minus
5316 next_screen_context_lines. If N is the symbol `-', scroll.
5317 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5318 up. This is the guts of Fscroll_up and Fscroll_down. */
5320 static void
5321 scroll_command (n, direction)
5322 Lisp_Object n;
5323 int direction;
5325 int count = SPECPDL_INDEX ();
5327 xassert (eabs (direction) == 1);
5329 /* If selected window's buffer isn't current, make it current for
5330 the moment. But don't screw up if window_scroll gets an error. */
5331 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5333 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5334 Fset_buffer (XWINDOW (selected_window)->buffer);
5336 /* Make redisplay consider other windows than just selected_window. */
5337 ++windows_or_buffers_changed;
5340 if (NILP (n))
5341 window_scroll (selected_window, direction, 1, 0);
5342 else if (EQ (n, Qminus))
5343 window_scroll (selected_window, -direction, 1, 0);
5344 else
5346 n = Fprefix_numeric_value (n);
5347 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5350 unbind_to (count, Qnil);
5353 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5354 doc: /* Scroll text of selected window upward ARG lines.
5355 If ARG is omitted or nil, scroll upward by a near full screen.
5356 A near full screen is `next-screen-context-lines' less than a full screen.
5357 Negative ARG means scroll downward.
5358 If ARG is the atom `-', scroll downward by nearly full screen.
5359 When calling from a program, supply as argument a number, nil, or `-'. */)
5360 (arg)
5361 Lisp_Object arg;
5363 scroll_command (arg, 1);
5364 return Qnil;
5367 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5368 doc: /* Scroll text of selected window down ARG lines.
5369 If ARG is omitted or nil, scroll down by a near full screen.
5370 A near full screen is `next-screen-context-lines' less than a full screen.
5371 Negative ARG means scroll upward.
5372 If ARG is the atom `-', scroll upward by nearly full screen.
5373 When calling from a program, supply as argument a number, nil, or `-'. */)
5374 (arg)
5375 Lisp_Object arg;
5377 scroll_command (arg, -1);
5378 return Qnil;
5381 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5382 doc: /* Return the other window for \"other window scroll\" commands.
5383 If `other-window-scroll-buffer' is non-nil, a window
5384 showing that buffer is used.
5385 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5386 specifies the window. This takes precedence over
5387 `other-window-scroll-buffer'. */)
5390 Lisp_Object window;
5392 if (MINI_WINDOW_P (XWINDOW (selected_window))
5393 && !NILP (Vminibuf_scroll_window))
5394 window = Vminibuf_scroll_window;
5395 /* If buffer is specified, scroll that buffer. */
5396 else if (!NILP (Vother_window_scroll_buffer))
5398 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5399 if (NILP (window))
5400 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5402 else
5404 /* Nothing specified; look for a neighboring window on the same
5405 frame. */
5406 window = Fnext_window (selected_window, Qnil, Qnil);
5408 if (EQ (window, selected_window))
5409 /* That didn't get us anywhere; look for a window on another
5410 visible frame. */
5412 window = Fnext_window (window, Qnil, Qt);
5413 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5414 && ! EQ (window, selected_window));
5417 CHECK_LIVE_WINDOW (window);
5419 if (EQ (window, selected_window))
5420 error ("There is no other window");
5422 return window;
5425 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5426 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5427 A near full screen is `next-screen-context-lines' less than a full screen.
5428 The next window is the one below the current one; or the one at the top
5429 if the current one is at the bottom. Negative ARG means scroll downward.
5430 If ARG is the atom `-', scroll downward by nearly full screen.
5431 When calling from a program, supply as argument a number, nil, or `-'.
5433 If `other-window-scroll-buffer' is non-nil, scroll the window
5434 showing that buffer, popping the buffer up if necessary.
5435 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5436 specifies the window to scroll. This takes precedence over
5437 `other-window-scroll-buffer'. */)
5438 (arg)
5439 Lisp_Object arg;
5441 Lisp_Object window;
5442 struct window *w;
5443 int count = SPECPDL_INDEX ();
5445 window = Fother_window_for_scrolling ();
5446 w = XWINDOW (window);
5448 /* Don't screw up if window_scroll gets an error. */
5449 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5450 ++windows_or_buffers_changed;
5452 Fset_buffer (w->buffer);
5453 SET_PT (marker_position (w->pointm));
5455 if (NILP (arg))
5456 window_scroll (window, 1, 1, 1);
5457 else if (EQ (arg, Qminus))
5458 window_scroll (window, -1, 1, 1);
5459 else
5461 if (CONSP (arg))
5462 arg = Fcar (arg);
5463 CHECK_NUMBER (arg);
5464 window_scroll (window, XINT (arg), 0, 1);
5467 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5468 unbind_to (count, Qnil);
5470 return Qnil;
5473 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5474 doc: /* Scroll selected window display ARG columns left.
5475 Default for ARG is window width minus 2.
5476 Value is the total amount of leftward horizontal scrolling in
5477 effect after the change.
5478 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5479 lower bound for automatic scrolling, i.e. automatic scrolling
5480 will not scroll a window to a column less than the value returned
5481 by this function. This happens in an interactive call. */)
5482 (arg, set_minimum)
5483 register Lisp_Object arg, set_minimum;
5485 Lisp_Object result;
5486 int hscroll;
5487 struct window *w = XWINDOW (selected_window);
5489 if (NILP (arg))
5490 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5491 else
5492 arg = Fprefix_numeric_value (arg);
5494 hscroll = XINT (w->hscroll) + XINT (arg);
5495 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5497 if (!NILP (set_minimum))
5498 w->min_hscroll = w->hscroll;
5500 return result;
5503 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5504 doc: /* Scroll selected window display ARG columns right.
5505 Default for ARG is window width minus 2.
5506 Value is the total amount of leftward horizontal scrolling in
5507 effect after the change.
5508 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5509 lower bound for automatic scrolling, i.e. automatic scrolling
5510 will not scroll a window to a column less than the value returned
5511 by this function. This happens in an interactive call. */)
5512 (arg, set_minimum)
5513 register Lisp_Object arg, set_minimum;
5515 Lisp_Object result;
5516 int hscroll;
5517 struct window *w = XWINDOW (selected_window);
5519 if (NILP (arg))
5520 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5521 else
5522 arg = Fprefix_numeric_value (arg);
5524 hscroll = XINT (w->hscroll) - XINT (arg);
5525 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5527 if (!NILP (set_minimum))
5528 w->min_hscroll = w->hscroll;
5530 return result;
5533 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5534 doc: /* Return the window which was selected when entering the minibuffer.
5535 Returns nil, if selected window is not a minibuffer window. */)
5538 if (minibuf_level > 0
5539 && MINI_WINDOW_P (XWINDOW (selected_window))
5540 && WINDOW_LIVE_P (minibuf_selected_window))
5541 return minibuf_selected_window;
5543 return Qnil;
5546 /* Value is the number of lines actually displayed in window W,
5547 as opposed to its height. */
5549 static int
5550 displayed_window_lines (w)
5551 struct window *w;
5553 struct it it;
5554 struct text_pos start;
5555 int height = window_box_height (w);
5556 struct buffer *old_buffer;
5557 int bottom_y;
5559 if (XBUFFER (w->buffer) != current_buffer)
5561 old_buffer = current_buffer;
5562 set_buffer_internal (XBUFFER (w->buffer));
5564 else
5565 old_buffer = NULL;
5567 /* In case W->start is out of the accessible range, do something
5568 reasonable. This happens in Info mode when Info-scroll-down
5569 calls (recenter -1) while W->start is 1. */
5570 if (XMARKER (w->start)->charpos < BEGV)
5571 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5572 else if (XMARKER (w->start)->charpos > ZV)
5573 SET_TEXT_POS (start, ZV, ZV_BYTE);
5574 else
5575 SET_TEXT_POS_FROM_MARKER (start, w->start);
5577 start_display (&it, w, start);
5578 move_it_vertically (&it, height);
5579 bottom_y = line_bottom_y (&it);
5581 /* rms: On a non-window display,
5582 the value of it.vpos at the bottom of the screen
5583 seems to be 1 larger than window_box_height (w).
5584 This kludge fixes a bug whereby (move-to-window-line -1)
5585 when ZV is on the last screen line
5586 moves to the previous screen line instead of the last one. */
5587 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5588 height++;
5590 /* Add in empty lines at the bottom of the window. */
5591 if (bottom_y < height)
5593 int uy = FRAME_LINE_HEIGHT (it.f);
5594 it.vpos += (height - bottom_y + uy - 1) / uy;
5597 if (old_buffer)
5598 set_buffer_internal (old_buffer);
5600 return it.vpos;
5604 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5605 doc: /* Center point in selected window and redisplay frame.
5606 With prefix argument ARG, recenter putting point on screen line ARG
5607 relative to the selected window. If ARG is negative, it counts up from the
5608 bottom of the window. (ARG should be less than the height of the window.)
5610 If ARG is omitted or nil, erase the entire frame and then redraw with point
5611 in the center of the selected window. If `auto-resize-tool-bars' is set to
5612 `grow-only', this resets the tool-bar's height to the minimum height needed.
5614 Just C-u as prefix means put point in the center of the window
5615 and redisplay normally--don't erase and redraw the frame. */)
5616 (arg)
5617 register Lisp_Object arg;
5619 struct window *w = XWINDOW (selected_window);
5620 struct buffer *buf = XBUFFER (w->buffer);
5621 struct buffer *obuf = current_buffer;
5622 int center_p = 0;
5623 int charpos, bytepos;
5624 int iarg;
5625 int this_scroll_margin;
5627 /* If redisplay is suppressed due to an error, try again. */
5628 obuf->display_error_modiff = 0;
5630 if (NILP (arg))
5632 int i;
5634 /* Invalidate pixel data calculated for all compositions. */
5635 for (i = 0; i < n_compositions; i++)
5636 composition_table[i]->font = NULL;
5638 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5640 Fredraw_frame (WINDOW_FRAME (w));
5641 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5642 center_p = 1;
5644 else if (CONSP (arg)) /* Just C-u. */
5645 center_p = 1;
5646 else
5648 arg = Fprefix_numeric_value (arg);
5649 CHECK_NUMBER (arg);
5650 iarg = XINT (arg);
5653 set_buffer_internal (buf);
5655 /* Do this after making BUF current
5656 in case scroll_margin is buffer-local. */
5657 this_scroll_margin = max (0, scroll_margin);
5658 this_scroll_margin = min (this_scroll_margin,
5659 XFASTINT (w->total_lines) / 4);
5661 /* Handle centering on a graphical frame specially. Such frames can
5662 have variable-height lines and centering point on the basis of
5663 line counts would lead to strange effects. */
5664 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5666 if (center_p)
5668 struct it it;
5669 struct text_pos pt;
5671 SET_TEXT_POS (pt, PT, PT_BYTE);
5672 start_display (&it, w, pt);
5673 move_it_vertically_backward (&it, window_box_height (w) / 2);
5674 charpos = IT_CHARPOS (it);
5675 bytepos = IT_BYTEPOS (it);
5677 else if (iarg < 0)
5679 struct it it;
5680 struct text_pos pt;
5681 int nlines = -iarg;
5682 int extra_line_spacing;
5683 int h = window_box_height (w);
5685 iarg = - max (-iarg, this_scroll_margin);
5687 SET_TEXT_POS (pt, PT, PT_BYTE);
5688 start_display (&it, w, pt);
5690 /* Be sure we have the exact height of the full line containing PT. */
5691 move_it_by_lines (&it, 0, 1);
5693 /* The amount of pixels we have to move back is the window
5694 height minus what's displayed in the line containing PT,
5695 and the lines below. */
5696 it.current_y = 0;
5697 it.vpos = 0;
5698 move_it_by_lines (&it, nlines, 1);
5700 if (it.vpos == nlines)
5701 h -= it.current_y;
5702 else
5704 /* Last line has no newline */
5705 h -= line_bottom_y (&it);
5706 it.vpos++;
5709 /* Don't reserve space for extra line spacing of last line. */
5710 extra_line_spacing = it.max_extra_line_spacing;
5712 /* If we can't move down NLINES lines because we hit
5713 the end of the buffer, count in some empty lines. */
5714 if (it.vpos < nlines)
5716 nlines -= it.vpos;
5717 extra_line_spacing = it.extra_line_spacing;
5718 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5720 if (h <= 0)
5721 return Qnil;
5723 /* Now find the new top line (starting position) of the window. */
5724 start_display (&it, w, pt);
5725 it.current_y = 0;
5726 move_it_vertically_backward (&it, h);
5728 /* If extra line spacing is present, we may move too far
5729 back. This causes the last line to be only partially
5730 visible (which triggers redisplay to recenter that line
5731 in the middle), so move forward.
5732 But ignore extra line spacing on last line, as it is not
5733 considered to be part of the visible height of the line.
5735 h += extra_line_spacing;
5736 while (-it.current_y > h)
5737 move_it_by_lines (&it, 1, 1);
5739 charpos = IT_CHARPOS (it);
5740 bytepos = IT_BYTEPOS (it);
5742 else
5744 struct position pos;
5746 iarg = max (iarg, this_scroll_margin);
5748 pos = *vmotion (PT, -iarg, w);
5749 charpos = pos.bufpos;
5750 bytepos = pos.bytepos;
5753 else
5755 struct position pos;
5756 int ht = window_internal_height (w);
5758 if (center_p)
5759 iarg = ht / 2;
5760 else if (iarg < 0)
5761 iarg += ht;
5763 /* Don't let it get into the margin at either top or bottom. */
5764 iarg = max (iarg, this_scroll_margin);
5765 iarg = min (iarg, ht - this_scroll_margin - 1);
5767 pos = *vmotion (PT, - iarg, w);
5768 charpos = pos.bufpos;
5769 bytepos = pos.bytepos;
5772 /* Set the new window start. */
5773 set_marker_both (w->start, w->buffer, charpos, bytepos);
5774 w->window_end_valid = Qnil;
5776 w->optional_new_start = Qt;
5778 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5779 w->start_at_line_beg = Qt;
5780 else
5781 w->start_at_line_beg = Qnil;
5783 set_buffer_internal (obuf);
5784 return Qnil;
5788 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5789 0, 1, 0,
5790 doc: /* Return the height in lines of the text display area of WINDOW.
5791 WINDOW defaults to the selected window.
5793 The return value does not include the mode line, any header line, nor
5794 any partial-height lines in the text display area. */)
5795 (window)
5796 Lisp_Object window;
5798 struct window *w = decode_window (window);
5799 int pixel_height = window_box_height (w);
5800 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5801 return make_number (line_height);
5806 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5807 1, 1, "P",
5808 doc: /* Position point relative to window.
5809 With no argument, position point at center of window.
5810 An argument specifies vertical position within the window;
5811 zero means top of window, negative means relative to bottom of window. */)
5812 (arg)
5813 Lisp_Object arg;
5815 struct window *w = XWINDOW (selected_window);
5816 int lines, start;
5817 Lisp_Object window;
5818 #if 0
5819 int this_scroll_margin;
5820 #endif
5822 window = selected_window;
5823 start = marker_position (w->start);
5824 if (start < BEGV || start > ZV)
5826 int height = window_internal_height (w);
5827 Fvertical_motion (make_number (- (height / 2)), window);
5828 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5829 w->start_at_line_beg = Fbolp ();
5830 w->force_start = Qt;
5832 else
5833 Fgoto_char (w->start);
5835 lines = displayed_window_lines (w);
5837 #if 0
5838 this_scroll_margin = max (0, scroll_margin);
5839 this_scroll_margin = min (this_scroll_margin, lines / 4);
5840 #endif
5842 if (NILP (arg))
5843 XSETFASTINT (arg, lines / 2);
5844 else
5846 int iarg = XINT (Fprefix_numeric_value (arg));
5848 if (iarg < 0)
5849 iarg = iarg + lines;
5851 #if 0 /* This code would prevent move-to-window-line from moving point
5852 to a place inside the scroll margins (which would cause the
5853 next redisplay to scroll). I wrote this code, but then concluded
5854 it is probably better not to install it. However, it is here
5855 inside #if 0 so as not to lose it. -- rms. */
5857 /* Don't let it get into the margin at either top or bottom. */
5858 iarg = max (iarg, this_scroll_margin);
5859 iarg = min (iarg, lines - this_scroll_margin - 1);
5860 #endif
5862 arg = make_number (iarg);
5865 /* Skip past a partially visible first line. */
5866 if (w->vscroll)
5867 XSETINT (arg, XINT (arg) + 1);
5869 return Fvertical_motion (arg, window);
5874 /***********************************************************************
5875 Window Configuration
5876 ***********************************************************************/
5878 struct save_window_data
5880 EMACS_UINT size;
5881 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5882 Lisp_Object selected_frame;
5883 Lisp_Object current_window;
5884 Lisp_Object current_buffer;
5885 Lisp_Object minibuf_scroll_window;
5886 Lisp_Object minibuf_selected_window;
5887 Lisp_Object root_window;
5888 Lisp_Object focus_frame;
5889 /* A vector, each of whose elements is a struct saved_window
5890 for one window. */
5891 Lisp_Object saved_windows;
5893 /* All fields above are traced by the GC.
5894 From `fame-cols' down, the fields are ignored by the GC. */
5896 int frame_cols, frame_lines, frame_menu_bar_lines;
5897 int frame_tool_bar_lines;
5900 /* This is saved as a Lisp_Vector */
5901 struct saved_window
5903 /* these first two must agree with struct Lisp_Vector in lisp.h */
5904 EMACS_UINT size;
5905 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5907 Lisp_Object window;
5908 Lisp_Object buffer, start, pointm, mark;
5909 Lisp_Object left_col, top_line, total_cols, total_lines;
5910 Lisp_Object hscroll, min_hscroll;
5911 Lisp_Object parent, prev;
5912 Lisp_Object start_at_line_beg;
5913 Lisp_Object display_table;
5914 Lisp_Object orig_top_line, orig_total_lines;
5915 Lisp_Object left_margin_cols, right_margin_cols;
5916 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5917 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5918 Lisp_Object dedicated, resize_proportionally;
5921 #define SAVED_WINDOW_N(swv,n) \
5922 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5924 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5925 doc: /* Return t if OBJECT is a window-configuration object. */)
5926 (object)
5927 Lisp_Object object;
5929 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5932 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5933 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5934 (config)
5935 Lisp_Object config;
5937 register struct save_window_data *data;
5938 struct Lisp_Vector *saved_windows;
5940 CHECK_WINDOW_CONFIGURATION (config);
5942 data = (struct save_window_data *) XVECTOR (config);
5943 saved_windows = XVECTOR (data->saved_windows);
5944 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5947 DEFUN ("set-window-configuration", Fset_window_configuration,
5948 Sset_window_configuration, 1, 1, 0,
5949 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5950 CONFIGURATION must be a value previously returned
5951 by `current-window-configuration' (which see).
5952 If CONFIGURATION was made from a frame that is now deleted,
5953 only frame-independent values can be restored. In this case,
5954 the return value is nil. Otherwise the value is t. */)
5955 (configuration)
5956 Lisp_Object configuration;
5958 register struct save_window_data *data;
5959 struct Lisp_Vector *saved_windows;
5960 Lisp_Object new_current_buffer;
5961 Lisp_Object frame;
5962 FRAME_PTR f;
5963 int old_point = -1;
5965 CHECK_WINDOW_CONFIGURATION (configuration);
5967 data = (struct save_window_data *) XVECTOR (configuration);
5968 saved_windows = XVECTOR (data->saved_windows);
5970 new_current_buffer = data->current_buffer;
5971 if (NILP (XBUFFER (new_current_buffer)->name))
5972 new_current_buffer = Qnil;
5973 else
5975 if (XBUFFER (new_current_buffer) == current_buffer)
5976 /* The code further down "preserves point" by saving here PT in
5977 old_point and then setting it later back into PT. When the
5978 current-selected-window and the final-selected-window both show
5979 the current buffer, this suffers from the problem that the
5980 current PT is the window-point of the current-selected-window,
5981 while the final PT is the point of the final-selected-window, so
5982 this copy from one PT to the other would end up moving the
5983 window-point of the final-selected-window to the window-point of
5984 the current-selected-window. So we have to be careful which
5985 point of the current-buffer we copy into old_point. */
5986 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5987 && WINDOWP (selected_window)
5988 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5989 && !EQ (selected_window, data->current_window))
5990 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5991 else
5992 old_point = PT;
5993 else
5994 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5995 point in new_current_buffer as of the last time this buffer was
5996 used. This can be non-deterministic since it can be changed by
5997 things like jit-lock by mere temporary selection of some random
5998 window that happens to show this buffer.
5999 So if possible we want this arbitrary choice of "which point" to
6000 be the one from the to-be-selected-window so as to prevent this
6001 window's cursor from being copied from another window. */
6002 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6003 /* If current_window = selected_window, its point is in BUF_PT. */
6004 && !EQ (selected_window, data->current_window))
6005 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6006 else
6007 old_point = BUF_PT (XBUFFER (new_current_buffer));
6010 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6011 f = XFRAME (frame);
6013 /* If f is a dead frame, don't bother rebuilding its window tree.
6014 However, there is other stuff we should still try to do below. */
6015 if (FRAME_LIVE_P (f))
6017 register struct window *w;
6018 register struct saved_window *p;
6019 struct window *root_window;
6020 struct window **leaf_windows;
6021 int n_leaf_windows;
6022 int k, i, n;
6024 /* If the frame has been resized since this window configuration was
6025 made, we change the frame to the size specified in the
6026 configuration, restore the configuration, and then resize it
6027 back. We keep track of the prevailing height in these variables. */
6028 int previous_frame_lines = FRAME_LINES (f);
6029 int previous_frame_cols = FRAME_COLS (f);
6030 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6031 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6033 /* The mouse highlighting code could get screwed up
6034 if it runs during this. */
6035 BLOCK_INPUT;
6037 if (data->frame_lines != previous_frame_lines
6038 || data->frame_cols != previous_frame_cols)
6039 change_frame_size (f, data->frame_lines,
6040 data->frame_cols, 0, 0, 0);
6041 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6042 if (data->frame_menu_bar_lines
6043 != previous_frame_menu_bar_lines)
6044 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
6045 make_number (0));
6046 #ifdef HAVE_WINDOW_SYSTEM
6047 if (data->frame_tool_bar_lines
6048 != previous_frame_tool_bar_lines)
6049 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
6050 make_number (0));
6051 #endif
6052 #endif
6054 /* "Swap out" point from the selected window's buffer
6055 into the window itself. (Normally the pointm of the selected
6056 window holds garbage.) We do this now, before
6057 restoring the window contents, and prevent it from
6058 being done later on when we select a new window. */
6059 if (! NILP (XWINDOW (selected_window)->buffer))
6061 w = XWINDOW (selected_window);
6062 set_marker_both (w->pointm,
6063 w->buffer,
6064 BUF_PT (XBUFFER (w->buffer)),
6065 BUF_PT_BYTE (XBUFFER (w->buffer)));
6068 windows_or_buffers_changed++;
6069 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6071 /* Problem: Freeing all matrices and later allocating them again
6072 is a serious redisplay flickering problem. What we would
6073 really like to do is to free only those matrices not reused
6074 below. */
6075 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6076 leaf_windows
6077 = (struct window **) alloca (count_windows (root_window)
6078 * sizeof (struct window *));
6079 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6081 /* Kludge Alert!
6082 Mark all windows now on frame as "deleted".
6083 Restoring the new configuration "undeletes" any that are in it.
6085 Save their current buffers in their height fields, since we may
6086 need it later, if a buffer saved in the configuration is now
6087 dead. */
6088 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6090 for (k = 0; k < saved_windows->size; k++)
6092 p = SAVED_WINDOW_N (saved_windows, k);
6093 w = XWINDOW (p->window);
6094 w->next = Qnil;
6096 if (!NILP (p->parent))
6097 w->parent = SAVED_WINDOW_N (saved_windows,
6098 XFASTINT (p->parent))->window;
6099 else
6100 w->parent = Qnil;
6102 if (!NILP (p->prev))
6104 w->prev = SAVED_WINDOW_N (saved_windows,
6105 XFASTINT (p->prev))->window;
6106 XWINDOW (w->prev)->next = p->window;
6108 else
6110 w->prev = Qnil;
6111 if (!NILP (w->parent))
6113 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6115 XWINDOW (w->parent)->vchild = p->window;
6116 XWINDOW (w->parent)->hchild = Qnil;
6118 else
6120 XWINDOW (w->parent)->hchild = p->window;
6121 XWINDOW (w->parent)->vchild = Qnil;
6126 /* If we squirreled away the buffer in the window's height,
6127 restore it now. */
6128 if (BUFFERP (w->total_lines))
6129 w->buffer = w->total_lines;
6130 w->left_col = p->left_col;
6131 w->top_line = p->top_line;
6132 w->total_cols = p->total_cols;
6133 w->total_lines = p->total_lines;
6134 w->hscroll = p->hscroll;
6135 w->min_hscroll = p->min_hscroll;
6136 w->display_table = p->display_table;
6137 w->orig_top_line = p->orig_top_line;
6138 w->orig_total_lines = p->orig_total_lines;
6139 w->left_margin_cols = p->left_margin_cols;
6140 w->right_margin_cols = p->right_margin_cols;
6141 w->left_fringe_width = p->left_fringe_width;
6142 w->right_fringe_width = p->right_fringe_width;
6143 w->fringes_outside_margins = p->fringes_outside_margins;
6144 w->scroll_bar_width = p->scroll_bar_width;
6145 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6146 w->dedicated = p->dedicated;
6147 w->resize_proportionally = p->resize_proportionally;
6148 XSETFASTINT (w->last_modified, 0);
6149 XSETFASTINT (w->last_overlay_modified, 0);
6151 /* Reinstall the saved buffer and pointers into it. */
6152 if (NILP (p->buffer))
6153 w->buffer = p->buffer;
6154 else
6156 if (!NILP (XBUFFER (p->buffer)->name))
6157 /* If saved buffer is alive, install it. */
6159 w->buffer = p->buffer;
6160 w->start_at_line_beg = p->start_at_line_beg;
6161 set_marker_restricted (w->start, p->start, w->buffer);
6162 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6163 Fset_marker (XBUFFER (w->buffer)->mark,
6164 p->mark, w->buffer);
6166 /* As documented in Fcurrent_window_configuration, don't
6167 restore the location of point in the buffer which was
6168 current when the window configuration was recorded. */
6169 if (!EQ (p->buffer, new_current_buffer)
6170 && XBUFFER (p->buffer) == current_buffer)
6171 Fgoto_char (w->pointm);
6173 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6174 /* Else unless window has a live buffer, get one. */
6176 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6177 /* This will set the markers to beginning of visible
6178 range. */
6179 set_marker_restricted (w->start, make_number (0), w->buffer);
6180 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6181 w->start_at_line_beg = Qt;
6183 else
6184 /* Keeping window's old buffer; make sure the markers
6185 are real. */
6187 /* Set window markers at start of visible range. */
6188 if (XMARKER (w->start)->buffer == 0)
6189 set_marker_restricted (w->start, make_number (0),
6190 w->buffer);
6191 if (XMARKER (w->pointm)->buffer == 0)
6192 set_marker_restricted_both (w->pointm, w->buffer,
6193 BUF_PT (XBUFFER (w->buffer)),
6194 BUF_PT_BYTE (XBUFFER (w->buffer)));
6195 w->start_at_line_beg = Qt;
6200 FRAME_ROOT_WINDOW (f) = data->root_window;
6201 /* Prevent "swapping out point" in the old selected window
6202 using the buffer that has been restored into it.
6203 We already swapped out point that from that window's old buffer. */
6204 selected_window = Qnil;
6206 /* Arrange *not* to restore point in the buffer that was
6207 current when the window configuration was saved. */
6208 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6209 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6210 make_number (old_point),
6211 XWINDOW (data->current_window)->buffer);
6213 Fselect_window (data->current_window, Qnil);
6214 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6215 = selected_window;
6217 if (NILP (data->focus_frame)
6218 || (FRAMEP (data->focus_frame)
6219 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6220 Fredirect_frame_focus (frame, data->focus_frame);
6222 #if 0 /* I don't understand why this is needed, and it causes problems
6223 when the frame's old selected window has been deleted. */
6224 if (f != selected_frame && FRAME_WINDOW_P (f))
6225 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6226 0, 0, Qnil);
6227 #endif
6229 /* Set the screen height to the value it had before this function. */
6230 if (previous_frame_lines != FRAME_LINES (f)
6231 || previous_frame_cols != FRAME_COLS (f))
6232 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6233 0, 0, 0);
6234 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6235 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6236 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6237 make_number (0));
6238 #ifdef HAVE_WINDOW_SYSTEM
6239 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6240 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6241 make_number (0));
6242 #endif
6243 #endif
6245 /* Now, free glyph matrices in windows that were not reused. */
6246 for (i = n = 0; i < n_leaf_windows; ++i)
6248 if (NILP (leaf_windows[i]->buffer))
6250 /* Assert it's not reused as a combination. */
6251 xassert (NILP (leaf_windows[i]->hchild)
6252 && NILP (leaf_windows[i]->vchild));
6253 free_window_matrices (leaf_windows[i]);
6255 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6256 ++n;
6259 adjust_glyphs (f);
6261 UNBLOCK_INPUT;
6263 /* Fselect_window will have made f the selected frame, so we
6264 reselect the proper frame here. Fhandle_switch_frame will change the
6265 selected window too, but that doesn't make the call to
6266 Fselect_window above totally superfluous; it still sets f's
6267 selected window. */
6268 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6269 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6271 run_window_configuration_change_hook (f);
6274 if (!NILP (new_current_buffer))
6275 Fset_buffer (new_current_buffer);
6277 Vminibuf_scroll_window = data->minibuf_scroll_window;
6278 minibuf_selected_window = data->minibuf_selected_window;
6280 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6283 /* Mark all windows now on frame as deleted
6284 by setting their buffers to nil. */
6286 void
6287 delete_all_subwindows (w)
6288 register struct window *w;
6290 if (!NILP (w->next))
6291 delete_all_subwindows (XWINDOW (w->next));
6292 if (!NILP (w->vchild))
6293 delete_all_subwindows (XWINDOW (w->vchild));
6294 if (!NILP (w->hchild))
6295 delete_all_subwindows (XWINDOW (w->hchild));
6297 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6299 if (!NILP (w->buffer))
6300 unshow_buffer (w);
6302 /* We set all three of these fields to nil, to make sure that we can
6303 distinguish this dead window from any live window. Live leaf
6304 windows will have buffer set, and combination windows will have
6305 vchild or hchild set. */
6306 w->buffer = Qnil;
6307 w->vchild = Qnil;
6308 w->hchild = Qnil;
6310 Vwindow_list = Qnil;
6313 static int
6314 count_windows (window)
6315 register struct window *window;
6317 register int count = 1;
6318 if (!NILP (window->next))
6319 count += count_windows (XWINDOW (window->next));
6320 if (!NILP (window->vchild))
6321 count += count_windows (XWINDOW (window->vchild));
6322 if (!NILP (window->hchild))
6323 count += count_windows (XWINDOW (window->hchild));
6324 return count;
6328 /* Fill vector FLAT with leaf windows under W, starting at index I.
6329 Value is last index + 1. */
6331 static int
6332 get_leaf_windows (w, flat, i)
6333 struct window *w;
6334 struct window **flat;
6335 int i;
6337 while (w)
6339 if (!NILP (w->hchild))
6340 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6341 else if (!NILP (w->vchild))
6342 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6343 else
6344 flat[i++] = w;
6346 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6349 return i;
6353 /* Return a pointer to the glyph W's physical cursor is on. Value is
6354 null if W's current matrix is invalid, so that no meaningfull glyph
6355 can be returned. */
6357 struct glyph *
6358 get_phys_cursor_glyph (w)
6359 struct window *w;
6361 struct glyph_row *row;
6362 struct glyph *glyph;
6364 if (w->phys_cursor.vpos >= 0
6365 && w->phys_cursor.vpos < w->current_matrix->nrows
6366 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6367 row->enabled_p)
6368 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6369 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6370 else
6371 glyph = NULL;
6373 return glyph;
6377 static int
6378 save_window_save (window, vector, i)
6379 Lisp_Object window;
6380 struct Lisp_Vector *vector;
6381 int i;
6383 register struct saved_window *p;
6384 register struct window *w;
6385 register Lisp_Object tem;
6387 for (;!NILP (window); window = w->next)
6389 p = SAVED_WINDOW_N (vector, i);
6390 w = XWINDOW (window);
6392 XSETFASTINT (w->temslot, i); i++;
6393 p->window = window;
6394 p->buffer = w->buffer;
6395 p->left_col = w->left_col;
6396 p->top_line = w->top_line;
6397 p->total_cols = w->total_cols;
6398 p->total_lines = w->total_lines;
6399 p->hscroll = w->hscroll;
6400 p->min_hscroll = w->min_hscroll;
6401 p->display_table = w->display_table;
6402 p->orig_top_line = w->orig_top_line;
6403 p->orig_total_lines = w->orig_total_lines;
6404 p->left_margin_cols = w->left_margin_cols;
6405 p->right_margin_cols = w->right_margin_cols;
6406 p->left_fringe_width = w->left_fringe_width;
6407 p->right_fringe_width = w->right_fringe_width;
6408 p->fringes_outside_margins = w->fringes_outside_margins;
6409 p->scroll_bar_width = w->scroll_bar_width;
6410 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6411 p->dedicated = w->dedicated;
6412 p->resize_proportionally = w->resize_proportionally;
6413 if (!NILP (w->buffer))
6415 /* Save w's value of point in the window configuration.
6416 If w is the selected window, then get the value of point
6417 from the buffer; pointm is garbage in the selected window. */
6418 if (EQ (window, selected_window))
6420 p->pointm = Fmake_marker ();
6421 set_marker_both (p->pointm, w->buffer,
6422 BUF_PT (XBUFFER (w->buffer)),
6423 BUF_PT_BYTE (XBUFFER (w->buffer)));
6425 else
6426 p->pointm = Fcopy_marker (w->pointm, Qnil);
6428 p->start = Fcopy_marker (w->start, Qnil);
6429 p->start_at_line_beg = w->start_at_line_beg;
6431 tem = XBUFFER (w->buffer)->mark;
6432 p->mark = Fcopy_marker (tem, Qnil);
6434 else
6436 p->pointm = Qnil;
6437 p->start = Qnil;
6438 p->mark = Qnil;
6439 p->start_at_line_beg = Qnil;
6442 if (NILP (w->parent))
6443 p->parent = Qnil;
6444 else
6445 p->parent = XWINDOW (w->parent)->temslot;
6447 if (NILP (w->prev))
6448 p->prev = Qnil;
6449 else
6450 p->prev = XWINDOW (w->prev)->temslot;
6452 if (!NILP (w->vchild))
6453 i = save_window_save (w->vchild, vector, i);
6454 if (!NILP (w->hchild))
6455 i = save_window_save (w->hchild, vector, i);
6458 return i;
6461 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6462 Scurrent_window_configuration, 0, 1, 0,
6463 doc: /* Return an object representing the current window configuration of FRAME.
6464 If FRAME is nil or omitted, use the selected frame.
6465 This describes the number of windows, their sizes and current buffers,
6466 and for each displayed buffer, where display starts, and the positions of
6467 point and mark. An exception is made for point in the current buffer:
6468 its value is -not- saved.
6469 This also records the currently selected frame, and FRAME's focus
6470 redirection (see `redirect-frame-focus'). */)
6471 (frame)
6472 Lisp_Object frame;
6474 register Lisp_Object tem;
6475 register int n_windows;
6476 register struct save_window_data *data;
6477 register int i;
6478 FRAME_PTR f;
6480 if (NILP (frame))
6481 frame = selected_frame;
6482 CHECK_LIVE_FRAME (frame);
6483 f = XFRAME (frame);
6485 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6486 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6487 PVEC_WINDOW_CONFIGURATION);
6489 data->frame_cols = FRAME_COLS (f);
6490 data->frame_lines = FRAME_LINES (f);
6491 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6492 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6493 data->selected_frame = selected_frame;
6494 data->current_window = FRAME_SELECTED_WINDOW (f);
6495 XSETBUFFER (data->current_buffer, current_buffer);
6496 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6497 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6498 data->root_window = FRAME_ROOT_WINDOW (f);
6499 data->focus_frame = FRAME_FOCUS_FRAME (f);
6500 tem = Fmake_vector (make_number (n_windows), Qnil);
6501 data->saved_windows = tem;
6502 for (i = 0; i < n_windows; i++)
6503 XVECTOR (tem)->contents[i]
6504 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6505 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6506 XSETWINDOW_CONFIGURATION (tem, data);
6507 return (tem);
6510 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6511 0, UNEVALLED, 0,
6512 doc: /* Execute BODY, preserving window sizes and contents.
6513 Return the value of the last form in BODY.
6514 Restore which buffer appears in which window, where display starts,
6515 and the value of point and mark for each window.
6516 Also restore the choice of selected window.
6517 Also restore which buffer is current.
6518 Does not restore the value of point in current buffer.
6519 usage: (save-window-excursion BODY...) */)
6520 (args)
6521 Lisp_Object args;
6523 register Lisp_Object val;
6524 register int count = SPECPDL_INDEX ();
6526 record_unwind_protect (Fset_window_configuration,
6527 Fcurrent_window_configuration (Qnil));
6528 val = Fprogn (args);
6529 return unbind_to (count, val);
6534 /***********************************************************************
6535 Window Split Tree
6536 ***********************************************************************/
6538 static Lisp_Object
6539 window_tree (w)
6540 struct window *w;
6542 Lisp_Object tail = Qnil;
6543 Lisp_Object result = Qnil;
6545 while (w)
6547 Lisp_Object wn;
6549 XSETWINDOW (wn, w);
6550 if (!NILP (w->hchild))
6551 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6552 window_tree (XWINDOW (w->hchild))));
6553 else if (!NILP (w->vchild))
6554 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6555 window_tree (XWINDOW (w->vchild))));
6557 if (NILP (result))
6559 result = tail = Fcons (wn, Qnil);
6561 else
6563 XSETCDR (tail, Fcons (wn, Qnil));
6564 tail = XCDR (tail);
6567 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6570 return result;
6575 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6576 0, 1, 0,
6577 doc: /* Return the window tree for frame FRAME.
6579 The return value is a list of the form (ROOT MINI), where ROOT
6580 represents the window tree of the frame's root window, and MINI
6581 is the frame's minibuffer window.
6583 If the root window is not split, ROOT is the root window itself.
6584 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6585 horizontal split, and t for a vertical split, EDGES gives the combined
6586 size and position of the subwindows in the split, and the rest of the
6587 elements are the subwindows in the split. Each of the subwindows may
6588 again be a window or a list representing a window split, and so on.
6589 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6591 If FRAME is nil or omitted, return information on the currently
6592 selected frame. */)
6593 (frame)
6594 Lisp_Object frame;
6596 FRAME_PTR f;
6598 if (NILP (frame))
6599 frame = selected_frame;
6601 CHECK_FRAME (frame);
6602 f = XFRAME (frame);
6604 if (!FRAME_LIVE_P (f))
6605 return Qnil;
6607 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6611 /***********************************************************************
6612 Marginal Areas
6613 ***********************************************************************/
6615 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6616 2, 3, 0,
6617 doc: /* Set width of marginal areas of window WINDOW.
6618 If WINDOW is nil, set margins of the currently selected window.
6619 Second arg LEFT-WIDTH specifies the number of character cells to
6620 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6621 does the same for the right marginal area. A nil width parameter
6622 means no margin. */)
6623 (window, left_width, right_width)
6624 Lisp_Object window, left_width, right_width;
6626 struct window *w = decode_window (window);
6628 /* Translate negative or zero widths to nil.
6629 Margins that are too wide have to be checked elsewhere. */
6631 if (!NILP (left_width))
6633 CHECK_NUMBER (left_width);
6634 if (XINT (left_width) <= 0)
6635 left_width = Qnil;
6638 if (!NILP (right_width))
6640 CHECK_NUMBER (right_width);
6641 if (XINT (right_width) <= 0)
6642 right_width = Qnil;
6645 if (!EQ (w->left_margin_cols, left_width)
6646 || !EQ (w->right_margin_cols, right_width))
6648 w->left_margin_cols = left_width;
6649 w->right_margin_cols = right_width;
6651 adjust_window_margins (w);
6653 ++windows_or_buffers_changed;
6654 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6657 return Qnil;
6661 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6662 0, 1, 0,
6663 doc: /* Get width of marginal areas of window WINDOW.
6664 If WINDOW is omitted or nil, use the currently selected window.
6665 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6666 If a marginal area does not exist, its width will be returned
6667 as nil. */)
6668 (window)
6669 Lisp_Object window;
6671 struct window *w = decode_window (window);
6672 return Fcons (w->left_margin_cols, w->right_margin_cols);
6677 /***********************************************************************
6678 Fringes
6679 ***********************************************************************/
6681 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6682 2, 4, 0,
6683 doc: /* Set the fringe widths of window WINDOW.
6684 If WINDOW is nil, set the fringe widths of the currently selected
6685 window.
6686 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6687 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6688 fringe width. If a fringe width arg is nil, that means to use the
6689 frame's default fringe width. Default fringe widths can be set with
6690 the command `set-fringe-style'.
6691 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6692 outside of the display margins. By default, fringes are drawn between
6693 display marginal areas and the text area. */)
6694 (window, left_width, right_width, outside_margins)
6695 Lisp_Object window, left_width, right_width, outside_margins;
6697 struct window *w = decode_window (window);
6699 if (!NILP (left_width))
6700 CHECK_NATNUM (left_width);
6701 if (!NILP (right_width))
6702 CHECK_NATNUM (right_width);
6704 /* Do nothing on a tty. */
6705 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6706 && (!EQ (w->left_fringe_width, left_width)
6707 || !EQ (w->right_fringe_width, right_width)
6708 || !EQ (w->fringes_outside_margins, outside_margins)))
6710 w->left_fringe_width = left_width;
6711 w->right_fringe_width = right_width;
6712 w->fringes_outside_margins = outside_margins;
6714 adjust_window_margins (w);
6716 clear_glyph_matrix (w->current_matrix);
6717 w->window_end_valid = Qnil;
6719 ++windows_or_buffers_changed;
6720 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6723 return Qnil;
6727 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6728 0, 1, 0,
6729 doc: /* Get width of fringes of window WINDOW.
6730 If WINDOW is omitted or nil, use the currently selected window.
6731 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6732 (window)
6733 Lisp_Object window;
6735 struct window *w = decode_window (window);
6737 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6738 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6739 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6740 ? Qt : Qnil), Qnil)));
6745 /***********************************************************************
6746 Scroll bars
6747 ***********************************************************************/
6749 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6750 2, 4, 0,
6751 doc: /* Set width and type of scroll bars of window WINDOW.
6752 If window is nil, set scroll bars of the currently selected window.
6753 Second parameter WIDTH specifies the pixel width for the scroll bar;
6754 this is automatically adjusted to a multiple of the frame column width.
6755 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6756 bar: left, right, or nil.
6757 If WIDTH is nil, use the frame's scroll-bar width.
6758 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6759 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6760 (window, width, vertical_type, horizontal_type)
6761 Lisp_Object window, width, vertical_type, horizontal_type;
6763 struct window *w = decode_window (window);
6765 if (!NILP (width))
6767 CHECK_NATNUM (width);
6769 if (XINT (width) == 0)
6770 vertical_type = Qnil;
6773 if (!(NILP (vertical_type)
6774 || EQ (vertical_type, Qleft)
6775 || EQ (vertical_type, Qright)
6776 || EQ (vertical_type, Qt)))
6777 error ("Invalid type of vertical scroll bar");
6779 if (!EQ (w->scroll_bar_width, width)
6780 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6782 w->scroll_bar_width = width;
6783 w->vertical_scroll_bar_type = vertical_type;
6785 adjust_window_margins (w);
6787 clear_glyph_matrix (w->current_matrix);
6788 w->window_end_valid = Qnil;
6790 ++windows_or_buffers_changed;
6791 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6794 return Qnil;
6798 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6799 0, 1, 0,
6800 doc: /* Get width and type of scroll bars of window WINDOW.
6801 If WINDOW is omitted or nil, use the currently selected window.
6802 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6803 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6804 value. */)
6805 (window)
6806 Lisp_Object window;
6808 struct window *w = decode_window (window);
6809 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6810 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6811 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6812 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6813 Fcons (w->vertical_scroll_bar_type,
6814 Fcons (Qnil, Qnil))));
6819 /***********************************************************************
6820 Smooth scrolling
6821 ***********************************************************************/
6823 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6824 doc: /* Return the amount by which WINDOW is scrolled vertically.
6825 Use the selected window if WINDOW is nil or omitted.
6826 Normally, value is a multiple of the canonical character height of WINDOW;
6827 optional second arg PIXELS-P means value is measured in pixels. */)
6828 (window, pixels_p)
6829 Lisp_Object window, pixels_p;
6831 Lisp_Object result;
6832 struct frame *f;
6833 struct window *w;
6835 if (NILP (window))
6836 window = selected_window;
6837 else
6838 CHECK_WINDOW (window);
6839 w = XWINDOW (window);
6840 f = XFRAME (w->frame);
6842 if (FRAME_WINDOW_P (f))
6843 result = (NILP (pixels_p)
6844 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6845 : make_number (-w->vscroll));
6846 else
6847 result = make_number (0);
6848 return result;
6852 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6853 2, 3, 0,
6854 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6855 WINDOW nil means use the selected window. Normally, VSCROLL is a
6856 non-negative multiple of the canonical character height of WINDOW;
6857 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6858 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6859 corresponds to an integral number of pixels. The return value is the
6860 result of this rounding.
6861 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6862 (window, vscroll, pixels_p)
6863 Lisp_Object window, vscroll, pixels_p;
6865 struct window *w;
6866 struct frame *f;
6868 if (NILP (window))
6869 window = selected_window;
6870 else
6871 CHECK_WINDOW (window);
6872 CHECK_NUMBER_OR_FLOAT (vscroll);
6874 w = XWINDOW (window);
6875 f = XFRAME (w->frame);
6877 if (FRAME_WINDOW_P (f))
6879 int old_dy = w->vscroll;
6881 w->vscroll = - (NILP (pixels_p)
6882 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6883 : XFLOATINT (vscroll));
6884 w->vscroll = min (w->vscroll, 0);
6886 if (w->vscroll != old_dy)
6888 /* Adjust glyph matrix of the frame if the virtual display
6889 area becomes larger than before. */
6890 if (w->vscroll < 0 && w->vscroll < old_dy)
6891 adjust_glyphs (f);
6893 /* Prevent redisplay shortcuts. */
6894 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6898 return Fwindow_vscroll (window, pixels_p);
6902 /* Call FN for all leaf windows on frame F. FN is called with the
6903 first argument being a pointer to the leaf window, and with
6904 additional argument USER_DATA. Stops when FN returns 0. */
6906 void
6907 foreach_window (f, fn, user_data)
6908 struct frame *f;
6909 int (* fn) P_ ((struct window *, void *));
6910 void *user_data;
6912 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6913 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6914 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6918 /* Helper function for foreach_window. Call FN for all leaf windows
6919 reachable from W. FN is called with the first argument being a
6920 pointer to the leaf window, and with additional argument USER_DATA.
6921 Stop when FN returns 0. Value is 0 if stopped by FN. */
6923 static int
6924 foreach_window_1 (w, fn, user_data)
6925 struct window *w;
6926 int (* fn) P_ ((struct window *, void *));
6927 void *user_data;
6929 int cont;
6931 for (cont = 1; w && cont;)
6933 if (!NILP (w->hchild))
6934 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6935 else if (!NILP (w->vchild))
6936 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6937 else
6938 cont = fn (w, user_data);
6940 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6943 return cont;
6947 /* Freeze or unfreeze the window start of W unless it is a
6948 mini-window or the selected window. FREEZE_P non-null means freeze
6949 the window start. */
6951 static int
6952 freeze_window_start (w, freeze_p)
6953 struct window *w;
6954 void *freeze_p;
6956 if (MINI_WINDOW_P (w)
6957 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
6958 && (w == XWINDOW (selected_window)
6959 || (MINI_WINDOW_P (XWINDOW (selected_window))
6960 && ! NILP (Vminibuf_scroll_window)
6961 && w == XWINDOW (Vminibuf_scroll_window)))))
6962 freeze_p = NULL;
6964 w->frozen_window_start_p = freeze_p != NULL;
6965 return 1;
6969 /* Freeze or unfreeze the window starts of all leaf windows on frame
6970 F, except the selected window and a mini-window. FREEZE_P non-zero
6971 means freeze the window start. */
6973 void
6974 freeze_window_starts (f, freeze_p)
6975 struct frame *f;
6976 int freeze_p;
6978 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6982 /***********************************************************************
6983 Initialization
6984 ***********************************************************************/
6986 /* Return 1 if window configurations C1 and C2
6987 describe the same state of affairs. This is used by Fequal. */
6990 compare_window_configurations (c1, c2, ignore_positions)
6991 Lisp_Object c1, c2;
6992 int ignore_positions;
6994 register struct save_window_data *d1, *d2;
6995 struct Lisp_Vector *sw1, *sw2;
6996 int i;
6998 CHECK_WINDOW_CONFIGURATION (c1);
6999 CHECK_WINDOW_CONFIGURATION (c2);
7001 d1 = (struct save_window_data *) XVECTOR (c1);
7002 d2 = (struct save_window_data *) XVECTOR (c2);
7003 sw1 = XVECTOR (d1->saved_windows);
7004 sw2 = XVECTOR (d2->saved_windows);
7006 if (d1->frame_cols != d2->frame_cols)
7007 return 0;
7008 if (d1->frame_lines != d2->frame_lines)
7009 return 0;
7010 if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines)
7011 return 0;
7012 if (! EQ (d1->selected_frame, d2->selected_frame))
7013 return 0;
7014 /* Don't compare the current_window field directly.
7015 Instead see w1_is_current and w2_is_current, below. */
7016 if (! EQ (d1->current_buffer, d2->current_buffer))
7017 return 0;
7018 if (! ignore_positions)
7020 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
7021 return 0;
7022 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
7023 return 0;
7025 /* Don't compare the root_window field.
7026 We don't require the two configurations
7027 to use the same window object,
7028 and the two root windows must be equivalent
7029 if everything else compares equal. */
7030 if (! EQ (d1->focus_frame, d2->focus_frame))
7031 return 0;
7033 /* Verify that the two confis have the same number of windows. */
7034 if (sw1->size != sw2->size)
7035 return 0;
7037 for (i = 0; i < sw1->size; i++)
7039 struct saved_window *p1, *p2;
7040 int w1_is_current, w2_is_current;
7042 p1 = SAVED_WINDOW_N (sw1, i);
7043 p2 = SAVED_WINDOW_N (sw2, i);
7045 /* Verify that the current windows in the two
7046 configurations correspond to each other. */
7047 w1_is_current = EQ (d1->current_window, p1->window);
7048 w2_is_current = EQ (d2->current_window, p2->window);
7050 if (w1_is_current != w2_is_current)
7051 return 0;
7053 /* Verify that the corresponding windows do match. */
7054 if (! EQ (p1->buffer, p2->buffer))
7055 return 0;
7056 if (! EQ (p1->left_col, p2->left_col))
7057 return 0;
7058 if (! EQ (p1->top_line, p2->top_line))
7059 return 0;
7060 if (! EQ (p1->total_cols, p2->total_cols))
7061 return 0;
7062 if (! EQ (p1->total_lines, p2->total_lines))
7063 return 0;
7064 if (! EQ (p1->display_table, p2->display_table))
7065 return 0;
7066 if (! EQ (p1->parent, p2->parent))
7067 return 0;
7068 if (! EQ (p1->prev, p2->prev))
7069 return 0;
7070 if (! ignore_positions)
7072 if (! EQ (p1->hscroll, p2->hscroll))
7073 return 0;
7074 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7075 return 0;
7076 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7077 return 0;
7078 if (NILP (Fequal (p1->start, p2->start)))
7079 return 0;
7080 if (NILP (Fequal (p1->pointm, p2->pointm)))
7081 return 0;
7082 if (NILP (Fequal (p1->mark, p2->mark)))
7083 return 0;
7085 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7086 return 0;
7087 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7088 return 0;
7089 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7090 return 0;
7091 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7092 return 0;
7093 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7094 return 0;
7095 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7096 return 0;
7097 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7098 return 0;
7101 return 1;
7104 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7105 Scompare_window_configurations, 2, 2, 0,
7106 doc: /* Compare two window configurations as regards the structure of windows.
7107 This function ignores details such as the values of point and mark
7108 and scrolling positions. */)
7109 (x, y)
7110 Lisp_Object x, y;
7112 if (compare_window_configurations (x, y, 1))
7113 return Qt;
7114 return Qnil;
7117 void
7118 init_window_once ()
7120 struct frame *f = make_initial_frame ();
7121 XSETFRAME (selected_frame, f);
7122 Vterminal_frame = selected_frame;
7123 minibuf_window = f->minibuffer_window;
7124 selected_window = f->selected_window;
7125 last_nonminibuf_frame = f;
7127 window_initialized = 1;
7130 void
7131 init_window ()
7133 Vwindow_list = Qnil;
7136 void
7137 syms_of_window ()
7139 Qscroll_up = intern ("scroll-up");
7140 staticpro (&Qscroll_up);
7142 Qscroll_down = intern ("scroll-down");
7143 staticpro (&Qscroll_down);
7145 Qwindow_size_fixed = intern ("window-size-fixed");
7146 staticpro (&Qwindow_size_fixed);
7147 Fset (Qwindow_size_fixed, Qnil);
7149 staticpro (&Qwindow_configuration_change_hook);
7150 Qwindow_configuration_change_hook
7151 = intern ("window-configuration-change-hook");
7153 Qwindowp = intern ("windowp");
7154 staticpro (&Qwindowp);
7156 Qwindow_configuration_p = intern ("window-configuration-p");
7157 staticpro (&Qwindow_configuration_p);
7159 Qwindow_live_p = intern ("window-live-p");
7160 staticpro (&Qwindow_live_p);
7162 Qdisplay_buffer = intern ("display-buffer");
7163 staticpro (&Qdisplay_buffer);
7165 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
7166 staticpro (&Qtemp_buffer_show_hook);
7168 staticpro (&Vwindow_list);
7170 minibuf_selected_window = Qnil;
7171 staticpro (&minibuf_selected_window);
7173 window_scroll_pixel_based_preserve_x = -1;
7174 window_scroll_pixel_based_preserve_y = -1;
7175 window_scroll_preserve_hpos = -1;
7176 window_scroll_preserve_vpos = -1;
7178 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7179 doc: /* Non-nil means call as function to display a help buffer.
7180 The function is called with one argument, the buffer to be displayed.
7181 Used by `with-output-to-temp-buffer'.
7182 If this function is used, then it must do the entire job of showing
7183 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7184 Vtemp_buffer_show_function = Qnil;
7186 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7187 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7188 Vminibuf_scroll_window = Qnil;
7190 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7191 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7192 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7193 is displayed in the `mode-line' face. */);
7194 mode_line_in_non_selected_windows = 1;
7196 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7197 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7198 Vother_window_scroll_buffer = Qnil;
7200 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7201 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7202 auto_window_vscroll_p = 1;
7204 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7205 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7206 next_screen_context_lines = 2;
7208 DEFVAR_INT ("window-min-height", &window_min_height,
7209 doc: /* Allow deleting windows less than this tall.
7210 The value is measured in line units. If a window wants a modeline it
7211 is counted as one line.
7213 Emacs honors settings of this variable when enlarging or shrinking
7214 windows vertically. A value less than 1 is invalid. */);
7215 window_min_height = 4;
7217 DEFVAR_INT ("window-min-width", &window_min_width,
7218 doc: /* Allow deleting windows less than this wide.
7219 The value is measured in characters and includes any fringes or
7220 the scrollbar.
7222 Emacs honors settings of this variable when enlarging or shrinking
7223 windows horizontally. A value less than 2 is invalid. */);
7224 window_min_width = 10;
7226 DEFVAR_LISP ("scroll-preserve-screen-position",
7227 &Vscroll_preserve_screen_position,
7228 doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
7229 A value of nil means point does not keep its screen position except
7230 at the scroll margin or window boundary respectively.
7231 A value of t means point keeps its screen position if the scroll
7232 command moved it vertically out of the window, e.g. when scrolling
7233 by full screens.
7234 Any other value means point always keeps its screen position. */);
7235 Vscroll_preserve_screen_position = Qnil;
7237 DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type,
7238 doc: /* Type of marker to use for `window-point'. */);
7239 Vwindow_point_insertion_type = Qnil;
7241 DEFVAR_LISP ("window-configuration-change-hook",
7242 &Vwindow_configuration_change_hook,
7243 doc: /* Functions to call when window configuration changes.
7244 The buffer-local part is run once per window, with the relevant window
7245 selected; while the global part is run only once for the modified frame,
7246 with the relevant frame selected. */);
7247 Vwindow_configuration_change_hook = Qnil;
7249 defsubr (&Sselected_window);
7250 defsubr (&Sminibuffer_window);
7251 defsubr (&Swindow_minibuffer_p);
7252 defsubr (&Swindowp);
7253 defsubr (&Swindow_live_p);
7254 defsubr (&Spos_visible_in_window_p);
7255 defsubr (&Swindow_line_height);
7256 defsubr (&Swindow_buffer);
7257 defsubr (&Swindow_height);
7258 defsubr (&Swindow_width);
7259 defsubr (&Swindow_full_width_p);
7260 defsubr (&Swindow_hscroll);
7261 defsubr (&Sset_window_hscroll);
7262 defsubr (&Swindow_redisplay_end_trigger);
7263 defsubr (&Sset_window_redisplay_end_trigger);
7264 defsubr (&Swindow_edges);
7265 defsubr (&Swindow_pixel_edges);
7266 defsubr (&Swindow_inside_edges);
7267 defsubr (&Swindow_inside_pixel_edges);
7268 defsubr (&Scoordinates_in_window_p);
7269 defsubr (&Swindow_at);
7270 defsubr (&Swindow_point);
7271 defsubr (&Swindow_start);
7272 defsubr (&Swindow_end);
7273 defsubr (&Sset_window_point);
7274 defsubr (&Sset_window_start);
7275 defsubr (&Swindow_dedicated_p);
7276 defsubr (&Sset_window_dedicated_p);
7277 defsubr (&Swindow_display_table);
7278 defsubr (&Sset_window_display_table);
7279 defsubr (&Snext_window);
7280 defsubr (&Sprevious_window);
7281 defsubr (&Sother_window);
7282 defsubr (&Sget_lru_window);
7283 defsubr (&Sget_largest_window);
7284 defsubr (&Sget_buffer_window);
7285 defsubr (&Sdelete_other_windows);
7286 defsubr (&Sdelete_windows_on);
7287 defsubr (&Sreplace_buffer_in_windows);
7288 defsubr (&Sdelete_window);
7289 defsubr (&Sset_window_buffer);
7290 defsubr (&Sselect_window);
7291 defsubr (&Sforce_window_update);
7292 defsubr (&Ssplit_window);
7293 defsubr (&Senlarge_window);
7294 defsubr (&Sshrink_window);
7295 defsubr (&Sadjust_window_trailing_edge);
7296 defsubr (&Sscroll_up);
7297 defsubr (&Sscroll_down);
7298 defsubr (&Sscroll_left);
7299 defsubr (&Sscroll_right);
7300 defsubr (&Sother_window_for_scrolling);
7301 defsubr (&Sscroll_other_window);
7302 defsubr (&Sminibuffer_selected_window);
7303 defsubr (&Srecenter);
7304 defsubr (&Swindow_text_height);
7305 defsubr (&Smove_to_window_line);
7306 defsubr (&Swindow_configuration_p);
7307 defsubr (&Swindow_configuration_frame);
7308 defsubr (&Sset_window_configuration);
7309 defsubr (&Scurrent_window_configuration);
7310 defsubr (&Ssave_window_excursion);
7311 defsubr (&Swindow_tree);
7312 defsubr (&Sset_window_margins);
7313 defsubr (&Swindow_margins);
7314 defsubr (&Sset_window_fringes);
7315 defsubr (&Swindow_fringes);
7316 defsubr (&Sset_window_scroll_bars);
7317 defsubr (&Swindow_scroll_bars);
7318 defsubr (&Swindow_vscroll);
7319 defsubr (&Sset_window_vscroll);
7320 defsubr (&Scompare_window_configurations);
7321 defsubr (&Swindow_list);
7322 defsubr (&Swindow_parameters);
7323 defsubr (&Swindow_parameter);
7324 defsubr (&Sset_window_parameter);
7328 void
7329 keys_of_window ()
7331 initial_define_key (control_x_map, '1', "delete-other-windows");
7332 initial_define_key (control_x_map, '2', "split-window");
7333 initial_define_key (control_x_map, '0', "delete-window");
7334 initial_define_key (control_x_map, 'o', "other-window");
7335 initial_define_key (control_x_map, '^', "enlarge-window");
7336 initial_define_key (control_x_map, '<', "scroll-left");
7337 initial_define_key (control_x_map, '>', "scroll-right");
7339 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7340 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7341 initial_define_key (meta_map, 'v', "scroll-down");
7343 initial_define_key (global_map, Ctl('L'), "recenter");
7344 initial_define_key (meta_map, 'r', "move-to-window-line");
7347 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7348 (do not change this comment) */