* lispref/modes.texi (Region to Refontify): Rename from "Region to Fontify".
[emacs.git] / src / window.c
blob3e6062a7153fc34cc7f12af43ddc7d2a268f74dc
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, 2010, 2011
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>
24 #include <setjmp.h>
26 #include "lisp.h"
27 #include "buffer.h"
28 #include "keyboard.h"
29 #include "keymap.h"
30 #include "frame.h"
31 #include "window.h"
32 #include "commands.h"
33 #include "indent.h"
34 #include "termchar.h"
35 #include "disptab.h"
36 #include "dispextern.h"
37 #include "blockinput.h"
38 #include "intervals.h"
39 #include "termhooks.h" /* For FRAME_TERMINAL. */
41 #ifdef HAVE_X_WINDOWS
42 #include "xterm.h"
43 #endif /* HAVE_X_WINDOWS */
44 #ifdef WINDOWSNT
45 #include "w32term.h"
46 #endif
47 #ifdef MSDOS
48 #include "msdos.h"
49 #endif
50 #ifdef HAVE_NS
51 #include "nsterm.h"
52 #endif
55 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
56 Lisp_Object Qdisplay_buffer;
57 Lisp_Object Qscroll_up, Qscroll_down;
58 Lisp_Object Qwindow_size_fixed;
60 extern Lisp_Object Qleft_margin, Qright_margin;
62 static int displayed_window_lines P_ ((struct window *));
63 static struct window *decode_window P_ ((Lisp_Object));
64 static int count_windows P_ ((struct window *));
65 static int get_leaf_windows P_ ((struct window *, struct window **, int));
66 static void window_scroll P_ ((Lisp_Object, int, int, int));
67 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
68 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
69 static int window_min_size_1 P_ ((struct window *, int, int));
70 static int window_min_size_2 P_ ((struct window *, int, int));
71 static int window_min_size P_ ((struct window *, int, int, int, int *));
72 static void size_window P_ ((Lisp_Object, int, int, int, int, int));
73 static int freeze_window_start P_ ((struct window *, void *));
74 static int window_fixed_size_p P_ ((struct window *, int, int));
75 static void enlarge_window P_ ((Lisp_Object, int, int));
76 static Lisp_Object window_list P_ ((void));
77 static int add_window_to_list P_ ((struct window *, void *));
78 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
79 Lisp_Object));
80 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
81 Lisp_Object, int));
82 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
83 Lisp_Object *));
84 static int foreach_window_1 P_ ((struct window *,
85 int (* fn) (struct window *, void *),
86 void *));
87 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
88 static Lisp_Object select_window P_ ((Lisp_Object, Lisp_Object, int));
90 /* This is the window in which the terminal's cursor should
91 be left when nothing is being done with it. This must
92 always be a leaf window, and its buffer is selected by
93 the top level editing loop at the end of each command.
95 This value is always the same as
96 FRAME_SELECTED_WINDOW (selected_frame). */
98 Lisp_Object selected_window;
100 /* A list of all windows for use by next_window and Fwindow_list.
101 Functions creating or deleting windows should invalidate this cache
102 by setting it to nil. */
104 Lisp_Object Vwindow_list;
106 /* The mini-buffer window of the selected frame.
107 Note that you cannot test for mini-bufferness of an arbitrary window
108 by comparing against this; but you can test for mini-bufferness of
109 the selected window. */
111 Lisp_Object minibuf_window;
113 /* Non-nil means it is the window whose mode line should be
114 shown as the selected window when the minibuffer is selected. */
116 Lisp_Object minibuf_selected_window;
118 /* Non-nil means it is the window for C-M-v to scroll
119 when the mini-buffer is selected. */
121 Lisp_Object Vminibuf_scroll_window;
123 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
125 Lisp_Object Vother_window_scroll_buffer;
127 /* Non-nil means it's function to call to display temp buffers. */
129 Lisp_Object Vtemp_buffer_show_function;
131 /* Non-zero means line and page scrolling on tall lines (with images)
132 does partial scrolling by modifying window-vscroll. */
134 int auto_window_vscroll_p;
136 /* Non-zero means to use mode-line-inactive face in all windows but the
137 selected-window and the minibuffer-scroll-window when the
138 minibuffer is active. */
139 int mode_line_in_non_selected_windows;
141 /* If a window gets smaller than either of these, it is removed. */
143 EMACS_INT window_min_height;
144 EMACS_INT window_min_width;
146 /* Hook run at end of temp_output_buffer_show. */
148 Lisp_Object Qtemp_buffer_show_hook;
150 /* Number of lines of continuity in scrolling by screenfuls. */
152 EMACS_INT next_screen_context_lines;
154 /* Incremented for each window created. */
156 static int sequence_number;
158 /* Nonzero after init_window_once has finished. */
160 static int window_initialized;
162 /* Hook to run when window config changes. */
164 static Lisp_Object Qwindow_configuration_change_hook;
165 static Lisp_Object Vwindow_configuration_change_hook;
167 /* Non-nil means scroll commands try to put point
168 at the same screen height as previously. */
170 Lisp_Object Vscroll_preserve_screen_position;
172 /* Non-nil means that text is inserted before window's markers. */
174 Lisp_Object Vwindow_point_insertion_type;
176 /* Incremented by 1 whenever a window is deleted. */
178 int window_deletion_count;
180 /* Used by the function window_scroll_pixel_based */
182 static int window_scroll_pixel_based_preserve_x;
183 static int window_scroll_pixel_based_preserve_y;
185 /* Same for window_scroll_line_based. */
187 static int window_scroll_preserve_hpos;
188 static int window_scroll_preserve_vpos;
190 extern EMACS_INT scroll_margin;
192 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
194 /* If non-nil, then the `recenter' command with a nil argument
195 the entire frame to be redrawn; the special value `tty' causes the
196 frame to be redrawn only if it is a tty frame. */
198 static Lisp_Object Vrecenter_redisplay;
199 extern Lisp_Object Qtty;
202 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
203 doc: /* Return t if OBJECT is a window. */)
204 (object)
205 Lisp_Object object;
207 return WINDOWP (object) ? Qt : Qnil;
210 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
211 doc: /* Return t if OBJECT is a window which is currently visible. */)
212 (object)
213 Lisp_Object object;
215 return WINDOW_LIVE_P (object) ? Qt : Qnil;
218 Lisp_Object
219 make_window ()
221 Lisp_Object val;
222 register struct window *p;
224 p = allocate_window ();
225 ++sequence_number;
226 XSETFASTINT (p->sequence_number, sequence_number);
227 XSETFASTINT (p->left_col, 0);
228 XSETFASTINT (p->top_line, 0);
229 XSETFASTINT (p->total_lines, 0);
230 XSETFASTINT (p->total_cols, 0);
231 XSETFASTINT (p->hscroll, 0);
232 XSETFASTINT (p->min_hscroll, 0);
233 p->orig_top_line = p->orig_total_lines = Qnil;
234 p->start = Fmake_marker ();
235 p->pointm = Fmake_marker ();
236 XSETFASTINT (p->use_time, 0);
237 p->frame = Qnil;
238 p->display_table = Qnil;
239 p->dedicated = Qnil;
240 p->window_parameters = Qnil;
241 p->pseudo_window_p = 0;
242 bzero (&p->cursor, sizeof (p->cursor));
243 bzero (&p->last_cursor, sizeof (p->last_cursor));
244 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
245 p->desired_matrix = p->current_matrix = 0;
246 p->nrows_scale_factor = p->ncols_scale_factor = 1;
247 p->phys_cursor_type = -1;
248 p->phys_cursor_width = -1;
249 p->must_be_updated_p = 0;
250 XSETFASTINT (p->window_end_vpos, 0);
251 XSETFASTINT (p->window_end_pos, 0);
252 p->window_end_valid = Qnil;
253 p->vscroll = 0;
254 XSETWINDOW (val, p);
255 XSETFASTINT (p->last_point, 0);
256 p->frozen_window_start_p = 0;
257 p->last_cursor_off_p = p->cursor_off_p = 0;
258 p->left_margin_cols = Qnil;
259 p->right_margin_cols = Qnil;
260 p->left_fringe_width = Qnil;
261 p->right_fringe_width = Qnil;
262 p->fringes_outside_margins = Qnil;
263 p->scroll_bar_width = Qnil;
264 p->vertical_scroll_bar_type = Qt;
265 p->resize_proportionally = Qnil;
267 Vwindow_list = Qnil;
268 return val;
271 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
272 doc: /* Return the window that the cursor now appears in and commands apply to. */)
275 return selected_window;
278 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
279 doc: /* Return the window used now for minibuffers.
280 If the optional argument FRAME is specified, return the minibuffer window
281 used by that frame. */)
282 (frame)
283 Lisp_Object frame;
285 if (NILP (frame))
286 frame = selected_frame;
287 CHECK_LIVE_FRAME (frame);
288 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
291 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
292 doc: /* Return non-nil if WINDOW is a minibuffer window.
293 WINDOW defaults to the selected window. */)
294 (window)
295 Lisp_Object window;
297 struct window *w = decode_window (window);
298 return MINI_WINDOW_P (w) ? Qt : Qnil;
302 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
303 Spos_visible_in_window_p, 0, 3, 0,
304 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
305 Return nil if that position is scrolled vertically out of view.
306 If a character is only partially visible, nil is returned, unless the
307 optional argument PARTIALLY is non-nil.
308 If POS is only out of view because of horizontal scrolling, return non-nil.
309 If POS is t, it specifies the position of the last visible glyph in WINDOW.
310 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
312 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
313 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
314 where X and Y are the pixel coordinates relative to the top left corner
315 of the window. The remaining elements are omitted if the character after
316 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
317 off-window at the top and bottom of the row, ROWH is the height of the
318 display row, and VPOS is the row number (0-based) containing POS. */)
319 (pos, window, partially)
320 Lisp_Object pos, window, partially;
322 register struct window *w;
323 register int posint;
324 register struct buffer *buf;
325 struct text_pos top;
326 Lisp_Object in_window = Qnil;
327 int rtop, rbot, rowh, vpos, fully_p = 1;
328 int x, y;
330 w = decode_window (window);
331 buf = XBUFFER (w->buffer);
332 SET_TEXT_POS_FROM_MARKER (top, w->start);
334 if (EQ (pos, Qt))
335 posint = -1;
336 else if (!NILP (pos))
338 CHECK_NUMBER_COERCE_MARKER (pos);
339 posint = XINT (pos);
341 else if (w == XWINDOW (selected_window))
342 posint = PT;
343 else
344 posint = XMARKER (w->pointm)->charpos;
346 /* If position is above window start or outside buffer boundaries,
347 or if window start is out of range, position is not visible. */
348 if ((EQ (pos, Qt)
349 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
350 && CHARPOS (top) >= BUF_BEGV (buf)
351 && CHARPOS (top) <= BUF_ZV (buf)
352 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
353 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
354 in_window = Qt;
356 if (!NILP (in_window) && !NILP (partially))
358 Lisp_Object part = Qnil;
359 if (!fully_p)
360 part = list4 (make_number (rtop), make_number (rbot),
361 make_number (rowh), make_number (vpos));
362 in_window = Fcons (make_number (x),
363 Fcons (make_number (y), part));
366 return in_window;
369 DEFUN ("window-line-height", Fwindow_line_height,
370 Swindow_line_height, 0, 2, 0,
371 doc: /* Return height in pixels of text line LINE in window WINDOW.
372 If WINDOW is nil or omitted, use selected window.
374 Return height of current line if LINE is omitted or nil. Return height of
375 header or mode line if LINE is `header-line' and `mode-line'.
376 Otherwise, LINE is a text line number starting from 0. A negative number
377 counts from the end of the window.
379 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
380 in pixels of the visible part of the line, VPOS and YPOS are the
381 vertical position in lines and pixels of the line, relative to the top
382 of the first text line, and OFFBOT is the number of off-window pixels at
383 the bottom of the text line. If there are off-window pixels at the top
384 of the (first) text line, YPOS is negative.
386 Return nil if window display is not up-to-date. In that case, use
387 `pos-visible-in-window-p' to obtain the information. */)
388 (line, window)
389 Lisp_Object line, window;
391 register struct window *w;
392 register struct buffer *b;
393 struct glyph_row *row, *end_row;
394 int max_y, crop, i, n;
396 w = decode_window (window);
398 if (noninteractive
399 || w->pseudo_window_p)
400 return Qnil;
402 CHECK_BUFFER (w->buffer);
403 b = XBUFFER (w->buffer);
405 /* Fail if current matrix is not up-to-date. */
406 if (NILP (w->window_end_valid)
407 || current_buffer->clip_changed
408 || current_buffer->prevent_redisplay_optimizations_p
409 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
410 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
411 return Qnil;
413 if (NILP (line))
415 i = w->cursor.vpos;
416 if (i < 0 || i >= w->current_matrix->nrows
417 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
418 return Qnil;
419 max_y = window_text_bottom_y (w);
420 goto found_row;
423 if (EQ (line, Qheader_line))
425 if (!WINDOW_WANTS_HEADER_LINE_P (w))
426 return Qnil;
427 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
428 if (!row->enabled_p)
429 return Qnil;
430 return list4 (make_number (row->height),
431 make_number (0), make_number (0),
432 make_number (0));
435 if (EQ (line, Qmode_line))
437 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
438 if (!row->enabled_p)
439 return Qnil;
440 return list4 (make_number (row->height),
441 make_number (0), /* not accurate */
442 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
443 + window_text_bottom_y (w)),
444 make_number (0));
447 CHECK_NUMBER (line);
448 n = XINT (line);
450 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
451 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
452 max_y = window_text_bottom_y (w);
453 i = 0;
455 while ((n < 0 || i < n)
456 && row <= end_row && row->enabled_p
457 && row->y + row->height < max_y)
458 row++, i++;
460 if (row > end_row || !row->enabled_p)
461 return Qnil;
463 if (++n < 0)
465 if (-n > i)
466 return Qnil;
467 row += n;
468 i += n;
471 found_row:
472 crop = max (0, (row->y + row->height) - max_y);
473 return list4 (make_number (row->height + min (0, row->y) - crop),
474 make_number (i),
475 make_number (row->y),
476 make_number (crop));
481 static struct window *
482 decode_window (window)
483 register Lisp_Object window;
485 if (NILP (window))
486 return XWINDOW (selected_window);
488 CHECK_LIVE_WINDOW (window);
489 return XWINDOW (window);
492 static struct window *
493 decode_any_window (window)
494 register Lisp_Object window;
496 if (NILP (window))
497 return XWINDOW (selected_window);
499 CHECK_WINDOW (window);
500 return XWINDOW (window);
503 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
504 doc: /* Return the buffer that WINDOW is displaying.
505 WINDOW defaults to the selected window. */)
506 (window)
507 Lisp_Object window;
509 return decode_window (window)->buffer;
512 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
513 doc: /* Return the number of lines in WINDOW.
514 WINDOW defaults to the selected window.
516 The return value includes WINDOW's mode line and header line, if any.
518 Note: The function does not take into account the value of `line-spacing'
519 when calculating the number of lines in WINDOW. */)
520 (window)
521 Lisp_Object window;
523 return decode_any_window (window)->total_lines;
526 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
527 doc: /* Return the number of display columns in WINDOW.
528 WINDOW defaults to the selected window.
530 Note: The return value is the number of columns available for text in
531 WINDOW. If you want to find out how many columns WINDOW takes up, use
532 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
533 (window)
534 Lisp_Object window;
536 return make_number (window_box_text_cols (decode_any_window (window)));
539 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
540 doc: /* Return t if WINDOW is as wide as its frame.
541 WINDOW defaults to the selected window. */)
542 (window)
543 Lisp_Object window;
545 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
548 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
549 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
550 WINDOW defaults to the selected window. */)
551 (window)
552 Lisp_Object window;
554 return decode_window (window)->hscroll;
557 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
558 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
559 Return NCOL. NCOL should be zero or positive.
561 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
562 window so that the location of point moves off-window. */)
563 (window, ncol)
564 Lisp_Object window, ncol;
566 struct window *w = decode_window (window);
567 int hscroll;
569 CHECK_NUMBER (ncol);
570 hscroll = max (0, XINT (ncol));
572 /* Prevent redisplay shortcuts when changing the hscroll. */
573 if (XINT (w->hscroll) != hscroll)
574 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
576 w->hscroll = make_number (hscroll);
577 return ncol;
580 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
581 Swindow_redisplay_end_trigger, 0, 1, 0,
582 doc: /* Return WINDOW's redisplay end trigger value.
583 WINDOW defaults to the selected window.
584 See `set-window-redisplay-end-trigger' for more information. */)
585 (window)
586 Lisp_Object window;
588 return decode_window (window)->redisplay_end_trigger;
591 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
592 Sset_window_redisplay_end_trigger, 2, 2, 0,
593 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
594 VALUE should be a buffer position (typically a marker) or nil.
595 If it is a buffer position, then if redisplay in WINDOW reaches a position
596 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
597 with two arguments: WINDOW, and the end trigger value.
598 Afterwards the end-trigger value is reset to nil. */)
599 (window, value)
600 register Lisp_Object window, value;
602 register struct window *w;
604 w = decode_window (window);
605 w->redisplay_end_trigger = value;
606 return value;
609 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
610 doc: /* Return a list of the edge coordinates of WINDOW.
611 The list has the form (LEFT TOP RIGHT BOTTOM).
612 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
613 all relative to 0, 0 at top left corner of frame.
615 RIGHT is one more than the rightmost column occupied by WINDOW.
616 BOTTOM is one more than the bottommost row occupied by WINDOW.
617 The edges include the space used by WINDOW's scroll bar, display
618 margins, fringes, header line, and/or mode line. For the edges of
619 just the text area, use `window-inside-edges'. */)
620 (window)
621 Lisp_Object window;
623 register struct window *w = decode_any_window (window);
625 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
626 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
627 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
628 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
629 Qnil))));
632 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
633 doc: /* Return a list of the edge pixel coordinates of WINDOW.
634 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
635 the top left corner of the frame.
637 RIGHT is one more than the rightmost x position occupied by WINDOW.
638 BOTTOM is one more than the bottommost y position occupied by WINDOW.
639 The pixel edges include the space used by WINDOW's scroll bar, display
640 margins, fringes, header line, and/or mode line. For the pixel edges
641 of just the text area, use `window-inside-pixel-edges'. */)
642 (window)
643 Lisp_Object window;
645 register struct window *w = decode_any_window (window);
647 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
648 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
649 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
650 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
651 Qnil))));
654 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
655 doc: /* Return a list of the edge coordinates of WINDOW.
656 The list has the form (LEFT TOP RIGHT BOTTOM).
657 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
658 all relative to 0, 0 at top left corner of frame.
660 RIGHT is one more than the rightmost column of WINDOW's text area.
661 BOTTOM is one more than the bottommost row of WINDOW's text area.
662 The inside edges do not include the space used by the WINDOW's scroll
663 bar, display margins, fringes, header line, and/or mode line. */)
664 (window)
665 Lisp_Object window;
667 register struct window *w = decode_any_window (window);
669 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
670 + WINDOW_LEFT_MARGIN_COLS (w)
671 + WINDOW_LEFT_FRINGE_COLS (w)),
672 make_number (WINDOW_TOP_EDGE_LINE (w)
673 + WINDOW_HEADER_LINE_LINES (w)),
674 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
675 - WINDOW_RIGHT_MARGIN_COLS (w)
676 - WINDOW_RIGHT_FRINGE_COLS (w)),
677 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
678 - WINDOW_MODE_LINE_LINES (w)));
681 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
682 doc: /* Return a list of the edge pixel coordinates of WINDOW.
683 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
684 the top left corner of the frame.
686 RIGHT is one more than the rightmost x position of WINDOW's text area.
687 BOTTOM is one more than the bottommost y position of WINDOW's text area.
688 The inside edges do not include the space used by WINDOW's scroll bar,
689 display margins, fringes, header line, and/or mode line. */)
690 (window)
691 Lisp_Object window;
693 register struct window *w = decode_any_window (window);
695 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
696 + WINDOW_LEFT_MARGIN_WIDTH (w)
697 + WINDOW_LEFT_FRINGE_WIDTH (w)),
698 make_number (WINDOW_TOP_EDGE_Y (w)
699 + WINDOW_HEADER_LINE_HEIGHT (w)),
700 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
701 - WINDOW_RIGHT_MARGIN_WIDTH (w)
702 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
703 make_number (WINDOW_BOTTOM_EDGE_Y (w)
704 - WINDOW_MODE_LINE_HEIGHT (w)));
707 /* Test if the character at column *X, row *Y is within window W.
708 If it is not, return ON_NOTHING;
709 if it is in the window's text area,
710 set *x and *y to its location relative to the upper left corner
711 of the window, and
712 return ON_TEXT;
713 if it is on the window's modeline, return ON_MODE_LINE;
714 if it is on the border between the window and its right sibling,
715 return ON_VERTICAL_BORDER.
716 if it is on a scroll bar,
717 return ON_SCROLL_BAR.
718 if it is on the window's top line, return ON_HEADER_LINE;
719 if it is in left or right fringe of the window,
720 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
721 to window-relative coordinates;
722 if it is in the marginal area to the left/right of the window,
723 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
724 to window-relative coordinates.
726 X and Y are frame relative pixel coordinates. */
728 static enum window_part
729 coordinates_in_window (w, x, y)
730 register struct window *w;
731 register int *x, *y;
733 struct frame *f = XFRAME (WINDOW_FRAME (w));
734 int left_x, right_x, top_y, bottom_y;
735 enum window_part part;
736 int ux = FRAME_COLUMN_WIDTH (f);
737 int x0 = WINDOW_LEFT_EDGE_X (w);
738 int x1 = WINDOW_RIGHT_EDGE_X (w);
739 /* The width of the area where the vertical line can be dragged.
740 (Between mode lines for instance. */
741 int grabbable_width = ux;
742 int lmargin_width, rmargin_width, text_left, text_right;
744 /* In what's below, we subtract 1 when computing right_x because we
745 want the rightmost pixel, which is given by left_pixel+width-1. */
746 if (w->pseudo_window_p)
748 left_x = 0;
749 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
750 top_y = WINDOW_TOP_EDGE_Y (w);
751 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
753 else
755 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
756 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
757 top_y = WINDOW_TOP_EDGE_Y (w);
758 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
761 /* Outside any interesting row? */
762 if (*y < top_y || *y >= bottom_y)
763 return ON_NOTHING;
765 /* On the mode line or header line? If it's near the start of
766 the mode or header line of window that's has a horizontal
767 sibling, say it's on the vertical line. That's to be able
768 to resize windows horizontally in case we're using toolkit
769 scroll bars. */
771 if (WINDOW_WANTS_MODELINE_P (w)
772 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
774 part = ON_MODE_LINE;
776 header_vertical_border_check:
777 /* We're somewhere on the mode line. We consider the place
778 between mode lines of horizontally adjacent mode lines
779 as the vertical border. If scroll bars on the left,
780 return the right window. */
781 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
782 || WINDOW_RIGHTMOST_P (w))
784 if (!WINDOW_LEFTMOST_P (w) && eabs (*x - x0) < grabbable_width)
786 /* Convert X and Y to window relative coordinates.
787 Vertical border is at the left edge of window. */
788 *x = max (0, *x - x0);
789 *y -= top_y;
790 return ON_VERTICAL_BORDER;
793 else
795 /* Make sure we're not at the rightmost position of a
796 mode-/header-line and there's yet another window on
797 the right. (Bug#1372) */
798 if ((WINDOW_RIGHTMOST_P (w) || *x < x1)
799 && eabs (*x - x1) < grabbable_width)
801 /* Convert X and Y to window relative coordinates.
802 Vertical border is at the right edge of window. */
803 *x = min (x1, *x) - x0;
804 *y -= top_y;
805 return ON_VERTICAL_BORDER;
809 if (*x < x0 || *x >= x1)
810 return ON_NOTHING;
812 /* Convert X and Y to window relative coordinates.
813 Mode line starts at left edge of window. */
814 *x -= x0;
815 *y -= top_y;
816 return part;
819 if (WINDOW_WANTS_HEADER_LINE_P (w)
820 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
822 part = ON_HEADER_LINE;
823 goto header_vertical_border_check;
826 if (*x < x0 || *x >= x1)
827 return ON_NOTHING;
829 /* Outside any interesting column? */
830 if (*x < left_x || *x > right_x)
832 *y -= top_y;
833 return ON_SCROLL_BAR;
836 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
837 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
839 text_left = window_box_left (w, TEXT_AREA);
840 text_right = text_left + window_box_width (w, TEXT_AREA);
842 if (FRAME_WINDOW_P (f))
844 if (!w->pseudo_window_p
845 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
846 && !WINDOW_RIGHTMOST_P (w)
847 && (eabs (*x - right_x) < grabbable_width))
849 /* Convert X and Y to window relative coordinates.
850 Vertical border is at the right edge of window. */
851 *x = min (right_x, *x) - left_x;
852 *y -= top_y;
853 return ON_VERTICAL_BORDER;
856 else
858 /* Need to say "*x > right_x" rather than >=, since on character
859 terminals, the vertical line's x coordinate is right_x. */
860 if (!w->pseudo_window_p
861 && !WINDOW_RIGHTMOST_P (w)
862 && *x > right_x - ux)
864 /* On the border on the right side of the window? Assume that
865 this area begins at RIGHT_X minus a canonical char width. */
866 *x = min (right_x, *x) - left_x;
867 *y -= top_y;
868 return ON_VERTICAL_BORDER;
872 if (*x < text_left)
874 if (lmargin_width > 0
875 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
876 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
877 : (*x < left_x + lmargin_width)))
879 *x -= left_x;
880 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
881 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
882 *y -= top_y;
883 return ON_LEFT_MARGIN;
886 /* Convert X and Y to window-relative pixel coordinates. */
887 *x -= left_x;
888 *y -= top_y;
889 return ON_LEFT_FRINGE;
892 if (*x >= text_right)
894 if (rmargin_width > 0
895 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
896 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
897 : (*x >= right_x - rmargin_width)))
899 *x -= right_x - rmargin_width;
900 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
901 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
902 *y -= top_y;
903 return ON_RIGHT_MARGIN;
906 /* Convert X and Y to window-relative pixel coordinates. */
907 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
908 *y -= top_y;
909 return ON_RIGHT_FRINGE;
912 /* Everything special ruled out - must be on text area */
913 *x -= text_left;
914 *y -= top_y;
915 return ON_TEXT;
919 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
920 Scoordinates_in_window_p, 2, 2, 0,
921 doc: /* Return non-nil if COORDINATES are in WINDOW.
922 COORDINATES is a cons of the form (X . Y), X and Y being distances
923 measured in characters from the upper-left corner of the frame.
924 \(0 . 0) denotes the character in the upper left corner of the
925 frame.
926 If COORDINATES are in the text portion of WINDOW,
927 the coordinates relative to the window are returned.
928 If they are in the mode line of WINDOW, `mode-line' is returned.
929 If they are in the top mode line of WINDOW, `header-line' is returned.
930 If they are in the left fringe of WINDOW, `left-fringe' is returned.
931 If they are in the right fringe of WINDOW, `right-fringe' is returned.
932 If they are on the border between WINDOW and its right sibling,
933 `vertical-line' is returned.
934 If they are in the windows's left or right marginal areas, `left-margin'\n\
935 or `right-margin' is returned. */)
936 (coordinates, window)
937 register Lisp_Object coordinates, window;
939 struct window *w;
940 struct frame *f;
941 int x, y;
942 Lisp_Object lx, ly;
944 CHECK_WINDOW (window);
945 w = XWINDOW (window);
946 f = XFRAME (w->frame);
947 CHECK_CONS (coordinates);
948 lx = Fcar (coordinates);
949 ly = Fcdr (coordinates);
950 CHECK_NUMBER_OR_FLOAT (lx);
951 CHECK_NUMBER_OR_FLOAT (ly);
952 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
953 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
955 switch (coordinates_in_window (w, &x, &y))
957 case ON_NOTHING:
958 return Qnil;
960 case ON_TEXT:
961 /* X and Y are now window relative pixel coordinates. Convert
962 them to canonical char units before returning them. */
963 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
964 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
966 case ON_MODE_LINE:
967 return Qmode_line;
969 case ON_VERTICAL_BORDER:
970 return Qvertical_line;
972 case ON_HEADER_LINE:
973 return Qheader_line;
975 case ON_LEFT_FRINGE:
976 return Qleft_fringe;
978 case ON_RIGHT_FRINGE:
979 return Qright_fringe;
981 case ON_LEFT_MARGIN:
982 return Qleft_margin;
984 case ON_RIGHT_MARGIN:
985 return Qright_margin;
987 case ON_SCROLL_BAR:
988 /* Historically we are supposed to return nil in this case. */
989 return Qnil;
991 default:
992 abort ();
997 /* Callback for foreach_window, used in window_from_coordinates.
998 Check if window W contains coordinates specified by USER_DATA which
999 is actually a pointer to a struct check_window_data CW.
1001 Check if window W contains coordinates *CW->x and *CW->y. If it
1002 does, return W in *CW->window, as Lisp_Object, and return in
1003 *CW->part the part of the window under coordinates *X,*Y. Return
1004 zero from this function to stop iterating over windows. */
1006 struct check_window_data
1008 Lisp_Object *window;
1009 int *x, *y;
1010 enum window_part *part;
1013 static int
1014 check_window_containing (w, user_data)
1015 struct window *w;
1016 void *user_data;
1018 struct check_window_data *cw = (struct check_window_data *) user_data;
1019 enum window_part found;
1020 int continue_p = 1;
1022 found = coordinates_in_window (w, cw->x, cw->y);
1023 if (found != ON_NOTHING)
1025 *cw->part = found;
1026 XSETWINDOW (*cw->window, w);
1027 continue_p = 0;
1030 return continue_p;
1034 /* Find the window containing frame-relative pixel position X/Y and
1035 return it as a Lisp_Object.
1037 If X, Y is on one of the window's special `window_part' elements,
1038 set *PART to the id of that element, and return X and Y converted
1039 to window relative coordinates in WX and WY.
1041 If there is no window under X, Y return nil and leave *PART
1042 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1044 This function was previously implemented with a loop cycling over
1045 windows with Fnext_window, and starting with the frame's selected
1046 window. It turned out that this doesn't work with an
1047 implementation of next_window using Vwindow_list, because
1048 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1049 tree of F when this function is called asynchronously from
1050 note_mouse_highlight. The original loop didn't terminate in this
1051 case. */
1053 Lisp_Object
1054 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1055 struct frame *f;
1056 int x, y;
1057 enum window_part *part;
1058 int *wx, *wy;
1059 int tool_bar_p;
1061 Lisp_Object window;
1062 struct check_window_data cw;
1063 enum window_part dummy;
1065 if (part == 0)
1066 part = &dummy;
1068 window = Qnil;
1069 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1070 foreach_window (f, check_window_containing, &cw);
1072 /* If not found above, see if it's in the tool bar window, if a tool
1073 bar exists. */
1074 if (NILP (window)
1075 && tool_bar_p
1076 && WINDOWP (f->tool_bar_window)
1077 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1078 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1079 != ON_NOTHING))
1081 *part = ON_TEXT;
1082 window = f->tool_bar_window;
1085 if (wx) *wx = x;
1086 if (wy) *wy = y;
1088 return window;
1091 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1092 doc: /* Return window containing coordinates X and Y on FRAME.
1093 If omitted, FRAME defaults to the currently selected frame.
1094 The top left corner of the frame is considered to be row 0,
1095 column 0. */)
1096 (x, y, frame)
1097 Lisp_Object x, y, frame;
1099 struct frame *f;
1101 if (NILP (frame))
1102 frame = selected_frame;
1103 CHECK_LIVE_FRAME (frame);
1104 f = XFRAME (frame);
1106 /* Check that arguments are integers or floats. */
1107 CHECK_NUMBER_OR_FLOAT (x);
1108 CHECK_NUMBER_OR_FLOAT (y);
1110 return window_from_coordinates (f,
1111 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1112 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1113 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1114 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1115 0, 0, 0, 0);
1118 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1119 doc: /* Return current value of point in WINDOW.
1120 WINDOW defaults to the selected window.
1122 For a nonselected window, this is the value point would have
1123 if that window were selected.
1125 Note that, when WINDOW is the selected window and its buffer
1126 is also currently selected, the value returned is the same as (point).
1127 It would be more strictly correct to return the `top-level' value
1128 of point, outside of any save-excursion forms.
1129 But that is hard to define. */)
1130 (window)
1131 Lisp_Object window;
1133 register struct window *w = decode_window (window);
1135 if (w == XWINDOW (selected_window)
1136 && current_buffer == XBUFFER (w->buffer))
1137 return Fpoint ();
1138 return Fmarker_position (w->pointm);
1141 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1142 doc: /* Return position at which display currently starts in WINDOW.
1143 WINDOW defaults to the selected window.
1144 This is updated by redisplay or by calling `set-window-start'. */)
1145 (window)
1146 Lisp_Object window;
1148 return Fmarker_position (decode_window (window)->start);
1151 /* This is text temporarily removed from the doc string below.
1153 This function returns nil if the position is not currently known.
1154 That happens when redisplay is preempted and doesn't finish.
1155 If in that case you want to compute where the end of the window would
1156 have been if redisplay had finished, do this:
1157 (save-excursion
1158 (goto-char (window-start window))
1159 (vertical-motion (1- (window-height window)) window)
1160 (point))") */
1162 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1163 doc: /* Return position at which display currently ends in WINDOW.
1164 WINDOW defaults to the selected window.
1165 This is updated by redisplay, when it runs to completion.
1166 Simply changing the buffer text or setting `window-start'
1167 does not update this value.
1168 Return nil if there is no recorded value. \(This can happen if the
1169 last redisplay of WINDOW was preempted, and did not finish.)
1170 If UPDATE is non-nil, compute the up-to-date position
1171 if it isn't already recorded. */)
1172 (window, update)
1173 Lisp_Object window, update;
1175 Lisp_Object value;
1176 struct window *w = decode_window (window);
1177 Lisp_Object buf;
1178 struct buffer *b;
1180 buf = w->buffer;
1181 CHECK_BUFFER (buf);
1182 b = XBUFFER (buf);
1184 #if 0 /* This change broke some things. We should make it later. */
1185 /* If we don't know the end position, return nil.
1186 The user can compute it with vertical-motion if he wants to.
1187 It would be nicer to do it automatically,
1188 but that's so slow that it would probably bother people. */
1189 if (NILP (w->window_end_valid))
1190 return Qnil;
1191 #endif
1193 if (! NILP (update)
1194 && ! (! NILP (w->window_end_valid)
1195 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1196 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1197 && !noninteractive)
1199 struct text_pos startp;
1200 struct it it;
1201 struct buffer *old_buffer = NULL;
1203 /* Cannot use Fvertical_motion because that function doesn't
1204 cope with variable-height lines. */
1205 if (b != current_buffer)
1207 old_buffer = current_buffer;
1208 set_buffer_internal (b);
1211 /* In case W->start is out of the range, use something
1212 reasonable. This situation occurred when loading a file with
1213 `-l' containing a call to `rmail' with subsequent other
1214 commands. At the end, W->start happened to be BEG, while
1215 rmail had already narrowed the buffer. */
1216 if (XMARKER (w->start)->charpos < BEGV)
1217 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1218 else if (XMARKER (w->start)->charpos > ZV)
1219 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1220 else
1221 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1223 start_display (&it, w, startp);
1224 move_it_vertically (&it, window_box_height (w));
1225 if (it.current_y < it.last_visible_y)
1226 move_it_past_eol (&it);
1227 value = make_number (IT_CHARPOS (it));
1229 if (old_buffer)
1230 set_buffer_internal (old_buffer);
1232 else
1233 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1235 return value;
1238 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1239 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1240 Return POS. */)
1241 (window, pos)
1242 Lisp_Object window, pos;
1244 register struct window *w = decode_window (window);
1246 CHECK_NUMBER_COERCE_MARKER (pos);
1247 if (w == XWINDOW (selected_window)
1248 && XBUFFER (w->buffer) == current_buffer)
1249 Fgoto_char (pos);
1250 else
1251 set_marker_restricted (w->pointm, pos, w->buffer);
1253 /* We have to make sure that redisplay updates the window to show
1254 the new value of point. */
1255 if (!EQ (window, selected_window))
1256 ++windows_or_buffers_changed;
1258 return pos;
1261 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1262 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1263 WINDOW defaults to the selected window. Return POS.
1264 Optional third arg NOFORCE non-nil inhibits next redisplay from
1265 overriding motion of point in order to display at this exact start. */)
1266 (window, pos, noforce)
1267 Lisp_Object window, pos, noforce;
1269 register struct window *w = decode_window (window);
1271 CHECK_NUMBER_COERCE_MARKER (pos);
1272 set_marker_restricted (w->start, pos, w->buffer);
1273 /* this is not right, but much easier than doing what is right. */
1274 w->start_at_line_beg = Qnil;
1275 if (NILP (noforce))
1276 w->force_start = Qt;
1277 w->update_mode_line = Qt;
1278 XSETFASTINT (w->last_modified, 0);
1279 XSETFASTINT (w->last_overlay_modified, 0);
1280 if (!EQ (window, selected_window))
1281 windows_or_buffers_changed++;
1283 return pos;
1287 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1288 0, 1, 0,
1289 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1290 More precisely, return the value assigned by the last call of
1291 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1292 never called with WINDOW as its argument, or the value set by that
1293 function was internally reset since its last call. WINDOW defaults to
1294 the selected window.
1296 When a window is dedicated to its buffer, `display-buffer' will refrain
1297 from displaying another buffer in it. `get-lru-window' and
1298 `get-largest-window' treat dedicated windows specially.
1299 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1300 `kill-buffer' can delete a dedicated window and the containing frame.
1302 Functions like `set-window-buffer' may change the buffer displayed by a
1303 window, unless that window is "strongly" dedicated to its buffer, that
1304 is the value returned by `window-dedicated-p' is t. */)
1305 (window)
1306 Lisp_Object window;
1308 return decode_window (window)->dedicated;
1311 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1312 Sset_window_dedicated_p, 2, 2, 0,
1313 doc: /* Mark WINDOW as dedicated according to FLAG.
1314 WINDOW defaults to the selected window. FLAG non-nil means mark WINDOW
1315 as dedicated to its buffer. FLAG nil means mark WINDOW as non-dedicated.
1316 Return FLAG.
1318 When a window is dedicated to its buffer, `display-buffer' will refrain
1319 from displaying another buffer in it. `get-lru-window' and
1320 `get-largest-window' treat dedicated windows specially.
1321 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1322 `kill-buffer' can delete a dedicated window and the containing
1323 frame.
1325 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1326 its buffer. Functions like `set-window-buffer' may change the buffer
1327 displayed by a window, unless that window is strongly dedicated to its
1328 buffer. If and when `set-window-buffer' displays another buffer in a
1329 window, it also makes sure that the window is not marked as dedicated. */)
1330 (window, flag)
1331 Lisp_Object window, flag;
1333 register struct window *w = decode_window (window);
1335 w->dedicated = flag;
1336 return w->dedicated;
1340 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1341 0, 1, 0,
1342 doc: /* Return the parameters of WINDOW and their values.
1343 WINDOW defaults to the selected window. The return value is a list of
1344 elements of the form (PARAMETER . VALUE). */)
1345 (window)
1346 Lisp_Object window;
1348 return Fcopy_alist (decode_window (window)->window_parameters);
1351 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1352 2, 2, 0,
1353 doc: /* Return WINDOW's value for PARAMETER.
1354 WINDOW defaults to the selected window. */)
1355 (window, parameter)
1356 Lisp_Object window, parameter;
1358 Lisp_Object result;
1360 result = Fassq (parameter, decode_window (window)->window_parameters);
1361 return CDR_SAFE (result);
1364 DEFUN ("set-window-parameter", Fset_window_parameter,
1365 Sset_window_parameter, 3, 3, 0,
1366 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1367 WINDOW defaults to the selected window. Return VALUE. */)
1368 (window, parameter, value)
1369 Lisp_Object window, parameter, value;
1371 register struct window *w = decode_window (window);
1372 Lisp_Object old_alist_elt;
1374 old_alist_elt = Fassq (parameter, w->window_parameters);
1375 if (NILP (old_alist_elt))
1376 w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
1377 else
1378 Fsetcdr (old_alist_elt, value);
1379 return value;
1383 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1384 0, 1, 0,
1385 doc: /* Return the display-table that WINDOW is using.
1386 WINDOW defaults to the selected window. */)
1387 (window)
1388 Lisp_Object window;
1390 return decode_window (window)->display_table;
1393 /* Get the display table for use on window W. This is either W's
1394 display table or W's buffer's display table. Ignore the specified
1395 tables if they are not valid; if no valid table is specified,
1396 return 0. */
1398 struct Lisp_Char_Table *
1399 window_display_table (w)
1400 struct window *w;
1402 struct Lisp_Char_Table *dp = NULL;
1404 if (DISP_TABLE_P (w->display_table))
1405 dp = XCHAR_TABLE (w->display_table);
1406 else if (BUFFERP (w->buffer))
1408 struct buffer *b = XBUFFER (w->buffer);
1410 if (DISP_TABLE_P (b->display_table))
1411 dp = XCHAR_TABLE (b->display_table);
1412 else if (DISP_TABLE_P (Vstandard_display_table))
1413 dp = XCHAR_TABLE (Vstandard_display_table);
1416 return dp;
1419 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1420 doc: /* Set WINDOW's display-table to TABLE. */)
1421 (window, table)
1422 register Lisp_Object window, table;
1424 register struct window *w;
1426 w = decode_window (window);
1427 w->display_table = table;
1428 return table;
1431 /* Record info on buffer window w is displaying
1432 when it is about to cease to display that buffer. */
1433 static void
1434 unshow_buffer (w)
1435 register struct window *w;
1437 Lisp_Object buf;
1438 struct buffer *b;
1440 buf = w->buffer;
1441 b = XBUFFER (buf);
1442 if (b != XMARKER (w->pointm)->buffer)
1443 abort ();
1445 #if 0
1446 if (w == XWINDOW (selected_window)
1447 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1448 /* Do this except when the selected window's buffer
1449 is being removed from some other window. */
1450 #endif
1451 /* last_window_start records the start position that this buffer
1452 had in the last window to be disconnected from it.
1453 Now that this statement is unconditional,
1454 it is possible for the buffer to be displayed in the
1455 selected window, while last_window_start reflects another
1456 window which was recently showing the same buffer.
1457 Some people might say that might be a good thing. Let's see. */
1458 b->last_window_start = marker_position (w->start);
1460 /* Point in the selected window's buffer
1461 is actually stored in that buffer, and the window's pointm isn't used.
1462 So don't clobber point in that buffer. */
1463 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1464 /* This line helps to fix Horsley's testbug.el bug. */
1465 && !(WINDOWP (b->last_selected_window)
1466 && w != XWINDOW (b->last_selected_window)
1467 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1468 temp_set_point_both (b,
1469 clip_to_bounds (BUF_BEGV (b),
1470 XMARKER (w->pointm)->charpos,
1471 BUF_ZV (b)),
1472 clip_to_bounds (BUF_BEGV_BYTE (b),
1473 marker_byte_position (w->pointm),
1474 BUF_ZV_BYTE (b)));
1476 if (WINDOWP (b->last_selected_window)
1477 && w == XWINDOW (b->last_selected_window))
1478 b->last_selected_window = Qnil;
1481 /* Put replacement into the window structure in place of old. */
1482 static void
1483 replace_window (old, replacement)
1484 Lisp_Object old, replacement;
1486 register Lisp_Object tem;
1487 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1489 /* If OLD is its frame's root_window, then replacement is the new
1490 root_window for that frame. */
1492 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1493 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1495 p->left_col = o->left_col;
1496 p->top_line = o->top_line;
1497 p->total_cols = o->total_cols;
1498 p->total_lines = o->total_lines;
1499 p->desired_matrix = p->current_matrix = 0;
1500 p->vscroll = 0;
1501 bzero (&p->cursor, sizeof (p->cursor));
1502 bzero (&p->last_cursor, sizeof (p->last_cursor));
1503 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1504 p->phys_cursor_type = -1;
1505 p->phys_cursor_width = -1;
1506 p->must_be_updated_p = 0;
1507 p->pseudo_window_p = 0;
1508 XSETFASTINT (p->window_end_vpos, 0);
1509 XSETFASTINT (p->window_end_pos, 0);
1510 p->window_end_valid = Qnil;
1511 p->frozen_window_start_p = 0;
1512 p->orig_top_line = p->orig_total_lines = Qnil;
1514 p->next = tem = o->next;
1515 if (!NILP (tem))
1516 XWINDOW (tem)->prev = replacement;
1518 p->prev = tem = o->prev;
1519 if (!NILP (tem))
1520 XWINDOW (tem)->next = replacement;
1522 p->parent = tem = o->parent;
1523 if (!NILP (tem))
1525 if (EQ (XWINDOW (tem)->vchild, old))
1526 XWINDOW (tem)->vchild = replacement;
1527 if (EQ (XWINDOW (tem)->hchild, old))
1528 XWINDOW (tem)->hchild = replacement;
1531 /*** Here, if replacement is a vertical combination
1532 and so is its new parent, we should make replacement's
1533 children be children of that parent instead. ***/
1536 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1537 doc: /* Remove WINDOW from its frame.
1538 WINDOW defaults to the selected window. Return nil.
1539 Signal an error when WINDOW is the only window on its frame. */)
1540 (window)
1541 register Lisp_Object window;
1543 struct frame *f;
1544 if (NILP (window))
1545 window = selected_window;
1546 else
1547 CHECK_LIVE_WINDOW (window);
1549 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1550 delete_window (window);
1552 run_window_configuration_change_hook (f);
1554 return Qnil;
1557 void
1558 delete_window (window)
1559 register Lisp_Object window;
1561 register Lisp_Object tem, parent, sib;
1562 register struct window *p;
1563 register struct window *par;
1564 struct frame *f;
1566 /* Because this function is called by other C code on non-leaf
1567 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1568 so we can't decode_window here. */
1569 CHECK_WINDOW (window);
1570 p = XWINDOW (window);
1572 /* It's a no-op to delete an already-deleted window. */
1573 if (NILP (p->buffer)
1574 && NILP (p->hchild)
1575 && NILP (p->vchild))
1576 return;
1578 parent = p->parent;
1579 if (NILP (parent))
1580 error ("Attempt to delete minibuffer or sole ordinary window");
1581 par = XWINDOW (parent);
1583 windows_or_buffers_changed++;
1584 Vwindow_list = Qnil;
1585 f = XFRAME (WINDOW_FRAME (p));
1586 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1588 /* Are we trying to delete any frame's selected window? */
1590 Lisp_Object swindow, pwindow;
1592 /* See if the frame's selected window is either WINDOW
1593 or any subwindow of it, by finding all that window's parents
1594 and comparing each one with WINDOW. */
1595 swindow = FRAME_SELECTED_WINDOW (f);
1597 while (1)
1599 pwindow = swindow;
1600 while (!NILP (pwindow))
1602 if (EQ (window, pwindow))
1603 break;
1604 pwindow = XWINDOW (pwindow)->parent;
1607 /* If the window being deleted is not a parent of SWINDOW,
1608 then SWINDOW is ok as the new selected window. */
1609 if (!EQ (window, pwindow))
1610 break;
1611 /* Otherwise, try another window for SWINDOW. */
1612 swindow = Fnext_window (swindow, Qlambda, Qnil);
1614 /* If we get back to the frame's selected window,
1615 it means there was no acceptable alternative,
1616 so we cannot delete. */
1617 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1618 error ("Cannot delete window");
1621 /* If we need to change SWINDOW, do it. */
1622 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1624 /* If we're about to delete the selected window on the
1625 selected frame, then we should use Fselect_window to select
1626 the new window. On the other hand, if we're about to
1627 delete the selected window on any other frame, we shouldn't do
1628 anything but set the frame's selected_window slot. */
1629 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1630 Fselect_window (swindow, Qnil);
1631 else
1632 FRAME_SELECTED_WINDOW (f) = swindow;
1636 /* Now we know we can delete this one. */
1637 window_deletion_count++;
1639 tem = p->buffer;
1640 /* tem is null for dummy parent windows
1641 (which have inferiors but not any contents themselves) */
1642 if (!NILP (tem))
1644 unshow_buffer (p);
1645 unchain_marker (XMARKER (p->pointm));
1646 unchain_marker (XMARKER (p->start));
1649 /* Free window glyph matrices. It is sure that they are allocated
1650 again when ADJUST_GLYPHS is called. Block input so that expose
1651 events and other events that access glyph matrices are not
1652 processed while we are changing them. */
1653 BLOCK_INPUT;
1654 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1656 tem = p->next;
1657 if (!NILP (tem))
1658 XWINDOW (tem)->prev = p->prev;
1660 tem = p->prev;
1661 if (!NILP (tem))
1662 XWINDOW (tem)->next = p->next;
1664 if (EQ (window, par->hchild))
1665 par->hchild = p->next;
1666 if (EQ (window, par->vchild))
1667 par->vchild = p->next;
1669 /* Find one of our siblings to give our space to. */
1670 sib = p->prev;
1671 if (NILP (sib))
1673 /* If p gives its space to its next sibling, that sibling needs
1674 to have its top/left side pulled back to where p's is.
1675 set_window_{height,width} will re-position the sibling's
1676 children. */
1677 sib = p->next;
1678 XWINDOW (sib)->top_line = p->top_line;
1679 XWINDOW (sib)->left_col = p->left_col;
1682 /* Stretch that sibling. */
1683 if (!NILP (par->vchild))
1684 set_window_height (sib,
1685 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1687 if (!NILP (par->hchild))
1688 set_window_width (sib,
1689 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1692 /* If parent now has only one child,
1693 put the child into the parent's place. */
1694 tem = par->hchild;
1695 if (NILP (tem))
1696 tem = par->vchild;
1697 if (NILP (XWINDOW (tem)->next)) {
1698 replace_window (parent, tem);
1699 par = XWINDOW (tem);
1702 /* Since we may be deleting combination windows, we must make sure that
1703 not only p but all its children have been marked as deleted. */
1704 if (! NILP (p->hchild))
1705 delete_all_subwindows (XWINDOW (p->hchild));
1706 else if (! NILP (p->vchild))
1707 delete_all_subwindows (XWINDOW (p->vchild));
1709 /* Mark this window as deleted. */
1710 p->buffer = p->hchild = p->vchild = Qnil;
1712 if (! NILP (par->parent))
1713 par = XWINDOW (par->parent);
1715 /* Check if we have a v/hchild with a v/hchild. In that case remove
1716 one of them. */
1718 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1720 p = XWINDOW (par->vchild);
1721 par->vchild = p->vchild;
1722 tem = p->vchild;
1724 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1726 p = XWINDOW (par->hchild);
1727 par->hchild = p->hchild;
1728 tem = p->hchild;
1730 else
1731 p = 0;
1733 if (p)
1735 while (! NILP (tem)) {
1736 XWINDOW (tem)->parent = p->parent;
1737 if (NILP (XWINDOW (tem)->next))
1738 break;
1739 tem = XWINDOW (tem)->next;
1741 if (! NILP (tem)) {
1742 /* The next of the v/hchild we are removing is now the next of the
1743 last child for the v/hchild:
1744 Before v/hchild -> v/hchild -> next1 -> next2
1746 -> next3
1747 After: v/hchild -> next1 -> next2 -> next3
1749 XWINDOW (tem)->next = p->next;
1750 if (! NILP (p->next))
1751 XWINDOW (p->next)->prev = tem;
1753 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1757 /* Adjust glyph matrices. */
1758 adjust_glyphs (f);
1759 UNBLOCK_INPUT;
1764 /***********************************************************************
1765 Window List
1766 ***********************************************************************/
1768 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1769 pointer. This is a callback function for foreach_window, used in
1770 function window_list. */
1772 static int
1773 add_window_to_list (w, user_data)
1774 struct window *w;
1775 void *user_data;
1777 Lisp_Object *list = (Lisp_Object *) user_data;
1778 Lisp_Object window;
1779 XSETWINDOW (window, w);
1780 *list = Fcons (window, *list);
1781 return 1;
1785 /* Return a list of all windows, for use by next_window. If
1786 Vwindow_list is a list, return that list. Otherwise, build a new
1787 list, cache it in Vwindow_list, and return that. */
1789 static Lisp_Object
1790 window_list ()
1792 if (!CONSP (Vwindow_list))
1794 Lisp_Object tail;
1796 Vwindow_list = Qnil;
1797 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1799 Lisp_Object args[2];
1801 /* We are visiting windows in canonical order, and add
1802 new windows at the front of args[1], which means we
1803 have to reverse this list at the end. */
1804 args[1] = Qnil;
1805 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1806 args[0] = Vwindow_list;
1807 args[1] = Fnreverse (args[1]);
1808 Vwindow_list = Fnconc (2, args);
1812 return Vwindow_list;
1816 /* Value is non-zero if WINDOW satisfies the constraints given by
1817 OWINDOW, MINIBUF and ALL_FRAMES.
1819 MINIBUF t means WINDOW may be minibuffer windows.
1820 `lambda' means WINDOW may not be a minibuffer window.
1821 a window means a specific minibuffer window
1823 ALL_FRAMES t means search all frames,
1824 nil means search just current frame,
1825 `visible' means search just visible frames,
1826 0 means search visible and iconified frames,
1827 a window means search the frame that window belongs to,
1828 a frame means consider windows on that frame, only. */
1830 static int
1831 candidate_window_p (window, owindow, minibuf, all_frames)
1832 Lisp_Object window, owindow, minibuf, all_frames;
1834 struct window *w = XWINDOW (window);
1835 struct frame *f = XFRAME (w->frame);
1836 int candidate_p = 1;
1838 if (!BUFFERP (w->buffer))
1839 candidate_p = 0;
1840 else if (MINI_WINDOW_P (w)
1841 && (EQ (minibuf, Qlambda)
1842 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1844 /* If MINIBUF is `lambda' don't consider any mini-windows.
1845 If it is a window, consider only that one. */
1846 candidate_p = 0;
1848 else if (EQ (all_frames, Qt))
1849 candidate_p = 1;
1850 else if (NILP (all_frames))
1852 xassert (WINDOWP (owindow));
1853 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1855 else if (EQ (all_frames, Qvisible))
1857 FRAME_SAMPLE_VISIBILITY (f);
1858 candidate_p = FRAME_VISIBLE_P (f)
1859 && (FRAME_TERMINAL (XFRAME (w->frame))
1860 == FRAME_TERMINAL (XFRAME (selected_frame)));
1863 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1865 FRAME_SAMPLE_VISIBILITY (f);
1866 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
1867 #ifdef HAVE_X_WINDOWS
1868 /* Yuck!! If we've just created the frame and the
1869 window-manager requested the user to place it
1870 manually, the window may still not be considered
1871 `visible'. I'd argue it should be at least
1872 something like `iconified', but don't know how to do
1873 that yet. --Stef */
1874 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
1875 && !f->output_data.x->has_been_visible)
1876 #endif
1878 && (FRAME_TERMINAL (XFRAME (w->frame))
1879 == FRAME_TERMINAL (XFRAME (selected_frame)));
1881 else if (WINDOWP (all_frames))
1882 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1883 || EQ (XWINDOW (all_frames)->frame, w->frame)
1884 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1885 else if (FRAMEP (all_frames))
1886 candidate_p = EQ (all_frames, w->frame);
1888 return candidate_p;
1892 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1893 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1894 ALL_FRAMES. */
1896 static void
1897 decode_next_window_args (window, minibuf, all_frames)
1898 Lisp_Object *window, *minibuf, *all_frames;
1900 if (NILP (*window))
1901 *window = selected_window;
1902 else
1903 CHECK_LIVE_WINDOW (*window);
1905 /* MINIBUF nil may or may not include minibuffers. Decide if it
1906 does. */
1907 if (NILP (*minibuf))
1908 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1909 else if (!EQ (*minibuf, Qt))
1910 *minibuf = Qlambda;
1912 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1913 => count none of them, or a specific minibuffer window (the
1914 active one) to count. */
1916 /* ALL_FRAMES nil doesn't specify which frames to include. */
1917 if (NILP (*all_frames))
1918 *all_frames = (!EQ (*minibuf, Qlambda)
1919 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1920 : Qnil);
1921 else if (EQ (*all_frames, Qvisible))
1923 else if (EQ (*all_frames, make_number (0)))
1925 else if (FRAMEP (*all_frames))
1927 else if (!EQ (*all_frames, Qt))
1928 *all_frames = Qnil;
1930 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1931 search just current frame, `visible' meaning search just visible
1932 frames, 0 meaning search visible and iconified frames, or a
1933 window, meaning search the frame that window belongs to, or a
1934 frame, meaning consider windows on that frame, only. */
1938 /* Return the next or previous window of WINDOW in cyclic ordering
1939 of windows. NEXT_P non-zero means return the next window. See the
1940 documentation string of next-window for the meaning of MINIBUF and
1941 ALL_FRAMES. */
1943 static Lisp_Object
1944 next_window (window, minibuf, all_frames, next_p)
1945 Lisp_Object window, minibuf, all_frames;
1946 int next_p;
1948 decode_next_window_args (&window, &minibuf, &all_frames);
1950 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1951 return the first window on the frame. */
1952 if (FRAMEP (all_frames)
1953 && !EQ (all_frames, XWINDOW (window)->frame))
1954 return Fframe_first_window (all_frames);
1956 if (next_p)
1958 Lisp_Object list;
1960 /* Find WINDOW in the list of all windows. */
1961 list = Fmemq (window, window_list ());
1963 /* Scan forward from WINDOW to the end of the window list. */
1964 if (CONSP (list))
1965 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1966 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1967 break;
1969 /* Scan from the start of the window list up to WINDOW. */
1970 if (!CONSP (list))
1971 for (list = Vwindow_list;
1972 CONSP (list) && !EQ (XCAR (list), window);
1973 list = XCDR (list))
1974 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1975 break;
1977 if (CONSP (list))
1978 window = XCAR (list);
1980 else
1982 Lisp_Object candidate, list;
1984 /* Scan through the list of windows for candidates. If there are
1985 candidate windows in front of WINDOW, the last one of these
1986 is the one we want. If there are candidates following WINDOW
1987 in the list, again the last one of these is the one we want. */
1988 candidate = Qnil;
1989 for (list = window_list (); CONSP (list); list = XCDR (list))
1991 if (EQ (XCAR (list), window))
1993 if (WINDOWP (candidate))
1994 break;
1996 else if (candidate_window_p (XCAR (list), window, minibuf,
1997 all_frames))
1998 candidate = XCAR (list);
2001 if (WINDOWP (candidate))
2002 window = candidate;
2005 return window;
2009 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2010 doc: /* Return window following WINDOW in cyclic ordering of windows.
2011 WINDOW defaults to the selected window. The optional arguments
2012 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2014 MINIBUF t means consider the minibuffer window even if the
2015 minibuffer is not active. MINIBUF nil or omitted means consider
2016 the minibuffer window only if the minibuffer is active. Any
2017 other value means do not consider the minibuffer window even if
2018 the minibuffer is active.
2020 Several frames may share a single minibuffer; if the minibuffer
2021 is active, all windows on all frames that share that minibuffer
2022 are considered too. Therefore, if you are using a separate
2023 minibuffer frame and the minibuffer is active and MINIBUF says it
2024 counts, `next-window' considers the windows in the frame from
2025 which you entered the minibuffer, as well as the minibuffer
2026 window.
2028 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
2029 frame, plus the minibuffer window if specified by the MINIBUF
2030 argument, see above. If the minibuffer counts, consider all
2031 windows on all frames that share that minibuffer too.
2032 ALL-FRAMES t means consider all windows on all existing frames.
2033 ALL-FRAMES `visible' means consider all windows on all visible
2034 frames.
2035 ALL-FRAMES 0 means consider all windows on all visible and
2036 iconified frames.
2037 ALL-FRAMES a frame means consider all windows on that frame only.
2038 Anything else means consider all windows on WINDOW's frame and no
2039 others.
2041 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2042 `next-window' to iterate through the entire cycle of acceptable
2043 windows, eventually ending up back at the window you started with.
2044 `previous-window' traverses the same cycle, in the reverse order. */)
2045 (window, minibuf, all_frames)
2046 Lisp_Object window, minibuf, all_frames;
2048 return next_window (window, minibuf, all_frames, 1);
2052 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2053 doc: /* Return window preceding WINDOW in cyclic ordering of windows.
2054 WINDOW defaults to the selected window. The optional arguments
2055 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2056 For the precise meaning of these arguments see `next-window'.
2058 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2059 use `previous-window' to iterate through the entire cycle of
2060 acceptable windows, eventually ending up back at the window you
2061 started with. `next-window' traverses the same cycle, in the
2062 reverse order. */)
2063 (window, minibuf, all_frames)
2064 Lisp_Object window, minibuf, all_frames;
2066 return next_window (window, minibuf, all_frames, 0);
2070 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2071 doc: /* Select another window in cyclic ordering of windows.
2072 COUNT specifies the number of windows to skip, starting with the
2073 selected window, before making the selection. If COUNT is
2074 positive, skip COUNT windows forwards. If COUNT is negative,
2075 skip -COUNT windows backwards. COUNT zero means do not skip any
2076 window, so select the selected window. In an interactive call,
2077 COUNT is the numeric prefix argument. Return nil.
2079 This function uses `next-window' for finding the window to select.
2080 The argument ALL-FRAMES has the same meaning as in `next-window',
2081 but the MINIBUF argument of `next-window' is always effectively
2082 nil. */)
2083 (count, all_frames)
2084 Lisp_Object count, all_frames;
2086 Lisp_Object window;
2087 int i;
2089 CHECK_NUMBER (count);
2090 window = selected_window;
2092 for (i = XINT (count); i > 0; --i)
2093 window = Fnext_window (window, Qnil, all_frames);
2094 for (; i < 0; ++i)
2095 window = Fprevious_window (window, Qnil, all_frames);
2097 Fselect_window (window, Qnil);
2098 return Qnil;
2102 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2103 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2104 FRAME nil or omitted means use the selected frame.
2105 WINDOW nil or omitted means use the selected window.
2106 MINIBUF t means include the minibuffer window, even if it isn't active.
2107 MINIBUF nil or omitted means include the minibuffer window only
2108 if it's active.
2109 MINIBUF neither nil nor t means never include the minibuffer window. */)
2110 (frame, minibuf, window)
2111 Lisp_Object frame, minibuf, window;
2113 if (NILP (window))
2114 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2115 CHECK_WINDOW (window);
2116 if (NILP (frame))
2117 frame = selected_frame;
2119 if (!EQ (frame, XWINDOW (window)->frame))
2120 error ("Window is on a different frame");
2122 return window_list_1 (window, minibuf, frame);
2126 /* Return a list of windows in cyclic ordering. Arguments are like
2127 for `next-window'. */
2129 static Lisp_Object
2130 window_list_1 (window, minibuf, all_frames)
2131 Lisp_Object window, minibuf, all_frames;
2133 Lisp_Object tail, list, rest;
2135 decode_next_window_args (&window, &minibuf, &all_frames);
2136 list = Qnil;
2138 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2139 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2140 list = Fcons (XCAR (tail), list);
2142 /* Rotate the list to start with WINDOW. */
2143 list = Fnreverse (list);
2144 rest = Fmemq (window, list);
2145 if (!NILP (rest) && !EQ (rest, list))
2147 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2149 XSETCDR (tail, Qnil);
2150 list = nconc2 (rest, list);
2152 return list;
2157 /* Look at all windows, performing an operation specified by TYPE
2158 with argument OBJ.
2159 If FRAMES is Qt, look at all frames;
2160 Qnil, look at just the selected frame;
2161 Qvisible, look at visible frames;
2162 a frame, just look at windows on that frame.
2163 If MINI is non-zero, perform the operation on minibuffer windows too. */
2165 enum window_loop
2167 WINDOW_LOOP_UNUSED,
2168 GET_BUFFER_WINDOW, /* Arg is buffer */
2169 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2170 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2171 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2172 GET_LARGEST_WINDOW,
2173 UNSHOW_BUFFER, /* Arg is buffer */
2174 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2175 CHECK_ALL_WINDOWS
2178 static Lisp_Object
2179 window_loop (type, obj, mini, frames)
2180 enum window_loop type;
2181 Lisp_Object obj, frames;
2182 int mini;
2184 Lisp_Object window, windows, best_window, frame_arg;
2185 struct frame *f;
2186 struct gcpro gcpro1;
2188 /* If we're only looping through windows on a particular frame,
2189 frame points to that frame. If we're looping through windows
2190 on all frames, frame is 0. */
2191 if (FRAMEP (frames))
2192 f = XFRAME (frames);
2193 else if (NILP (frames))
2194 f = SELECTED_FRAME ();
2195 else
2196 f = NULL;
2198 if (f)
2199 frame_arg = Qlambda;
2200 else if (EQ (frames, make_number (0)))
2201 frame_arg = frames;
2202 else if (EQ (frames, Qvisible))
2203 frame_arg = frames;
2204 else
2205 frame_arg = Qt;
2207 /* frame_arg is Qlambda to stick to one frame,
2208 Qvisible to consider all visible frames,
2209 or Qt otherwise. */
2211 /* Pick a window to start with. */
2212 if (WINDOWP (obj))
2213 window = obj;
2214 else if (f)
2215 window = FRAME_SELECTED_WINDOW (f);
2216 else
2217 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2219 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2220 GCPRO1 (windows);
2221 best_window = Qnil;
2223 for (; CONSP (windows); windows = XCDR (windows))
2225 struct window *w;
2227 window = XCAR (windows);
2228 w = XWINDOW (window);
2230 /* Note that we do not pay attention here to whether the frame
2231 is visible, since Fwindow_list skips non-visible frames if
2232 that is desired, under the control of frame_arg. */
2233 if (!MINI_WINDOW_P (w)
2234 /* For UNSHOW_BUFFER, we must always consider all windows. */
2235 || type == UNSHOW_BUFFER
2236 || (mini && minibuf_level > 0))
2237 switch (type)
2239 case GET_BUFFER_WINDOW:
2240 if (EQ (w->buffer, obj)
2241 /* Don't find any minibuffer window
2242 except the one that is currently in use. */
2243 && (MINI_WINDOW_P (w)
2244 ? EQ (window, minibuf_window)
2245 : 1))
2247 if (NILP (best_window))
2248 best_window = window;
2249 else if (EQ (window, selected_window))
2250 /* Prefer to return selected-window. */
2251 RETURN_UNGCPRO (window);
2252 else if (EQ (Fwindow_frame (window), selected_frame))
2253 /* Prefer windows on the current frame. */
2254 best_window = window;
2256 break;
2258 case GET_LRU_WINDOW:
2259 /* `obj' is an integer encoding a bitvector.
2260 `obj & 1' means consider only full-width windows.
2261 `obj & 2' means consider also dedicated windows. */
2262 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2263 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2264 /* Minibuffer windows are always ignored. */
2265 || MINI_WINDOW_P (w))
2266 break;
2267 if (NILP (best_window)
2268 || (XFASTINT (XWINDOW (best_window)->use_time)
2269 > XFASTINT (w->use_time)))
2270 best_window = window;
2271 break;
2273 case DELETE_OTHER_WINDOWS:
2274 if (!EQ (window, obj))
2275 Fdelete_window (window);
2276 break;
2278 case DELETE_BUFFER_WINDOWS:
2279 if (EQ (w->buffer, obj))
2281 struct frame *f = XFRAME (WINDOW_FRAME (w));
2283 /* If this window is dedicated, and in a frame of its own,
2284 kill the frame. */
2285 if (EQ (window, FRAME_ROOT_WINDOW (f))
2286 && !NILP (w->dedicated)
2287 && other_visible_frames (f))
2289 /* Skip the other windows on this frame.
2290 There might be one, the minibuffer! */
2291 while (CONSP (XCDR (windows))
2292 && EQ (XWINDOW (XCAR (windows))->frame,
2293 XWINDOW (XCAR (XCDR (windows)))->frame))
2294 windows = XCDR (windows);
2296 /* Now we can safely delete the frame. */
2297 delete_frame (w->frame, Qnil);
2299 else if (NILP (w->parent))
2301 /* If we're deleting the buffer displayed in the
2302 only window on the frame, find a new buffer to
2303 display there. */
2304 Lisp_Object buffer;
2305 buffer = Fother_buffer (obj, Qnil, w->frame);
2306 /* Reset dedicated state of window. */
2307 w->dedicated = Qnil;
2308 Fset_window_buffer (window, buffer, Qnil);
2309 if (EQ (window, selected_window))
2310 Fset_buffer (w->buffer);
2312 else
2313 Fdelete_window (window);
2315 break;
2317 case GET_LARGEST_WINDOW:
2318 { /* nil `obj' means to ignore dedicated windows. */
2319 /* Ignore dedicated windows and minibuffers. */
2320 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2321 break;
2323 if (NILP (best_window))
2324 best_window = window;
2325 else
2327 struct window *b = XWINDOW (best_window);
2328 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2329 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2330 best_window = window;
2333 break;
2335 case UNSHOW_BUFFER:
2336 if (EQ (w->buffer, obj))
2338 Lisp_Object buffer;
2339 struct frame *f = XFRAME (w->frame);
2341 /* Find another buffer to show in this window. */
2342 buffer = Fother_buffer (obj, Qnil, w->frame);
2344 /* If this window is dedicated, and in a frame of its own,
2345 kill the frame. */
2346 if (EQ (window, FRAME_ROOT_WINDOW (f))
2347 && !NILP (w->dedicated)
2348 && other_visible_frames (f))
2350 /* Skip the other windows on this frame.
2351 There might be one, the minibuffer! */
2352 while (CONSP (XCDR (windows))
2353 && EQ (XWINDOW (XCAR (windows))->frame,
2354 XWINDOW (XCAR (XCDR (windows)))->frame))
2355 windows = XCDR (windows);
2357 /* Now we can safely delete the frame. */
2358 delete_frame (w->frame, Qnil);
2360 else if (!NILP (w->dedicated) && !NILP (w->parent))
2362 Lisp_Object window;
2363 XSETWINDOW (window, w);
2364 /* If this window is dedicated and not the only window
2365 in its frame, then kill it. */
2366 Fdelete_window (window);
2368 else
2370 /* Otherwise show a different buffer in the window. */
2371 w->dedicated = Qnil;
2372 Fset_window_buffer (window, buffer, Qnil);
2373 if (EQ (window, selected_window))
2374 Fset_buffer (w->buffer);
2377 break;
2379 case REDISPLAY_BUFFER_WINDOWS:
2380 if (EQ (w->buffer, obj))
2382 mark_window_display_accurate (window, 0);
2383 w->update_mode_line = Qt;
2384 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2385 ++update_mode_lines;
2386 best_window = window;
2388 break;
2390 /* Check for a window that has a killed buffer. */
2391 case CHECK_ALL_WINDOWS:
2392 if (! NILP (w->buffer)
2393 && NILP (XBUFFER (w->buffer)->name))
2394 abort ();
2395 break;
2397 case WINDOW_LOOP_UNUSED:
2398 break;
2402 UNGCPRO;
2403 return best_window;
2406 /* Used for debugging. Abort if any window has a dead buffer. */
2408 void
2409 check_all_windows ()
2411 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2414 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2415 doc: /* Return the window least recently selected or used for display.
2416 \(LRU means Least Recently Used.)
2418 Return a full-width window if possible.
2419 A minibuffer window is never a candidate.
2420 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2421 so if all windows are dedicated, the value is nil.
2422 If optional argument FRAME is `visible', search all visible frames.
2423 If FRAME is 0, search all visible and iconified frames.
2424 If FRAME is t, search all frames.
2425 If FRAME is nil, search only the selected frame.
2426 If FRAME is a frame, search only that frame. */)
2427 (frame, dedicated)
2428 Lisp_Object frame, dedicated;
2430 register Lisp_Object w;
2431 /* First try for a window that is full-width */
2432 w = window_loop (GET_LRU_WINDOW,
2433 NILP (dedicated) ? make_number (1) : make_number (3),
2434 0, frame);
2435 if (!NILP (w) && !EQ (w, selected_window))
2436 return w;
2437 /* If none of them, try the rest */
2438 return window_loop (GET_LRU_WINDOW,
2439 NILP (dedicated) ? make_number (0) : make_number (2),
2440 0, frame);
2443 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2444 doc: /* Return the largest window in area.
2445 A minibuffer window is never a candidate.
2446 A dedicated window is never a candidate unless DEDICATED is non-nil,
2447 so if all windows are dedicated, the value is nil.
2448 If optional argument FRAME is `visible', search all visible frames.
2449 If FRAME is 0, search all visible and iconified frames.
2450 If FRAME is t, search all frames.
2451 If FRAME is nil, search only the selected frame.
2452 If FRAME is a frame, search only that frame. */)
2453 (frame, dedicated)
2454 Lisp_Object frame, dedicated;
2456 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2457 frame);
2460 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2461 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2462 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
2463 current buffer.
2464 If optional argument FRAME is `visible', search all visible frames.
2465 If optional argument FRAME is 0, search all visible and iconified frames.
2466 If FRAME is t, search all frames.
2467 If FRAME is nil, search only the selected frame.
2468 If FRAME is a frame, search only that frame. */)
2469 (buffer_or_name, frame)
2470 Lisp_Object buffer_or_name, frame;
2472 Lisp_Object buffer;
2474 if (NILP (buffer_or_name))
2475 buffer = Fcurrent_buffer ();
2476 else
2477 buffer = Fget_buffer (buffer_or_name);
2479 if (BUFFERP (buffer))
2480 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2481 else
2482 return Qnil;
2485 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2486 0, 1, "",
2487 doc: /* Make WINDOW (or the selected window) fill its frame.
2488 Only the frame WINDOW is on is affected.
2489 This function tries to reduce display jumps by keeping the text
2490 previously visible in WINDOW in the same place on the frame. Doing this
2491 depends on the value of (window-start WINDOW), so if calling this
2492 function in a program gives strange scrolling, make sure the
2493 window-start value is reasonable when this function is called. */)
2494 (window)
2495 Lisp_Object window;
2497 struct window *w;
2498 int startpos;
2499 int top, new_top;
2501 if (NILP (window))
2502 window = selected_window;
2503 else
2504 CHECK_LIVE_WINDOW (window);
2505 w = XWINDOW (window);
2507 startpos = marker_position (w->start);
2508 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2510 if (MINI_WINDOW_P (w) && top > 0)
2511 error ("Can't expand minibuffer to full frame");
2513 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2515 /* Try to minimize scrolling, by setting the window start to the point
2516 will cause the text at the old window start to be at the same place
2517 on the frame. But don't try to do this if the window start is
2518 outside the visible portion (as might happen when the display is
2519 not current, due to typeahead). */
2520 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2521 if (new_top != top
2522 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2523 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2525 struct position pos;
2526 struct buffer *obuf = current_buffer;
2528 Fset_buffer (w->buffer);
2529 /* This computation used to temporarily move point, but that can
2530 have unwanted side effects due to text properties. */
2531 pos = *vmotion (startpos, -top, w);
2533 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2534 w->window_end_valid = Qnil;
2535 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2536 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2537 : Qnil);
2538 /* We need to do this, so that the window-scroll-functions
2539 get called. */
2540 w->optional_new_start = Qt;
2542 set_buffer_internal (obuf);
2545 return Qnil;
2548 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2549 0, 2, "bDelete windows on (buffer): ",
2550 doc: /* Delete all windows showing BUFFER-OR-NAME.
2551 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2552 defaults to the current buffer.
2554 Optional second argument FRAME controls which frames are affected.
2555 If optional argument FRAME is `visible', search all visible frames.
2556 If FRAME is 0, search all visible and iconified frames.
2557 If FRAME is nil, search all frames.
2558 If FRAME is t, search only the selected frame.
2559 If FRAME is a frame, search only that frame.
2560 When a window showing BUFFER-OR-NAME is dedicated and the only window of
2561 its frame, that frame is deleted when there are other frames left. */)
2562 (buffer_or_name, frame)
2563 Lisp_Object buffer_or_name, frame;
2565 Lisp_Object buffer;
2567 /* FRAME uses t and nil to mean the opposite of what window_loop
2568 expects. */
2569 if (NILP (frame))
2570 frame = Qt;
2571 else if (EQ (frame, Qt))
2572 frame = Qnil;
2574 if (NILP (buffer_or_name))
2575 buffer = Fcurrent_buffer ();
2576 else
2578 buffer = Fget_buffer (buffer_or_name);
2579 CHECK_BUFFER (buffer);
2582 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2584 return Qnil;
2587 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2588 Sreplace_buffer_in_windows,
2589 0, 1, "bReplace buffer in windows: ",
2590 doc: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2591 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2592 defaults to the current buffer.
2594 When a window showing BUFFER-OR-NAME is dedicated that window is
2595 deleted. If that window is the only window on its frame, that frame is
2596 deleted too when there are other frames left. If there are no other
2597 frames left, some other buffer is displayed in that window. */)
2598 (buffer_or_name)
2599 Lisp_Object buffer_or_name;
2601 Lisp_Object buffer;
2603 if (NILP (buffer_or_name))
2604 buffer = Fcurrent_buffer ();
2605 else
2607 buffer = Fget_buffer (buffer_or_name);
2608 CHECK_BUFFER (buffer);
2611 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2613 return Qnil;
2616 /* Replace BUFFER with some other buffer in all windows
2617 of all frames, even those on other keyboards. */
2619 void
2620 replace_buffer_in_all_windows (buffer)
2621 Lisp_Object buffer;
2623 Lisp_Object tail, frame;
2625 /* A single call to window_loop won't do the job
2626 because it only considers frames on the current keyboard.
2627 So loop manually over frames, and handle each one. */
2628 FOR_EACH_FRAME (tail, frame)
2629 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2632 /* Set the height of WINDOW and all its inferiors. */
2634 /* The smallest acceptable dimensions for a window. Anything smaller
2635 might crash Emacs. */
2637 #define MIN_SAFE_WINDOW_WIDTH (2)
2638 #define MIN_SAFE_WINDOW_HEIGHT (1)
2640 /* For wp non-zero the total number of columns of window w. Otherwise
2641 the total number of lines of w. */
2643 #define WINDOW_TOTAL_SIZE(w, wp) \
2644 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2646 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2647 minimum allowable size. */
2649 void
2650 check_frame_size (frame, rows, cols)
2651 FRAME_PTR frame;
2652 int *rows, *cols;
2654 /* For height, we have to see:
2655 how many windows the frame has at minimum (one or two),
2656 and whether it has a menu bar or other special stuff at the top. */
2657 int min_height
2658 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2659 ? MIN_SAFE_WINDOW_HEIGHT
2660 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2662 if (FRAME_TOP_MARGIN (frame) > 0)
2663 min_height += FRAME_TOP_MARGIN (frame);
2665 if (*rows < min_height)
2666 *rows = min_height;
2667 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2668 *cols = MIN_SAFE_WINDOW_WIDTH;
2671 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2672 check if W's width can be changed, otherwise check W's height.
2673 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2674 siblings, too. If none of the siblings is resizable, WINDOW isn't
2675 either. */
2677 static int
2678 window_fixed_size_p (w, width_p, check_siblings_p)
2679 struct window *w;
2680 int width_p, check_siblings_p;
2682 int fixed_p;
2683 struct window *c;
2685 if (!NILP (w->hchild))
2687 c = XWINDOW (w->hchild);
2689 if (width_p)
2691 /* A horizontal combination is fixed-width if all of if its
2692 children are. */
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 horizontal combination is fixed-height if one of if its
2700 children is. */
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 (!NILP (w->vchild))
2708 c = XWINDOW (w->vchild);
2710 if (width_p)
2712 /* A vertical combination is fixed-width if one of if its
2713 children is. */
2714 while (c && !window_fixed_size_p (c, width_p, 0))
2715 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2716 fixed_p = c != NULL;
2718 else
2720 /* A vertical combination is fixed-height if all of if its
2721 children are. */
2722 while (c && window_fixed_size_p (c, width_p, 0))
2723 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2724 fixed_p = c == NULL;
2727 else if (BUFFERP (w->buffer))
2729 struct buffer *old = current_buffer;
2730 Lisp_Object val;
2732 current_buffer = XBUFFER (w->buffer);
2733 val = find_symbol_value (Qwindow_size_fixed);
2734 current_buffer = old;
2736 fixed_p = 0;
2737 if (!EQ (val, Qunbound))
2739 fixed_p = !NILP (val);
2741 if (fixed_p
2742 && ((EQ (val, Qheight) && width_p)
2743 || (EQ (val, Qwidth) && !width_p)))
2744 fixed_p = 0;
2747 /* Can't tell if this one is resizable without looking at
2748 siblings. If all siblings are fixed-size this one is too. */
2749 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2751 Lisp_Object child;
2753 for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev)
2754 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2755 break;
2757 if (NILP (child))
2758 for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next)
2759 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2760 break;
2762 if (NILP (child))
2763 fixed_p = 1;
2766 else
2767 fixed_p = 1;
2769 return fixed_p;
2772 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2773 the minimum width of W, WIDTH_P zero means return the minimum height
2774 of W. SAFE_P non-zero means ignore window-min-height|width but just
2775 return values that won't crash Emacs and don't hide components like
2776 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2777 minibuffer window, always return 1. */
2779 static int
2780 window_min_size_2 (w, width_p, safe_p)
2781 struct window *w;
2782 int width_p, safe_p;
2784 /* We should consider buffer-local values of window_min_height and
2785 window_min_width here. */
2786 if (width_p)
2788 int safe_size = (MIN_SAFE_WINDOW_WIDTH
2789 + WINDOW_FRINGE_COLS (w)
2790 + WINDOW_SCROLL_BAR_COLS (w));
2792 return safe_p ? safe_size : max (window_min_width, safe_size);
2794 else if (MINI_WINDOW_P (w))
2795 return 1;
2796 else
2798 int safe_size = (MIN_SAFE_WINDOW_HEIGHT
2799 + ((BUFFERP (w->buffer)
2800 && !NILP (XBUFFER (w->buffer)->mode_line_format))
2801 ? 1 : 0));
2803 return safe_p ? safe_size : max (window_min_height, safe_size);
2807 /* Return minimum size of window W, not taking fixed-width windows into
2808 account. WIDTH_P non-zero means return the minimum width, otherwise
2809 return the minimum height. SAFE_P non-zero means ignore
2810 window-min-height|width but just return values that won't crash Emacs
2811 and don't hide components like fringes, scrollbars, or modelines. If
2812 W is a combination window, compute the minimum size from the minimum
2813 sizes of W's children. */
2815 static int
2816 window_min_size_1 (w, width_p, safe_p)
2817 struct window *w;
2818 int width_p, safe_p;
2820 struct window *c;
2821 int size;
2823 if (!NILP (w->hchild))
2825 /* W is a horizontal combination. */
2826 c = XWINDOW (w->hchild);
2827 size = 0;
2829 if (width_p)
2831 /* The minimum width of a horizontal combination is the sum of
2832 the minimum widths of its children. */
2833 while (c)
2835 size += window_min_size_1 (c, 1, safe_p);
2836 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2839 else
2841 /* The minimum height of a horizontal combination is the
2842 maximum of the minimum heights of its children. */
2843 while (c)
2845 size = max (window_min_size_1 (c, 0, safe_p), size);
2846 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2850 else if (!NILP (w->vchild))
2852 /* W is a vertical combination. */
2853 c = XWINDOW (w->vchild);
2854 size = 0;
2856 if (width_p)
2858 /* The minimum width of a vertical combination is the maximum
2859 of the minimum widths of its children. */
2860 while (c)
2862 size = max (window_min_size_1 (c, 1, safe_p), size);
2863 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2866 else
2868 /* The minimum height of a vertical combination is the sum of
2869 the minimum height of its children. */
2870 while (c)
2872 size += window_min_size_1 (c, 0, safe_p);
2873 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2877 else
2878 /* W is a leaf window. */
2879 size = window_min_size_2 (w, width_p, safe_p);
2881 return size;
2884 /* Return the minimum size of window W, taking fixed-size windows into
2885 account. WIDTH_P non-zero means return the minimum width, otherwise
2886 return the minimum height. SAFE_P non-zero means ignore
2887 window-min-height|width but just return values that won't crash Emacs
2888 and don't hide components like fringes, scrollbars, or modelines.
2889 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2890 to 1 if W is fixed-size unless FIXED is null. */
2892 static int
2893 window_min_size (w, width_p, safe_p, ignore_fixed_p, fixed)
2894 struct window *w;
2895 int width_p, safe_p, ignore_fixed_p, *fixed;
2897 int size, fixed_p;
2899 if (ignore_fixed_p)
2900 fixed_p = 0;
2901 else
2902 fixed_p = window_fixed_size_p (w, width_p, 1);
2904 if (fixed)
2905 *fixed = fixed_p;
2907 if (fixed_p)
2908 size = WINDOW_TOTAL_SIZE (w, width_p);
2909 else
2910 size = window_min_size_1 (w, width_p, safe_p);
2912 return size;
2916 /* Adjust the margins of window W if text area is too small.
2917 Return 1 if window width is ok after adjustment; 0 if window
2918 is still too narrow. */
2920 static int
2921 adjust_window_margins (w)
2922 struct window *w;
2924 int box_cols = (WINDOW_TOTAL_COLS (w)
2925 - WINDOW_FRINGE_COLS (w)
2926 - WINDOW_SCROLL_BAR_COLS (w));
2927 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2928 + WINDOW_RIGHT_MARGIN_COLS (w));
2930 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2931 return 1;
2933 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2934 return 0;
2936 /* Window's text area is too narrow, but reducing the window
2937 margins will fix that. */
2938 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2939 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2941 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2942 w->left_margin_cols = w->right_margin_cols
2943 = make_number (margin_cols/2);
2944 else
2945 w->right_margin_cols = make_number (margin_cols);
2947 else
2948 w->left_margin_cols = make_number (margin_cols);
2949 return 1;
2952 /* Calculate new sizes for windows in the list FORWARD when their
2953 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2954 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2955 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2956 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2957 shrink columns, otherwise shrink lines.
2959 SAFE_P zero means windows may be sized down to window-min-height
2960 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2961 non-zero means windows may be sized down to their minimum safe sizes
2962 taking into account the space needed to display modelines, fringes,
2963 and scrollbars.
2965 This function returns an allocated array of new sizes that the caller
2966 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2967 zero. A size zero means the window shall be deleted. Array index 0
2968 refers to the first window in FORWARD, 1 to the second, and so on.
2970 This function resizes windows proportionally to their size. It also
2971 tries to preserve smaller windows by resizing larger windows before
2972 resizing any window to zero. If resize_proportionally is non-nil for
2973 a specific window, it will attempt to strictly resize that window
2974 proportionally, even at the expense of deleting smaller windows. */
2975 static int *
2976 shrink_windows (total, size, nchildren, shrinkable, resize_fixed_p,
2977 forward, width_p, safe_p)
2978 int total, size, nchildren, shrinkable;
2979 int resize_fixed_p, width_p, safe_p;
2980 Lisp_Object forward;
2982 int available_resize = 0;
2983 int *new_sizes, *min_sizes;
2984 struct window *c;
2985 Lisp_Object child;
2986 int smallest = total;
2987 int total_removed = 0;
2988 int total_shrink = total - size;
2989 int i;
2991 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2992 min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
2994 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2996 int child_size;
2998 c = XWINDOW (child);
2999 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3001 if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
3002 new_sizes[i] = -1;
3003 else
3005 new_sizes[i] = child_size;
3006 min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
3007 if (child_size > min_sizes[i]
3008 && NILP (c->resize_proportionally))
3009 available_resize += child_size - min_sizes[i];
3012 /* We might need to shrink some windows to zero. Find the smallest
3013 windows and set them to 0 until we can fulfil the new size. */
3015 while (shrinkable > 1 && size + available_resize < total)
3017 for (i = 0; i < nchildren; ++i)
3018 if (new_sizes[i] > 0 && smallest > new_sizes[i])
3019 smallest = new_sizes[i];
3021 for (i = 0; i < nchildren; ++i)
3022 if (new_sizes[i] == smallest)
3024 /* Resize this window down to zero. */
3025 new_sizes[i] = 0;
3026 if (smallest > min_sizes[i])
3027 available_resize -= smallest - min_sizes[i];
3028 available_resize += smallest;
3029 --shrinkable;
3030 total_removed += smallest;
3032 /* We don't know what the smallest is now. */
3033 smallest = total;
3035 /* Out of for, just remove one window at the time and
3036 check again if we have enough space. */
3037 break;
3041 /* Now, calculate the new sizes. Try to shrink each window
3042 proportional to its size. */
3043 for (i = 0; i < nchildren; ++i)
3045 if (new_sizes[i] > min_sizes[i])
3047 int to_shrink = total_shrink * new_sizes[i] / total;
3049 if (new_sizes[i] - to_shrink < min_sizes[i])
3050 to_shrink = new_sizes[i] - min_sizes[i];
3051 new_sizes[i] -= to_shrink;
3052 total_removed += to_shrink;
3056 /* Any reminder due to rounding, we just subtract from windows
3057 that are left and still can be shrunk. */
3058 while (total_shrink > total_removed)
3060 int nonzero_sizes = 0;
3061 int nonzero_idx = -1;
3063 for (i = 0; i < nchildren; ++i)
3064 if (new_sizes[i] > 0)
3066 ++nonzero_sizes;
3067 nonzero_idx = i;
3070 for (i = 0; i < nchildren; ++i)
3071 if (new_sizes[i] > min_sizes[i])
3073 --new_sizes[i];
3074 ++total_removed;
3076 /* Out of for, just shrink one window at the time and
3077 check again if we have enough space. */
3078 break;
3081 /* Special case, only one window left. */
3082 if (nonzero_sizes == 1)
3083 break;
3086 /* Any surplus due to rounding, we add to windows that are left. */
3087 while (total_shrink < total_removed)
3089 for (i = 0; i < nchildren; ++i)
3091 if (new_sizes[i] != 0 && total_shrink < total_removed)
3093 ++new_sizes[i];
3094 --total_removed;
3095 break;
3100 xfree (min_sizes);
3102 return new_sizes;
3105 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3106 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3107 their proportionate size relative to WINDOW.
3109 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3110 they are in series. If LAST_ONLY is 1, change only the last of
3111 WINDOW's children when they are in series.
3113 Propagate WINDOW's top or left edge position to children. Delete
3114 windows that become too small unless NODELETE_P is 1. When
3115 NODELETE_P equals 2 do not honor settings for window-min-height and
3116 window-min-width when resizing windows but use safe defaults instead.
3117 This should give better behavior when resizing frames. */
3119 static void
3120 size_window (window, size, width_p, nodelete_p, first_only, last_only)
3121 Lisp_Object window;
3122 int size, width_p, nodelete_p;
3123 int first_only, last_only;
3125 struct window *w = XWINDOW (window);
3126 struct window *c;
3127 Lisp_Object child, *forward, *sideward;
3128 int old_size = WINDOW_TOTAL_SIZE (w, width_p);
3130 size = max (0, size);
3132 /* Delete WINDOW if it's too small. */
3133 if (nodelete_p != 1 && !NILP (w->parent)
3134 && size < window_min_size_1 (w, width_p, nodelete_p == 2))
3136 delete_window (window);
3137 return;
3140 /* Set redisplay hints. */
3141 w->last_modified = make_number (0);
3142 w->last_overlay_modified = make_number (0);
3143 windows_or_buffers_changed++;
3144 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3146 if (width_p)
3148 sideward = &w->vchild;
3149 forward = &w->hchild;
3150 w->total_cols = make_number (size);
3151 adjust_window_margins (w);
3153 else
3155 sideward = &w->hchild;
3156 forward = &w->vchild;
3157 w->total_lines = make_number (size);
3158 w->orig_total_lines = Qnil;
3161 if (!NILP (*sideward))
3163 /* We have a chain of parallel siblings whose size should all change. */
3164 for (child = *sideward; !NILP (child); child = c->next)
3166 c = XWINDOW (child);
3167 if (width_p)
3168 c->left_col = w->left_col;
3169 else
3170 c->top_line = w->top_line;
3171 size_window (child, size, width_p, nodelete_p,
3172 first_only, last_only);
3175 else if (!NILP (*forward) && last_only)
3177 /* Change the last in a series of siblings. */
3178 Lisp_Object last_child;
3179 int child_size;
3181 for (child = *forward; !NILP (child); child = c->next)
3183 c = XWINDOW (child);
3184 last_child = child;
3187 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3188 size_window (last_child, size - old_size + child_size,
3189 width_p, nodelete_p, first_only, last_only);
3191 else if (!NILP (*forward) && first_only)
3193 /* Change the first in a series of siblings. */
3194 int child_size;
3196 child = *forward;
3197 c = XWINDOW (child);
3199 if (width_p)
3200 c->left_col = w->left_col;
3201 else
3202 c->top_line = w->top_line;
3204 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3205 size_window (child, size - old_size + child_size,
3206 width_p, nodelete_p, first_only, last_only);
3208 else if (!NILP (*forward))
3210 int fixed_size, each, extra, n;
3211 int resize_fixed_p, nfixed;
3212 int last_pos, first_pos, nchildren, total;
3213 int *new_sizes = NULL;
3215 /* Determine the fixed-size portion of this window, and the
3216 number of child windows. */
3217 fixed_size = nchildren = nfixed = total = 0;
3218 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3220 int child_size;
3222 c = XWINDOW (child);
3223 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3224 total += child_size;
3226 if (window_fixed_size_p (c, width_p, 0))
3228 fixed_size += child_size;
3229 ++nfixed;
3233 /* If the new size is smaller than fixed_size, or if there
3234 aren't any resizable windows, allow resizing fixed-size
3235 windows. */
3236 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3238 /* Compute how many lines/columns to add/remove to each child. The
3239 value of extra takes care of rounding errors. */
3240 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3241 if (size < total && n > 1)
3242 new_sizes = shrink_windows (total, size, nchildren, n,
3243 resize_fixed_p, *forward, width_p,
3244 nodelete_p == 2);
3245 else
3247 each = (size - total) / n;
3248 extra = (size - total) - n * each;
3251 /* Compute new children heights and edge positions. */
3252 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3253 last_pos = first_pos;
3254 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3256 int new_size, old_size;
3258 c = XWINDOW (child);
3259 old_size = WINDOW_TOTAL_SIZE (c, width_p);
3260 new_size = old_size;
3262 /* The top or left edge position of this child equals the
3263 bottom or right edge of its predecessor. */
3264 if (width_p)
3265 c->left_col = make_number (last_pos);
3266 else
3267 c->top_line = make_number (last_pos);
3269 /* If this child can be resized, do it. */
3270 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3272 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3273 extra = 0;
3276 /* Set new size. Note that size_window also propagates
3277 edge positions to children, so it's not a no-op if we
3278 didn't change the child's size. */
3279 size_window (child, new_size, width_p, 1, first_only, last_only);
3281 /* Remember the bottom/right edge position of this child; it
3282 will be used to set the top/left edge of the next child. */
3283 last_pos += new_size;
3286 xfree (new_sizes);
3288 /* We should have covered the parent exactly with child windows. */
3289 xassert (size == last_pos - first_pos);
3291 /* Now delete any children that became too small. */
3292 if (nodelete_p != 1)
3293 for (child = *forward; !NILP (child); child = c->next)
3295 int child_size;
3297 c = XWINDOW (child);
3298 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3299 size_window (child, child_size, width_p, nodelete_p,
3300 first_only, last_only);
3305 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3306 WINDOW's children. NODELETE zero means windows that have become
3307 smaller than window-min-height in the process may be deleted.
3308 NODELETE 1 means never delete windows that become too small in the
3309 process. (The caller should check later and do so if appropriate.)
3310 NODELETE 2 means delete only windows that have become too small to be
3311 displayed correctly. */
3313 void
3314 set_window_height (window, height, nodelete)
3315 Lisp_Object window;
3316 int height;
3317 int nodelete;
3319 size_window (window, height, 0, nodelete, 0, 0);
3322 /* Set WINDOW's width to WIDTH, and recursively change the width of
3323 WINDOW's children. NODELETE zero means windows that have become
3324 smaller than window-min-width in the process may be deleted.
3325 NODELETE 1 means never delete windows that become too small in the
3326 process. (The caller should check later and do so if appropriate.)
3327 NODELETE 2 means delete only windows that have become too small to be
3328 displayed correctly. */
3330 void
3331 set_window_width (window, width, nodelete)
3332 Lisp_Object window;
3333 int width;
3334 int nodelete;
3336 size_window (window, width, 1, nodelete, 0, 0);
3339 /* Change window heights in windows rooted in WINDOW by N lines. */
3341 void
3342 change_window_heights (window, n)
3343 Lisp_Object window;
3344 int n;
3346 struct window *w = XWINDOW (window);
3348 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3349 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3351 if (INTEGERP (w->orig_top_line))
3352 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3353 if (INTEGERP (w->orig_total_lines))
3354 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3356 /* Handle just the top child in a vertical split. */
3357 if (!NILP (w->vchild))
3358 change_window_heights (w->vchild, n);
3360 /* Adjust all children in a horizontal split. */
3361 for (window = w->hchild; !NILP (window); window = w->next)
3363 w = XWINDOW (window);
3364 change_window_heights (window, n);
3369 int window_select_count;
3371 EXFUN (Fset_window_fringes, 4);
3372 EXFUN (Fset_window_scroll_bars, 4);
3374 static void
3375 run_funs (Lisp_Object funs)
3377 for (; CONSP (funs); funs = XCDR (funs))
3378 if (!EQ (XCAR (funs), Qt))
3379 call0 (XCAR (funs));
3382 static Lisp_Object select_window_norecord (Lisp_Object window);
3383 static Lisp_Object select_frame_norecord (Lisp_Object frame);
3385 void
3386 run_window_configuration_change_hook (struct frame *f)
3388 int count = SPECPDL_INDEX ();
3389 Lisp_Object frame, global_wcch
3390 = Fdefault_value (Qwindow_configuration_change_hook);
3391 XSETFRAME (frame, f);
3393 if (NILP (Vrun_hooks))
3394 return;
3396 if (SELECTED_FRAME () != f)
3398 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3399 Fselect_frame (frame, Qt);
3402 /* Use the right buffer. Matters when running the local hooks. */
3403 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3405 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3406 Fset_buffer (Fwindow_buffer (Qnil));
3409 /* Look for buffer-local values. */
3411 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3412 for (; CONSP (windows); windows = XCDR (windows))
3414 Lisp_Object window = XCAR (windows);
3415 Lisp_Object buffer = Fwindow_buffer (window);
3416 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3417 buffer)))
3419 int count = SPECPDL_INDEX ();
3420 record_unwind_protect (select_window_norecord, Fselected_window ());
3421 select_window_norecord (window);
3422 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3423 buffer));
3424 unbind_to (count, Qnil);
3429 run_funs (global_wcch);
3430 unbind_to (count, Qnil);
3433 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3434 means it's allowed to run hooks. See make_frame for a case where
3435 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3436 margins, fringes, and scroll-bar settings of the window are not
3437 reset from the buffer's local settings. */
3439 void
3440 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3441 Lisp_Object window, buffer;
3442 int run_hooks_p, keep_margins_p;
3444 struct window *w = XWINDOW (window);
3445 struct buffer *b = XBUFFER (buffer);
3446 int count = SPECPDL_INDEX ();
3447 int samebuf = EQ (buffer, w->buffer);
3449 w->buffer = buffer;
3451 if (EQ (window, selected_window))
3452 b->last_selected_window = window;
3454 /* Let redisplay errors through. */
3455 b->display_error_modiff = 0;
3457 /* Update time stamps of buffer display. */
3458 if (INTEGERP (b->display_count))
3459 XSETINT (b->display_count, XINT (b->display_count) + 1);
3460 b->display_time = Fcurrent_time ();
3462 XSETFASTINT (w->window_end_pos, 0);
3463 XSETFASTINT (w->window_end_vpos, 0);
3464 bzero (&w->last_cursor, sizeof w->last_cursor);
3465 w->window_end_valid = Qnil;
3466 if (!(keep_margins_p && samebuf))
3467 { /* If we're not actually changing the buffer, don't reset hscroll and
3468 vscroll. This case happens for example when called from
3469 change_frame_size_1, where we use a dummy call to
3470 Fset_window_buffer on the frame's selected window (and no other)
3471 just in order to run window-configuration-change-hook.
3472 Resetting hscroll and vscroll here is problematic for things like
3473 image-mode and doc-view-mode since it resets the image's position
3474 whenever we resize the frame. */
3475 w->hscroll = w->min_hscroll = make_number (0);
3476 w->vscroll = 0;
3477 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3478 set_marker_restricted (w->start,
3479 make_number (b->last_window_start),
3480 buffer);
3481 w->start_at_line_beg = Qnil;
3482 w->force_start = Qnil;
3483 XSETFASTINT (w->last_modified, 0);
3484 XSETFASTINT (w->last_overlay_modified, 0);
3486 /* Maybe we could move this into the `if' but it's not obviously safe and
3487 I doubt it's worth the trouble. */
3488 windows_or_buffers_changed++;
3490 /* We must select BUFFER for running the window-scroll-functions. */
3491 /* We can't check ! NILP (Vwindow_scroll_functions) here
3492 because that might itself be a local variable. */
3493 if (window_initialized)
3495 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3496 Fset_buffer (buffer);
3499 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3501 if (!keep_margins_p)
3503 /* Set left and right marginal area width etc. from buffer. */
3505 /* This may call adjust_window_margins three times, so
3506 temporarily disable window margins. */
3507 Lisp_Object save_left = w->left_margin_cols;
3508 Lisp_Object save_right = w->right_margin_cols;
3510 w->left_margin_cols = w->right_margin_cols = Qnil;
3512 Fset_window_fringes (window,
3513 b->left_fringe_width, b->right_fringe_width,
3514 b->fringes_outside_margins);
3516 Fset_window_scroll_bars (window,
3517 b->scroll_bar_width,
3518 b->vertical_scroll_bar_type, Qnil);
3520 w->left_margin_cols = save_left;
3521 w->right_margin_cols = save_right;
3523 Fset_window_margins (window,
3524 b->left_margin_cols, b->right_margin_cols);
3527 if (run_hooks_p)
3529 if (! NILP (Vwindow_scroll_functions))
3530 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3531 Fmarker_position (w->start));
3532 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3535 unbind_to (count, Qnil);
3539 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3540 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3541 WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
3542 or the name of an existing buffer. Optional third argument KEEP-MARGINS
3543 non-nil means that WINDOW's current display margins, fringe widths, and
3544 scroll bar settings are preserved; the default is to reset these from
3545 the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
3547 This function throws an error when WINDOW is strongly dedicated to its
3548 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3549 already display BUFFER-OR-NAME.
3551 This function runs `window-scroll-functions' before running
3552 `window-configuration-change-hook'. */)
3553 (window, buffer_or_name, keep_margins)
3554 register Lisp_Object window, buffer_or_name, keep_margins;
3556 register Lisp_Object tem, buffer;
3557 register struct window *w = decode_window (window);
3559 XSETWINDOW (window, w);
3560 buffer = Fget_buffer (buffer_or_name);
3561 CHECK_BUFFER (buffer);
3562 if (NILP (XBUFFER (buffer)->name))
3563 error ("Attempt to display deleted buffer");
3565 tem = w->buffer;
3566 if (NILP (tem))
3567 error ("Window is deleted");
3568 else if (!EQ (tem, Qt))
3569 /* w->buffer is t when the window is first being set up. */
3571 if (!EQ (tem, buffer))
3572 if (EQ (w->dedicated, Qt))
3573 error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem)->name));
3574 else
3575 w->dedicated = Qnil;
3577 unshow_buffer (w);
3580 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3581 return Qnil;
3584 /* If select_window is called with inhibit_point_swap non-zero it will
3585 not store point of the old selected window's buffer back into that
3586 window's pointm slot. This is needed by Fset_window_configuration to
3587 avoid that the display routine is called with selected_window set to
3588 Qnil causing a subsequent crash. */
3590 static Lisp_Object
3591 select_window (window, norecord, inhibit_point_swap)
3592 Lisp_Object window, norecord;
3593 int inhibit_point_swap;
3595 register struct window *w;
3596 register struct window *ow;
3597 struct frame *sf;
3599 CHECK_LIVE_WINDOW (window);
3601 w = XWINDOW (window);
3602 w->frozen_window_start_p = 0;
3604 if (NILP (norecord))
3606 ++window_select_count;
3607 XSETFASTINT (w->use_time, window_select_count);
3610 if (EQ (window, selected_window) && !inhibit_point_swap)
3611 return window;
3613 sf = SELECTED_FRAME ();
3614 if (XFRAME (WINDOW_FRAME (w)) != sf)
3616 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3617 /* Use this rather than Fhandle_switch_frame
3618 so that FRAME_FOCUS_FRAME is moved appropriately as we
3619 move around in the state where a minibuffer in a separate
3620 frame is active. */
3621 Fselect_frame (WINDOW_FRAME (w), norecord);
3622 /* Fselect_frame called us back so we've done all the work already. */
3623 eassert (EQ (window, selected_window));
3624 return window;
3626 else
3627 sf->selected_window = window;
3629 /* Store the current buffer's actual point into the
3630 old selected window. It belongs to that window,
3631 and when the window is not selected, must be in the window. */
3632 if (!inhibit_point_swap)
3634 ow = XWINDOW (selected_window);
3635 if (! NILP (ow->buffer))
3636 set_marker_both (ow->pointm, ow->buffer,
3637 BUF_PT (XBUFFER (ow->buffer)),
3638 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3641 selected_window = window;
3643 if (NILP (norecord))
3644 record_buffer (w->buffer);
3645 Fset_buffer (w->buffer);
3647 XBUFFER (w->buffer)->last_selected_window = window;
3649 /* Go to the point recorded in the window.
3650 This is important when the buffer is in more
3651 than one window. It also matters when
3652 redisplay_window has altered point after scrolling,
3653 because it makes the change only in the window. */
3655 register int new_point = marker_position (w->pointm);
3656 if (new_point < BEGV)
3657 SET_PT (BEGV);
3658 else if (new_point > ZV)
3659 SET_PT (ZV);
3660 else
3661 SET_PT (new_point);
3664 windows_or_buffers_changed++;
3665 return window;
3669 /* Note that selected_window can be nil when this is called from
3670 Fset_window_configuration. */
3672 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3673 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3674 If WINDOW is not already selected, make WINDOW's buffer current
3675 and make WINDOW the frame's selected window. Return WINDOW.
3676 Optional second arg NORECORD non-nil means do not put this buffer
3677 at the front of the list of recently selected ones and do not
3678 make this window the most recently selected one.
3680 Note that the main editor command loop selects the buffer of the
3681 selected window before each command. */)
3682 (window, norecord)
3683 register Lisp_Object window, norecord;
3685 return select_window (window, norecord, 0);
3688 static Lisp_Object
3689 select_window_norecord (window)
3690 Lisp_Object window;
3692 return WINDOW_LIVE_P (window)
3693 ? Fselect_window (window, Qt) : selected_window;
3696 static Lisp_Object
3697 select_frame_norecord (frame)
3698 Lisp_Object frame;
3700 return FRAME_LIVE_P (XFRAME (frame))
3701 ? Fselect_frame (frame, Qt) : selected_frame;
3704 Lisp_Object
3705 display_buffer (buffer, not_this_window_p, override_frame)
3706 Lisp_Object buffer, not_this_window_p, override_frame;
3708 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3711 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3712 0, 1, 0,
3713 doc: /* Force all windows to be updated on next redisplay.
3714 If optional arg OBJECT is a window, force redisplay of that window only.
3715 If OBJECT is a buffer or buffer name, force redisplay of all windows
3716 displaying that buffer. */)
3717 (object)
3718 Lisp_Object object;
3720 if (NILP (object))
3722 windows_or_buffers_changed++;
3723 update_mode_lines++;
3724 return Qt;
3727 if (WINDOWP (object))
3729 struct window *w = XWINDOW (object);
3730 mark_window_display_accurate (object, 0);
3731 w->update_mode_line = Qt;
3732 if (BUFFERP (w->buffer))
3733 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3734 ++update_mode_lines;
3735 return Qt;
3738 if (STRINGP (object))
3739 object = Fget_buffer (object);
3740 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3742 /* Walk all windows looking for buffer, and force update
3743 of each of those windows. */
3745 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3746 return NILP (object) ? Qnil : Qt;
3749 /* If nothing suitable was found, just return.
3750 We could signal an error, but this feature will typically be used
3751 asynchronously in timers or process sentinels, so we don't. */
3752 return Qnil;
3756 void
3757 temp_output_buffer_show (buf)
3758 register Lisp_Object buf;
3760 register struct buffer *old = current_buffer;
3761 register Lisp_Object window;
3762 register struct window *w;
3764 XBUFFER (buf)->directory = current_buffer->directory;
3766 Fset_buffer (buf);
3767 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3768 BEGV = BEG;
3769 ZV = Z;
3770 SET_PT (BEG);
3771 #if 0 /* rms: there should be no reason for this. */
3772 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3773 #endif
3774 set_buffer_internal (old);
3776 if (!NILP (Vtemp_buffer_show_function))
3777 call1 (Vtemp_buffer_show_function, buf);
3778 else
3780 window = display_buffer (buf, Qnil, Qnil);
3782 if (!EQ (XWINDOW (window)->frame, selected_frame))
3783 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3784 Vminibuf_scroll_window = window;
3785 w = XWINDOW (window);
3786 XSETFASTINT (w->hscroll, 0);
3787 XSETFASTINT (w->min_hscroll, 0);
3788 set_marker_restricted_both (w->start, buf, BEG, BEG);
3789 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3791 /* Run temp-buffer-show-hook, with the chosen window selected
3792 and its buffer current. */
3794 if (!NILP (Vrun_hooks)
3795 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3796 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3798 int count = SPECPDL_INDEX ();
3799 Lisp_Object prev_window, prev_buffer;
3800 prev_window = selected_window;
3801 XSETBUFFER (prev_buffer, old);
3803 /* Select the window that was chosen, for running the hook.
3804 Note: Both Fselect_window and select_window_norecord may
3805 set-buffer to the buffer displayed in the window,
3806 so we need to save the current buffer. --stef */
3807 record_unwind_protect (Fset_buffer, prev_buffer);
3808 record_unwind_protect (select_window_norecord, prev_window);
3809 Fselect_window (window, Qt);
3810 Fset_buffer (w->buffer);
3811 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3812 unbind_to (count, Qnil);
3817 static void
3818 make_dummy_parent (window)
3819 Lisp_Object window;
3821 Lisp_Object new;
3822 register struct window *o, *p;
3823 int i;
3825 o = XWINDOW (window);
3826 p = allocate_window ();
3827 for (i = 0; i < VECSIZE (struct window); ++i)
3828 ((struct Lisp_Vector *) p)->contents[i]
3829 = ((struct Lisp_Vector *)o)->contents[i];
3830 XSETWINDOW (new, p);
3832 ++sequence_number;
3833 XSETFASTINT (p->sequence_number, sequence_number);
3835 /* Put new into window structure in place of window */
3836 replace_window (window, new);
3838 o->next = Qnil;
3839 o->prev = Qnil;
3840 o->vchild = Qnil;
3841 o->hchild = Qnil;
3842 o->parent = new;
3844 p->start = Qnil;
3845 p->pointm = Qnil;
3846 p->buffer = Qnil;
3849 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3850 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3851 WINDOW defaults to selected one and SIZE to half its size.
3852 If optional third arg HORIZONTAL is non-nil, split side by side and put
3853 SIZE columns in the first of the pair. In that case, SIZE includes that
3854 window's scroll bar, or the divider column to its right.
3855 Interactively, all arguments are nil.
3856 Returns the newly created window (which is the lower or rightmost one).
3857 The upper or leftmost window is the original one, and remains selected
3858 if it was selected before.
3860 See Info node `(elisp)Splitting Windows' for more details and examples. */)
3861 (window, size, horizontal)
3862 Lisp_Object window, size, horizontal;
3864 register Lisp_Object new;
3865 register struct window *o, *p;
3866 FRAME_PTR fo;
3867 register int size_int;
3869 if (NILP (window))
3870 window = selected_window;
3871 else
3872 CHECK_LIVE_WINDOW (window);
3874 o = XWINDOW (window);
3875 fo = XFRAME (WINDOW_FRAME (o));
3877 if (NILP (size))
3879 if (!NILP (horizontal))
3880 /* Calculate the size of the left-hand window, by dividing
3881 the usable space in columns by two.
3882 We round up, since the left-hand window may include
3883 a dividing line, while the right-hand may not. */
3884 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3885 else
3886 size_int = XFASTINT (o->total_lines) >> 1;
3888 else
3890 CHECK_NUMBER (size);
3891 size_int = XINT (size);
3894 if (MINI_WINDOW_P (o))
3895 error ("Attempt to split minibuffer window");
3896 else if (window_fixed_size_p (o, !NILP (horizontal), 0))
3897 error ("Attempt to split fixed-size window");
3899 if (NILP (horizontal))
3901 int window_safe_height = window_min_size_2 (o, 0, 0);
3903 if (size_int < window_safe_height)
3904 error ("Window height %d too small (after splitting)", size_int);
3905 if (size_int + window_safe_height > XFASTINT (o->total_lines))
3906 error ("Window height %d too small (after splitting)",
3907 XFASTINT (o->total_lines) - size_int);
3908 if (NILP (o->parent)
3909 || NILP (XWINDOW (o->parent)->vchild))
3911 make_dummy_parent (window);
3912 new = o->parent;
3913 XWINDOW (new)->vchild = window;
3916 else
3918 int window_safe_width = window_min_size_2 (o, 1, 0);
3920 if (size_int < window_safe_width)
3921 error ("Window width %d too small (after splitting)", size_int);
3922 if (size_int + window_safe_width > XFASTINT (o->total_cols))
3923 error ("Window width %d too small (after splitting)",
3924 XFASTINT (o->total_cols) - size_int);
3925 if (NILP (o->parent)
3926 || NILP (XWINDOW (o->parent)->hchild))
3928 make_dummy_parent (window);
3929 new = o->parent;
3930 XWINDOW (new)->hchild = window;
3934 /* Now we know that window's parent is a vertical combination
3935 if we are dividing vertically, or a horizontal combination
3936 if we are making side-by-side windows */
3938 windows_or_buffers_changed++;
3939 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3940 new = make_window ();
3941 p = XWINDOW (new);
3943 p->frame = o->frame;
3944 p->next = o->next;
3945 if (!NILP (p->next))
3946 XWINDOW (p->next)->prev = new;
3947 p->prev = window;
3948 o->next = new;
3949 p->parent = o->parent;
3950 p->buffer = Qt;
3951 p->window_end_valid = Qnil;
3952 bzero (&p->last_cursor, sizeof p->last_cursor);
3954 /* Duplicate special geometry settings. */
3956 p->left_margin_cols = o->left_margin_cols;
3957 p->right_margin_cols = o->right_margin_cols;
3958 p->left_fringe_width = o->left_fringe_width;
3959 p->right_fringe_width = o->right_fringe_width;
3960 p->fringes_outside_margins = o->fringes_outside_margins;
3961 p->scroll_bar_width = o->scroll_bar_width;
3962 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3964 /* Apportion the available frame space among the two new windows */
3966 if (!NILP (horizontal))
3968 p->total_lines = o->total_lines;
3969 p->top_line = o->top_line;
3970 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3971 XSETFASTINT (o->total_cols, size_int);
3972 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3973 adjust_window_margins (p);
3974 adjust_window_margins (o);
3976 else
3978 p->left_col = o->left_col;
3979 p->total_cols = o->total_cols;
3980 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3981 XSETFASTINT (o->total_lines, size_int);
3982 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3985 /* Adjust glyph matrices. */
3986 adjust_glyphs (fo);
3988 Fset_window_buffer (new, o->buffer, Qt);
3989 return new;
3992 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3993 doc: /* Make selected window SIZE lines taller.
3994 Interactively, if no argument is given, make the selected window one
3995 line taller. If optional argument HORIZONTAL is non-nil, make selected
3996 window wider by SIZE columns. If SIZE is negative, shrink the window by
3997 -SIZE lines or columns. Return nil.
3999 This function can delete windows if they get too small. The size of
4000 fixed size windows is not altered by this function. */)
4001 (size, horizontal)
4002 Lisp_Object size, horizontal;
4004 CHECK_NUMBER (size);
4005 enlarge_window (selected_window, XINT (size), !NILP (horizontal));
4007 run_window_configuration_change_hook (SELECTED_FRAME ());
4009 return Qnil;
4012 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
4013 doc: /* Make selected window SIZE lines smaller.
4014 Interactively, if no argument is given, make the selected window one
4015 line smaller. If optional argument HORIZONTAL is non-nil, make the
4016 window narrower by SIZE columns. If SIZE is negative, enlarge selected
4017 window by -SIZE lines or columns. Return nil.
4019 This function can delete windows if they get too small. The size of
4020 fixed size windows is not altered by this function. */)
4021 (size, horizontal)
4022 Lisp_Object size, horizontal;
4024 CHECK_NUMBER (size);
4025 enlarge_window (selected_window, -XINT (size), !NILP (horizontal));
4027 run_window_configuration_change_hook (SELECTED_FRAME ());
4029 return Qnil;
4033 window_height (window)
4034 Lisp_Object window;
4036 register struct window *p = XWINDOW (window);
4037 return WINDOW_TOTAL_LINES (p);
4041 window_width (window)
4042 Lisp_Object window;
4044 register struct window *p = XWINDOW (window);
4045 return WINDOW_TOTAL_COLS (p);
4049 #define CURBEG(w) \
4050 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4052 #define CURSIZE(w) \
4053 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4056 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4057 horizontally; zero means do it vertically.
4059 Siblings of the selected window are resized to fulfill the size
4060 request. If they become too small in the process, they may be
4061 deleted. */
4063 static void
4064 enlarge_window (window, delta, horiz_flag)
4065 Lisp_Object window;
4066 int delta, horiz_flag;
4068 Lisp_Object parent, next, prev;
4069 struct window *p;
4070 Lisp_Object *sizep;
4071 int maximum;
4072 int (*sizefun) P_ ((Lisp_Object))
4073 = horiz_flag ? window_width : window_height;
4074 void (*setsizefun) P_ ((Lisp_Object, int, int))
4075 = (horiz_flag ? set_window_width : set_window_height);
4077 /* Give up if this window cannot be resized. */
4078 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4079 error ("Window is not resizable");
4081 /* Find the parent of the selected window. */
4082 while (1)
4084 p = XWINDOW (window);
4085 parent = p->parent;
4087 if (NILP (parent))
4089 if (horiz_flag)
4090 error ("No other window to side of this one");
4091 break;
4094 if (horiz_flag
4095 ? !NILP (XWINDOW (parent)->hchild)
4096 : !NILP (XWINDOW (parent)->vchild))
4097 break;
4099 window = parent;
4102 sizep = &CURSIZE (window);
4105 register int maxdelta;
4107 /* Compute the maximum size increment this window can have. */
4109 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4110 /* This is a main window followed by a minibuffer. */
4111 : !NILP (p->next) ? ((*sizefun) (p->next)
4112 - window_min_size (XWINDOW (p->next),
4113 horiz_flag, 0, 0, 0))
4114 /* This is a minibuffer following a main window. */
4115 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4116 - window_min_size (XWINDOW (p->prev),
4117 horiz_flag, 0, 0, 0))
4118 /* This is a frame with only one window, a minibuffer-only
4119 or a minibufferless frame. */
4120 : (delta = 0));
4122 if (delta > maxdelta)
4123 /* This case traps trying to make the minibuffer
4124 the full frame, or make the only window aside from the
4125 minibuffer the full frame. */
4126 delta = maxdelta;
4129 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
4130 horiz_flag, 0, 0, 0))
4132 delete_window (window);
4133 return;
4136 if (delta == 0)
4137 return;
4139 /* Find the total we can get from other siblings without deleting them. */
4140 maximum = 0;
4141 for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
4142 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4143 horiz_flag, 0, 0, 0);
4144 for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
4145 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4146 horiz_flag, 0, 0, 0);
4148 /* If we can get it all from them without deleting them, do so. */
4149 if (delta <= maximum)
4151 Lisp_Object first_unaffected;
4152 Lisp_Object first_affected;
4153 int fixed_p;
4155 next = p->next;
4156 prev = p->prev;
4157 first_affected = window;
4158 /* Look at one sibling at a time,
4159 moving away from this window in both directions alternately,
4160 and take as much as we can get without deleting that sibling. */
4161 while (delta != 0
4162 && (!NILP (next) || !NILP (prev)))
4164 if (! NILP (next))
4166 int this_one = ((*sizefun) (next)
4167 - window_min_size (XWINDOW (next), horiz_flag,
4168 0, 0, &fixed_p));
4169 if (!fixed_p)
4171 if (this_one > delta)
4172 this_one = delta;
4174 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4175 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4177 delta -= this_one;
4180 next = XWINDOW (next)->next;
4183 if (delta == 0)
4184 break;
4186 if (! NILP (prev))
4188 int this_one = ((*sizefun) (prev)
4189 - window_min_size (XWINDOW (prev), horiz_flag,
4190 0, 0, &fixed_p));
4191 if (!fixed_p)
4193 if (this_one > delta)
4194 this_one = delta;
4196 first_affected = prev;
4198 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4199 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4201 delta -= this_one;
4204 prev = XWINDOW (prev)->prev;
4208 xassert (delta == 0);
4210 /* Now recalculate the edge positions of all the windows affected,
4211 based on the new sizes. */
4212 first_unaffected = next;
4213 prev = first_affected;
4214 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4215 prev = next, next = XWINDOW (next)->next)
4217 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4218 /* This does not change size of NEXT,
4219 but it propagates the new top edge to its children */
4220 (*setsizefun) (next, (*sizefun) (next), 0);
4223 else
4225 register int delta1;
4226 register int opht = (*sizefun) (parent);
4228 if (opht <= XINT (*sizep) + delta)
4230 /* If trying to grow this window to or beyond size of the parent,
4231 just delete all the sibling windows. */
4232 Lisp_Object start, tem, next;
4234 start = XWINDOW (parent)->vchild;
4235 if (NILP (start))
4236 start = XWINDOW (parent)->hchild;
4238 /* Delete any siblings that come after WINDOW. */
4239 tem = XWINDOW (window)->next;
4240 while (! NILP (tem))
4242 next = XWINDOW (tem)->next;
4243 delete_window (tem);
4244 tem = next;
4247 /* Delete any siblings that come after WINDOW.
4248 Note that if START is not WINDOW, then WINDOW still
4249 has siblings, so WINDOW has not yet replaced its parent. */
4250 tem = start;
4251 while (! EQ (tem, window))
4253 next = XWINDOW (tem)->next;
4254 delete_window (tem);
4255 tem = next;
4258 else
4260 /* Otherwise, make delta1 just right so that if we add
4261 delta1 lines to this window and to the parent, and then
4262 shrink the parent back to its original size, the new
4263 proportional size of this window will increase by delta.
4265 The function size_window will compute the new height h'
4266 of the window from delta1 as:
4268 e = delta1/n
4269 x = delta1 - delta1/n * n for the 1st resizable child
4270 h' = h + e + x
4272 where n is the number of children that can be resized.
4273 We can ignore x by choosing a delta1 that is a multiple of
4274 n. We want the height of this window to come out as
4276 h' = h + delta
4278 So, delta1 must be
4280 h + e = h + delta
4281 delta1/n = delta
4282 delta1 = n * delta.
4284 The number of children n equals the number of resizable
4285 children of this window + 1 because we know window itself
4286 is resizable (otherwise we would have signaled an error).
4288 This reasoning is not correct when other windows become too
4289 small and shrink_windows refuses to delete them. Below we
4290 use resize_proportionally to work around this problem. */
4292 struct window *w = XWINDOW (window);
4293 Lisp_Object s;
4294 int n = 1;
4296 for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next)
4297 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4298 ++n;
4299 for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev)
4300 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4301 ++n;
4303 delta1 = n * delta;
4305 /* Add delta1 lines or columns to this window, and to the parent,
4306 keeping things consistent while not affecting siblings. */
4307 XSETINT (CURSIZE (parent), opht + delta1);
4308 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4310 /* Squeeze out delta1 lines or columns from our parent,
4311 shrinking this window and siblings proportionately. This
4312 brings parent back to correct size. Delta1 was calculated
4313 so this makes this window the desired size, taking it all
4314 out of the siblings.
4316 Temporarily set resize_proportionally to Qt to assure that,
4317 if necessary, shrink_windows deletes smaller windows rather
4318 than shrink this window. */
4319 w->resize_proportionally = Qt;
4320 (*setsizefun) (parent, opht, 0);
4321 w->resize_proportionally = Qnil;
4325 XSETFASTINT (p->last_modified, 0);
4326 XSETFASTINT (p->last_overlay_modified, 0);
4328 /* Adjust glyph matrices. */
4329 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4333 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4334 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4335 zero means adjust the height, moving the bottom edge.
4337 Following siblings of the selected window are resized to fulfill
4338 the size request. If they become too small in the process, they
4339 are not deleted; instead, we signal an error. */
4341 static void
4342 adjust_window_trailing_edge (window, delta, horiz_flag)
4343 Lisp_Object window;
4344 int delta, horiz_flag;
4346 Lisp_Object parent, child;
4347 struct window *p;
4348 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4349 int delcount = window_deletion_count;
4351 CHECK_WINDOW (window);
4353 /* Give up if this window cannot be resized. */
4354 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4355 error ("Window is not resizable");
4357 while (1)
4359 Lisp_Object first_parallel = Qnil;
4361 if (NILP (window))
4363 /* This happens if WINDOW on the previous iteration was
4364 at top level of the window tree. */
4365 Fset_window_configuration (old_config);
4366 error ("Specified window edge is fixed");
4369 p = XWINDOW (window);
4370 parent = p->parent;
4372 /* See if this level has windows in parallel in the specified
4373 direction. If so, set FIRST_PARALLEL to the first one. */
4374 if (horiz_flag)
4376 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4377 first_parallel = XWINDOW (parent)->vchild;
4378 else if (NILP (parent) && !NILP (p->next))
4380 /* Handle the vertical chain of main window and minibuffer
4381 which has no parent. */
4382 first_parallel = window;
4383 while (! NILP (XWINDOW (first_parallel)->prev))
4384 first_parallel = XWINDOW (first_parallel)->prev;
4387 else
4389 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4390 first_parallel = XWINDOW (parent)->hchild;
4393 /* If this level's succession is in the desired dimension,
4394 and this window is the last one, and there is no higher level,
4395 its trailing edge is fixed. */
4396 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4397 && NILP (parent))
4399 Fset_window_configuration (old_config);
4400 error ("Specified window edge is fixed");
4403 /* Don't make this window too small. */
4404 if (XINT (CURSIZE (window)) + delta
4405 < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
4407 Fset_window_configuration (old_config);
4408 error ("Cannot adjust window size as specified");
4411 /* Clear out some redisplay caches. */
4412 XSETFASTINT (p->last_modified, 0);
4413 XSETFASTINT (p->last_overlay_modified, 0);
4415 /* Adjust this window's edge. */
4416 XSETINT (CURSIZE (window),
4417 XINT (CURSIZE (window)) + delta);
4419 /* If this window has following siblings in the desired dimension,
4420 make them smaller, and exit the loop.
4422 (If we reach the top of the tree and can never do this,
4423 we will fail and report an error, above.) */
4424 if (NILP (first_parallel))
4426 if (!NILP (p->next))
4428 /* This may happen for the minibuffer. In that case
4429 the window_deletion_count check below does not work. */
4430 if (XINT (CURSIZE (p->next)) - delta <= 0)
4432 Fset_window_configuration (old_config);
4433 error ("Cannot adjust window size as specified");
4436 XSETINT (CURBEG (p->next),
4437 XINT (CURBEG (p->next)) + delta);
4438 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4439 horiz_flag, 0, 1, 0);
4440 break;
4443 else
4444 /* Here we have a chain of parallel siblings, in the other dimension.
4445 Change the size of the other siblings. */
4446 for (child = first_parallel;
4447 ! NILP (child);
4448 child = XWINDOW (child)->next)
4449 if (! EQ (child, window))
4450 size_window (child, XINT (CURSIZE (child)) + delta,
4451 horiz_flag, 0, 0, 1);
4453 window = parent;
4456 /* If we made a window so small it got deleted,
4457 we failed. Report failure. */
4458 if (delcount != window_deletion_count)
4460 Fset_window_configuration (old_config);
4461 error ("Cannot adjust window size as specified");
4464 /* Adjust glyph matrices. */
4465 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4468 #undef CURBEG
4469 #undef CURSIZE
4471 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4472 Sadjust_window_trailing_edge, 3, 3, 0,
4473 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4474 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4475 Otherwise, adjust the height, moving the bottom edge.
4477 Following siblings of the selected window are resized to fulfill
4478 the size request. If they become too small in the process, they
4479 are not deleted; instead, we signal an error. */)
4480 (window, delta, horizontal)
4481 Lisp_Object window, delta, horizontal;
4483 CHECK_NUMBER (delta);
4484 if (NILP (window))
4485 window = selected_window;
4486 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4488 run_window_configuration_change_hook
4489 (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4491 return Qnil;
4496 /***********************************************************************
4497 Resizing Mini-Windows
4498 ***********************************************************************/
4500 static void shrink_window_lowest_first P_ ((struct window *, int));
4502 enum save_restore_action
4504 CHECK_ORIG_SIZES,
4505 SAVE_ORIG_SIZES,
4506 RESTORE_ORIG_SIZES
4509 static int save_restore_orig_size P_ ((struct window *,
4510 enum save_restore_action));
4512 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4513 from lowest windows first. */
4515 static void
4516 shrink_window_lowest_first (w, height)
4517 struct window *w;
4518 int height;
4520 struct window *c;
4521 Lisp_Object child;
4522 int old_height;
4524 xassert (!MINI_WINDOW_P (w));
4526 /* Set redisplay hints. */
4527 XSETFASTINT (w->last_modified, 0);
4528 XSETFASTINT (w->last_overlay_modified, 0);
4529 windows_or_buffers_changed++;
4530 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4532 old_height = XFASTINT (w->total_lines);
4533 XSETFASTINT (w->total_lines, height);
4535 if (!NILP (w->hchild))
4537 for (child = w->hchild; !NILP (child); child = c->next)
4539 c = XWINDOW (child);
4540 c->top_line = w->top_line;
4541 shrink_window_lowest_first (c, height);
4544 else if (!NILP (w->vchild))
4546 Lisp_Object last_child;
4547 int delta = old_height - height;
4548 int last_top;
4550 last_child = Qnil;
4552 /* Find the last child. We are taking space from lowest windows
4553 first, so we iterate over children from the last child
4554 backwards. */
4555 for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
4556 last_child = child;
4558 /* Size children down to their safe heights. */
4559 for (child = last_child; delta && !NILP (child); child = c->prev)
4561 int this_one;
4563 c = XWINDOW (child);
4564 this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
4566 if (this_one > delta)
4567 this_one = delta;
4569 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4570 delta -= this_one;
4573 /* Compute new positions. */
4574 last_top = XINT (w->top_line);
4575 for (child = w->vchild; !NILP (child); child = c->next)
4577 c = XWINDOW (child);
4578 c->top_line = make_number (last_top);
4579 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4580 last_top += XFASTINT (c->total_lines);
4586 /* Save, restore, or check positions and sizes in the window tree
4587 rooted at W. ACTION says what to do.
4589 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4590 orig_total_lines members are valid for all windows in the window
4591 tree. Value is non-zero if they are valid.
4593 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4594 orig_top_line and orig_total_lines for all windows in the tree.
4596 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4597 stored in orig_top_line and orig_total_lines for all windows. */
4599 static int
4600 save_restore_orig_size (w, action)
4601 struct window *w;
4602 enum save_restore_action action;
4604 int success_p = 1;
4606 while (w)
4608 if (!NILP (w->hchild))
4610 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4611 success_p = 0;
4613 else if (!NILP (w->vchild))
4615 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4616 success_p = 0;
4619 switch (action)
4621 case CHECK_ORIG_SIZES:
4622 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4623 return 0;
4624 break;
4626 case SAVE_ORIG_SIZES:
4627 w->orig_top_line = w->top_line;
4628 w->orig_total_lines = w->total_lines;
4629 XSETFASTINT (w->last_modified, 0);
4630 XSETFASTINT (w->last_overlay_modified, 0);
4631 break;
4633 case RESTORE_ORIG_SIZES:
4634 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4635 w->top_line = w->orig_top_line;
4636 w->total_lines = w->orig_total_lines;
4637 w->orig_total_lines = w->orig_top_line = Qnil;
4638 XSETFASTINT (w->last_modified, 0);
4639 XSETFASTINT (w->last_overlay_modified, 0);
4640 break;
4642 default:
4643 abort ();
4646 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4649 return success_p;
4653 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4654 without deleting other windows. */
4656 void
4657 grow_mini_window (w, delta)
4658 struct window *w;
4659 int delta;
4661 struct frame *f = XFRAME (w->frame);
4662 struct window *root;
4664 xassert (MINI_WINDOW_P (w));
4665 /* Commenting out the following assertion goes against the stated interface
4666 of the function, but it currently does not seem to do anything useful.
4667 See discussion of this issue in the thread for bug#4534.
4668 xassert (delta >= 0); */
4670 /* Compute how much we can enlarge the mini-window without deleting
4671 other windows. */
4672 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4673 if (delta > 0)
4675 int min_height = window_min_size (root, 0, 0, 0, 0);
4676 if (XFASTINT (root->total_lines) - delta < min_height)
4677 /* Note that the root window may already be smaller than
4678 min_height. */
4679 delta = max (0, XFASTINT (root->total_lines) - min_height);
4682 if (delta)
4684 /* Save original window sizes and positions, if not already done. */
4685 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4686 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4688 /* Shrink other windows. */
4689 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4691 /* Grow the mini-window. */
4692 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4693 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4694 XSETFASTINT (w->last_modified, 0);
4695 XSETFASTINT (w->last_overlay_modified, 0);
4697 adjust_glyphs (f);
4702 /* Shrink mini-window W. If there is recorded info about window sizes
4703 before a call to grow_mini_window, restore recorded window sizes.
4704 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4705 line. */
4707 void
4708 shrink_mini_window (w)
4709 struct window *w;
4711 struct frame *f = XFRAME (w->frame);
4712 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4714 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4716 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4717 adjust_glyphs (f);
4718 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4719 windows_or_buffers_changed = 1;
4721 else if (XFASTINT (w->total_lines) > 1)
4723 /* Distribute the additional lines of the mini-window
4724 among the other windows. */
4725 Lisp_Object window;
4726 XSETWINDOW (window, w);
4727 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4733 /* Mark window cursors off for all windows in the window tree rooted
4734 at W by setting their phys_cursor_on_p flag to zero. Called from
4735 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4736 the frame are cleared. */
4738 void
4739 mark_window_cursors_off (w)
4740 struct window *w;
4742 while (w)
4744 if (!NILP (w->hchild))
4745 mark_window_cursors_off (XWINDOW (w->hchild));
4746 else if (!NILP (w->vchild))
4747 mark_window_cursors_off (XWINDOW (w->vchild));
4748 else
4749 w->phys_cursor_on_p = 0;
4751 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4756 /* Return number of lines of text (not counting mode lines) in W. */
4759 window_internal_height (w)
4760 struct window *w;
4762 int ht = XFASTINT (w->total_lines);
4764 if (!MINI_WINDOW_P (w))
4766 if (!NILP (w->parent)
4767 || !NILP (w->vchild)
4768 || !NILP (w->hchild)
4769 || !NILP (w->next)
4770 || !NILP (w->prev)
4771 || WINDOW_WANTS_MODELINE_P (w))
4772 --ht;
4774 if (WINDOW_WANTS_HEADER_LINE_P (w))
4775 --ht;
4778 return ht;
4782 /* Return the number of columns in W.
4783 Don't count columns occupied by scroll bars or the vertical bar
4784 separating W from the sibling to its right. */
4787 window_box_text_cols (w)
4788 struct window *w;
4790 struct frame *f = XFRAME (WINDOW_FRAME (w));
4791 int width = XINT (w->total_cols);
4793 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4794 /* Scroll bars occupy a few columns. */
4795 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4796 else if (!FRAME_WINDOW_P (f)
4797 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4798 /* The column of `|' characters separating side-by-side windows
4799 occupies one column only. */
4800 width -= 1;
4802 if (FRAME_WINDOW_P (f))
4803 /* On window-systems, fringes and display margins cannot be
4804 used for normal text. */
4805 width -= (WINDOW_FRINGE_COLS (w)
4806 + WINDOW_LEFT_MARGIN_COLS (w)
4807 + WINDOW_RIGHT_MARGIN_COLS (w));
4809 return width;
4813 /************************************************************************
4814 Window Scrolling
4815 ***********************************************************************/
4817 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4818 N screen-fulls, which is defined as the height of the window minus
4819 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4820 instead. Negative values of N mean scroll down. NOERROR non-zero
4821 means don't signal an error if we try to move over BEGV or ZV,
4822 respectively. */
4824 static void
4825 window_scroll (window, n, whole, noerror)
4826 Lisp_Object window;
4827 int n;
4828 int whole;
4829 int noerror;
4831 immediate_quit = 1;
4833 /* If we must, use the pixel-based version which is much slower than
4834 the line-based one but can handle varying line heights. */
4835 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4836 window_scroll_pixel_based (window, n, whole, noerror);
4837 else
4838 window_scroll_line_based (window, n, whole, noerror);
4840 immediate_quit = 0;
4844 /* Implementation of window_scroll that works based on pixel line
4845 heights. See the comment of window_scroll for parameter
4846 descriptions. */
4848 static void
4849 window_scroll_pixel_based (window, n, whole, noerror)
4850 Lisp_Object window;
4851 int n;
4852 int whole;
4853 int noerror;
4855 struct it it;
4856 struct window *w = XWINDOW (window);
4857 struct text_pos start;
4858 int this_scroll_margin;
4859 /* True if we fiddled the window vscroll field without really scrolling. */
4860 int vscrolled = 0;
4861 int x, y, rtop, rbot, rowh, vpos;
4863 SET_TEXT_POS_FROM_MARKER (start, w->start);
4865 /* If PT is not visible in WINDOW, move back one half of
4866 the screen. Allow PT to be partially visible, otherwise
4867 something like (scroll-down 1) with PT in the line before
4868 the partially visible one would recenter. */
4870 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4872 /* Move backward half the height of the window. Performance note:
4873 vmotion used here is about 10% faster, but would give wrong
4874 results for variable height lines. */
4875 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4876 it.current_y = it.last_visible_y;
4877 move_it_vertically_backward (&it, window_box_height (w) / 2);
4879 /* The function move_iterator_vertically may move over more than
4880 the specified y-distance. If it->w is small, e.g. a
4881 mini-buffer window, we may end up in front of the window's
4882 display area. This is the case when Start displaying at the
4883 start of the line containing PT in this case. */
4884 if (it.current_y <= 0)
4886 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4887 move_it_vertically_backward (&it, 0);
4888 it.current_y = 0;
4891 start = it.current.pos;
4893 else if (auto_window_vscroll_p)
4895 if (rtop || rbot) /* partially visible */
4897 int px;
4898 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4899 if (whole)
4900 dy = max ((window_box_height (w)
4901 - next_screen_context_lines * dy),
4902 dy);
4903 dy *= n;
4905 if (n < 0)
4907 /* Only vscroll backwards if already vscrolled forwards. */
4908 if (w->vscroll < 0 && rtop > 0)
4910 px = max (0, -w->vscroll - min (rtop, -dy));
4911 Fset_window_vscroll (window, make_number (px), Qt);
4912 return;
4915 if (n > 0)
4917 /* Do vscroll if already vscrolled or only display line. */
4918 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4920 px = max (0, -w->vscroll + min (rbot, dy));
4921 Fset_window_vscroll (window, make_number (px), Qt);
4922 return;
4925 /* Maybe modify window start instead of scrolling. */
4926 if (rbot > 0 || w->vscroll < 0)
4928 int spos;
4930 Fset_window_vscroll (window, make_number (0), Qt);
4931 /* If there are other text lines above the current row,
4932 move window start to current row. Else to next row. */
4933 if (rbot > 0)
4934 spos = XINT (Fline_beginning_position (Qnil));
4935 else
4936 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4937 set_marker_restricted (w->start, make_number (spos),
4938 w->buffer);
4939 w->start_at_line_beg = Qt;
4940 w->update_mode_line = Qt;
4941 XSETFASTINT (w->last_modified, 0);
4942 XSETFASTINT (w->last_overlay_modified, 0);
4943 /* Set force_start so that redisplay_window will run the
4944 window-scroll-functions. */
4945 w->force_start = Qt;
4946 return;
4950 /* Cancel previous vscroll. */
4951 Fset_window_vscroll (window, make_number (0), Qt);
4954 /* If scroll_preserve_screen_position is non-nil, we try to set
4955 point in the same window line as it is now, so get that line. */
4956 if (!NILP (Vscroll_preserve_screen_position))
4958 /* We preserve the goal pixel coordinate across consecutive
4959 calls to scroll-up or scroll-down. This avoids the
4960 possibility of point becoming "stuck" on a tall line when
4961 scrolling by one line. */
4962 if (window_scroll_pixel_based_preserve_y < 0
4963 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
4964 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
4966 start_display (&it, w, start);
4967 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4968 window_scroll_pixel_based_preserve_y = it.current_y;
4969 window_scroll_pixel_based_preserve_x = it.current_x;
4972 else
4973 window_scroll_pixel_based_preserve_y
4974 = window_scroll_pixel_based_preserve_x = -1;
4976 /* Move iterator it from start the specified distance forward or
4977 backward. The result is the new window start. */
4978 start_display (&it, w, start);
4979 if (whole)
4981 int start_pos = IT_CHARPOS (it);
4982 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4983 dy = max ((window_box_height (w)
4984 - next_screen_context_lines * dy),
4985 dy) * n;
4987 /* Note that move_it_vertically always moves the iterator to the
4988 start of a line. So, if the last line doesn't have a newline,
4989 we would end up at the start of the line ending at ZV. */
4990 if (dy <= 0)
4992 move_it_vertically_backward (&it, -dy);
4993 /* Ensure we actually do move, e.g. in case we are currently
4994 looking at an image that is taller that the window height. */
4995 while (start_pos == IT_CHARPOS (it)
4996 && start_pos > BEGV)
4997 move_it_by_lines (&it, -1, 1);
4999 else if (dy > 0)
5001 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5002 MOVE_TO_POS | MOVE_TO_Y);
5003 /* Ensure we actually do move, e.g. in case we are currently
5004 looking at an image that is taller that the window height. */
5005 while (start_pos == IT_CHARPOS (it)
5006 && start_pos < ZV)
5007 move_it_by_lines (&it, 1, 1);
5010 else
5011 move_it_by_lines (&it, n, 1);
5013 /* We failed if we find ZV is already on the screen (scrolling up,
5014 means there's nothing past the end), or if we can't start any
5015 earlier (scrolling down, means there's nothing past the top). */
5016 if ((n > 0 && IT_CHARPOS (it) == ZV)
5017 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5019 if (IT_CHARPOS (it) == ZV)
5021 if (it.current_y < it.last_visible_y
5022 && (it.current_y + it.max_ascent + it.max_descent
5023 > it.last_visible_y))
5025 /* The last line was only partially visible, make it fully
5026 visible. */
5027 w->vscroll = (it.last_visible_y
5028 - it.current_y + it.max_ascent + it.max_descent);
5029 adjust_glyphs (it.f);
5031 else if (noerror)
5032 return;
5033 else if (n < 0) /* could happen with empty buffers */
5034 xsignal0 (Qbeginning_of_buffer);
5035 else
5036 xsignal0 (Qend_of_buffer);
5038 else
5040 if (w->vscroll != 0)
5041 /* The first line was only partially visible, make it fully
5042 visible. */
5043 w->vscroll = 0;
5044 else if (noerror)
5045 return;
5046 else
5047 xsignal0 (Qbeginning_of_buffer);
5050 /* If control gets here, then we vscrolled. */
5052 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5054 /* Don't try to change the window start below. */
5055 vscrolled = 1;
5058 if (! vscrolled)
5060 int pos = IT_CHARPOS (it);
5061 int bytepos;
5063 /* If in the middle of a multi-glyph character move forward to
5064 the next character. */
5065 if (in_display_vector_p (&it))
5067 ++pos;
5068 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5071 /* Set the window start, and set up the window for redisplay. */
5072 set_marker_restricted (w->start, make_number (pos),
5073 w->buffer);
5074 bytepos = XMARKER (w->start)->bytepos;
5075 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5076 ? Qt : Qnil);
5077 w->update_mode_line = Qt;
5078 XSETFASTINT (w->last_modified, 0);
5079 XSETFASTINT (w->last_overlay_modified, 0);
5080 /* Set force_start so that redisplay_window will run the
5081 window-scroll-functions. */
5082 w->force_start = Qt;
5085 /* The rest of this function uses current_y in a nonstandard way,
5086 not including the height of the header line if any. */
5087 it.current_y = it.vpos = 0;
5089 /* Move PT out of scroll margins.
5090 This code wants current_y to be zero at the window start position
5091 even if there is a header line. */
5092 this_scroll_margin = max (0, scroll_margin);
5093 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5094 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5096 if (n > 0)
5098 /* We moved the window start towards ZV, so PT may be now
5099 in the scroll margin at the top. */
5100 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5101 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5102 && (NILP (Vscroll_preserve_screen_position)
5103 || EQ (Vscroll_preserve_screen_position, Qt)))
5104 /* We found PT at a legitimate height. Leave it alone. */
5106 else if (window_scroll_pixel_based_preserve_y >= 0)
5108 /* If we have a header line, take account of it.
5109 This is necessary because we set it.current_y to 0, above. */
5110 move_it_to (&it, -1,
5111 window_scroll_pixel_based_preserve_x,
5112 window_scroll_pixel_based_preserve_y
5113 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5114 -1, MOVE_TO_Y | MOVE_TO_X);
5115 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5117 else
5119 while (it.current_y < this_scroll_margin)
5121 int prev = it.current_y;
5122 move_it_by_lines (&it, 1, 1);
5123 if (prev == it.current_y)
5124 break;
5126 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5129 else if (n < 0)
5131 int charpos, bytepos;
5132 int partial_p;
5134 /* Save our position, for the
5135 window_scroll_pixel_based_preserve_y case. */
5136 charpos = IT_CHARPOS (it);
5137 bytepos = IT_BYTEPOS (it);
5139 /* We moved the window start towards BEGV, so PT may be now
5140 in the scroll margin at the bottom. */
5141 move_it_to (&it, PT, -1,
5142 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5143 - this_scroll_margin - 1),
5145 MOVE_TO_POS | MOVE_TO_Y);
5147 /* Save our position, in case it's correct. */
5148 charpos = IT_CHARPOS (it);
5149 bytepos = IT_BYTEPOS (it);
5151 /* See if point is on a partially visible line at the end. */
5152 if (it.what == IT_EOB)
5153 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5154 else
5156 move_it_by_lines (&it, 1, 1);
5157 partial_p = it.current_y > it.last_visible_y;
5160 if (charpos == PT && !partial_p
5161 && (NILP (Vscroll_preserve_screen_position)
5162 || EQ (Vscroll_preserve_screen_position, Qt)))
5163 /* We found PT before we found the display margin, so PT is ok. */
5165 else if (window_scroll_pixel_based_preserve_y >= 0)
5167 SET_TEXT_POS_FROM_MARKER (start, w->start);
5168 start_display (&it, w, start);
5169 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5170 here because we called start_display again and did not
5171 alter it.current_y this time. */
5172 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5173 window_scroll_pixel_based_preserve_y, -1,
5174 MOVE_TO_Y | MOVE_TO_X);
5175 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5177 else
5179 if (partial_p)
5180 /* The last line was only partially visible, so back up two
5181 lines to make sure we're on a fully visible line. */
5183 move_it_by_lines (&it, -2, 0);
5184 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5186 else
5187 /* No, the position we saved is OK, so use it. */
5188 SET_PT_BOTH (charpos, bytepos);
5194 /* Implementation of window_scroll that works based on screen lines.
5195 See the comment of window_scroll for parameter descriptions. */
5197 static void
5198 window_scroll_line_based (window, n, whole, noerror)
5199 Lisp_Object window;
5200 int n;
5201 int whole;
5202 int noerror;
5204 register struct window *w = XWINDOW (window);
5205 register int opoint = PT, opoint_byte = PT_BYTE;
5206 register int pos, pos_byte;
5207 register int ht = window_internal_height (w);
5208 register Lisp_Object tem;
5209 int lose;
5210 Lisp_Object bolp;
5211 int startpos;
5212 Lisp_Object original_pos = Qnil;
5214 /* If scrolling screen-fulls, compute the number of lines to
5215 scroll from the window's height. */
5216 if (whole)
5217 n *= max (1, ht - next_screen_context_lines);
5219 startpos = marker_position (w->start);
5221 if (!NILP (Vscroll_preserve_screen_position))
5223 if (window_scroll_preserve_vpos <= 0
5224 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5225 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5227 struct position posit
5228 = *compute_motion (startpos, 0, 0, 0,
5229 PT, ht, 0,
5230 -1, XINT (w->hscroll),
5231 0, w);
5232 window_scroll_preserve_vpos = posit.vpos;
5233 window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
5236 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5237 make_number (window_scroll_preserve_vpos));
5240 XSETFASTINT (tem, PT);
5241 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5243 if (NILP (tem))
5245 Fvertical_motion (make_number (- (ht / 2)), window);
5246 startpos = PT;
5249 SET_PT (startpos);
5250 lose = n < 0 && PT == BEGV;
5251 Fvertical_motion (make_number (n), window);
5252 pos = PT;
5253 pos_byte = PT_BYTE;
5254 bolp = Fbolp ();
5255 SET_PT_BOTH (opoint, opoint_byte);
5257 if (lose)
5259 if (noerror)
5260 return;
5261 else
5262 xsignal0 (Qbeginning_of_buffer);
5265 if (pos < ZV)
5267 int this_scroll_margin = scroll_margin;
5269 /* Don't use a scroll margin that is negative or too large. */
5270 if (this_scroll_margin < 0)
5271 this_scroll_margin = 0;
5273 if (XINT (w->total_lines) < 4 * scroll_margin)
5274 this_scroll_margin = XINT (w->total_lines) / 4;
5276 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5277 w->start_at_line_beg = bolp;
5278 w->update_mode_line = Qt;
5279 XSETFASTINT (w->last_modified, 0);
5280 XSETFASTINT (w->last_overlay_modified, 0);
5281 /* Set force_start so that redisplay_window will run
5282 the window-scroll-functions. */
5283 w->force_start = Qt;
5285 if (!NILP (Vscroll_preserve_screen_position)
5286 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5288 SET_PT_BOTH (pos, pos_byte);
5289 Fvertical_motion (original_pos, window);
5291 /* If we scrolled forward, put point enough lines down
5292 that it is outside the scroll margin. */
5293 else if (n > 0)
5295 int top_margin;
5297 if (this_scroll_margin > 0)
5299 SET_PT_BOTH (pos, pos_byte);
5300 Fvertical_motion (make_number (this_scroll_margin), window);
5301 top_margin = PT;
5303 else
5304 top_margin = pos;
5306 if (top_margin <= opoint)
5307 SET_PT_BOTH (opoint, opoint_byte);
5308 else if (!NILP (Vscroll_preserve_screen_position))
5310 SET_PT_BOTH (pos, pos_byte);
5311 Fvertical_motion (original_pos, window);
5313 else
5314 SET_PT (top_margin);
5316 else if (n < 0)
5318 int bottom_margin;
5320 /* If we scrolled backward, put point near the end of the window
5321 but not within the scroll margin. */
5322 SET_PT_BOTH (pos, pos_byte);
5323 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5324 if (XFASTINT (tem) == ht - this_scroll_margin)
5325 bottom_margin = PT;
5326 else
5327 bottom_margin = PT + 1;
5329 if (bottom_margin > opoint)
5330 SET_PT_BOTH (opoint, opoint_byte);
5331 else
5333 if (!NILP (Vscroll_preserve_screen_position))
5335 SET_PT_BOTH (pos, pos_byte);
5336 Fvertical_motion (original_pos, window);
5338 else
5339 Fvertical_motion (make_number (-1), window);
5343 else
5345 if (noerror)
5346 return;
5347 else
5348 xsignal0 (Qend_of_buffer);
5353 /* Scroll selected_window up or down. If N is nil, scroll a
5354 screen-full which is defined as the height of the window minus
5355 next_screen_context_lines. If N is the symbol `-', scroll.
5356 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5357 up. This is the guts of Fscroll_up and Fscroll_down. */
5359 static void
5360 scroll_command (n, direction)
5361 Lisp_Object n;
5362 int direction;
5364 int count = SPECPDL_INDEX ();
5366 xassert (eabs (direction) == 1);
5368 /* If selected window's buffer isn't current, make it current for
5369 the moment. But don't screw up if window_scroll gets an error. */
5370 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5372 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5373 Fset_buffer (XWINDOW (selected_window)->buffer);
5375 /* Make redisplay consider other windows than just selected_window. */
5376 ++windows_or_buffers_changed;
5379 if (NILP (n))
5380 window_scroll (selected_window, direction, 1, 0);
5381 else if (EQ (n, Qminus))
5382 window_scroll (selected_window, -direction, 1, 0);
5383 else
5385 n = Fprefix_numeric_value (n);
5386 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5389 unbind_to (count, Qnil);
5392 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5393 doc: /* Scroll text of selected window upward ARG lines.
5394 If ARG is omitted or nil, scroll upward by a near full screen.
5395 A near full screen is `next-screen-context-lines' less than a full screen.
5396 Negative ARG means scroll downward.
5397 If ARG is the atom `-', scroll downward by nearly full screen.
5398 When calling from a program, supply as argument a number, nil, or `-'. */)
5399 (arg)
5400 Lisp_Object arg;
5402 scroll_command (arg, 1);
5403 return Qnil;
5406 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5407 doc: /* Scroll text of selected window down ARG lines.
5408 If ARG is omitted or nil, scroll down by a near full screen.
5409 A near full screen is `next-screen-context-lines' less than a full screen.
5410 Negative ARG means scroll upward.
5411 If ARG is the atom `-', scroll upward by nearly full screen.
5412 When calling from a program, supply as argument a number, nil, or `-'. */)
5413 (arg)
5414 Lisp_Object arg;
5416 scroll_command (arg, -1);
5417 return Qnil;
5420 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5421 doc: /* Return the other window for \"other window scroll\" commands.
5422 If `other-window-scroll-buffer' is non-nil, a window
5423 showing that buffer is used.
5424 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5425 specifies the window. This takes precedence over
5426 `other-window-scroll-buffer'. */)
5429 Lisp_Object window;
5431 if (MINI_WINDOW_P (XWINDOW (selected_window))
5432 && !NILP (Vminibuf_scroll_window))
5433 window = Vminibuf_scroll_window;
5434 /* If buffer is specified, scroll that buffer. */
5435 else if (!NILP (Vother_window_scroll_buffer))
5437 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5438 if (NILP (window))
5439 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5441 else
5443 /* Nothing specified; look for a neighboring window on the same
5444 frame. */
5445 window = Fnext_window (selected_window, Qnil, Qnil);
5447 if (EQ (window, selected_window))
5448 /* That didn't get us anywhere; look for a window on another
5449 visible frame. */
5451 window = Fnext_window (window, Qnil, Qt);
5452 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5453 && ! EQ (window, selected_window));
5456 CHECK_LIVE_WINDOW (window);
5458 if (EQ (window, selected_window))
5459 error ("There is no other window");
5461 return window;
5464 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5465 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5466 A near full screen is `next-screen-context-lines' less than a full screen.
5467 The next window is the one below the current one; or the one at the top
5468 if the current one is at the bottom. Negative ARG means scroll downward.
5469 If ARG is the atom `-', scroll downward by nearly full screen.
5470 When calling from a program, supply as argument a number, nil, or `-'.
5472 If `other-window-scroll-buffer' is non-nil, scroll the window
5473 showing that buffer, popping the buffer up if necessary.
5474 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5475 specifies the window to scroll. This takes precedence over
5476 `other-window-scroll-buffer'. */)
5477 (arg)
5478 Lisp_Object arg;
5480 Lisp_Object window;
5481 struct window *w;
5482 int count = SPECPDL_INDEX ();
5484 window = Fother_window_for_scrolling ();
5485 w = XWINDOW (window);
5487 /* Don't screw up if window_scroll gets an error. */
5488 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5489 ++windows_or_buffers_changed;
5491 Fset_buffer (w->buffer);
5492 SET_PT (marker_position (w->pointm));
5494 if (NILP (arg))
5495 window_scroll (window, 1, 1, 1);
5496 else if (EQ (arg, Qminus))
5497 window_scroll (window, -1, 1, 1);
5498 else
5500 if (CONSP (arg))
5501 arg = Fcar (arg);
5502 CHECK_NUMBER (arg);
5503 window_scroll (window, XINT (arg), 0, 1);
5506 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5507 unbind_to (count, Qnil);
5509 return Qnil;
5512 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5513 doc: /* Scroll selected window display ARG columns left.
5514 Default for ARG is window width minus 2.
5515 Value is the total amount of leftward horizontal scrolling in
5516 effect after the change.
5517 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5518 lower bound for automatic scrolling, i.e. automatic scrolling
5519 will not scroll a window to a column less than the value returned
5520 by this function. This happens in an interactive call. */)
5521 (arg, set_minimum)
5522 register Lisp_Object arg, set_minimum;
5524 Lisp_Object result;
5525 int hscroll;
5526 struct window *w = XWINDOW (selected_window);
5528 if (NILP (arg))
5529 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5530 else
5531 arg = Fprefix_numeric_value (arg);
5533 hscroll = XINT (w->hscroll) + XINT (arg);
5534 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5536 if (!NILP (set_minimum))
5537 w->min_hscroll = w->hscroll;
5539 return result;
5542 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5543 doc: /* Scroll selected window display ARG columns right.
5544 Default for ARG is window width minus 2.
5545 Value is the total amount of leftward horizontal scrolling in
5546 effect after the change.
5547 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5548 lower bound for automatic scrolling, i.e. automatic scrolling
5549 will not scroll a window to a column less than the value returned
5550 by this function. This happens in an interactive call. */)
5551 (arg, set_minimum)
5552 register Lisp_Object arg, set_minimum;
5554 Lisp_Object result;
5555 int hscroll;
5556 struct window *w = XWINDOW (selected_window);
5558 if (NILP (arg))
5559 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5560 else
5561 arg = Fprefix_numeric_value (arg);
5563 hscroll = XINT (w->hscroll) - XINT (arg);
5564 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5566 if (!NILP (set_minimum))
5567 w->min_hscroll = w->hscroll;
5569 return result;
5572 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5573 doc: /* Return the window which was selected when entering the minibuffer.
5574 Returns nil, if selected window is not a minibuffer window. */)
5577 if (minibuf_level > 0
5578 && MINI_WINDOW_P (XWINDOW (selected_window))
5579 && WINDOW_LIVE_P (minibuf_selected_window))
5580 return minibuf_selected_window;
5582 return Qnil;
5585 /* Value is the number of lines actually displayed in window W,
5586 as opposed to its height. */
5588 static int
5589 displayed_window_lines (w)
5590 struct window *w;
5592 struct it it;
5593 struct text_pos start;
5594 int height = window_box_height (w);
5595 struct buffer *old_buffer;
5596 int bottom_y;
5598 if (XBUFFER (w->buffer) != current_buffer)
5600 old_buffer = current_buffer;
5601 set_buffer_internal (XBUFFER (w->buffer));
5603 else
5604 old_buffer = NULL;
5606 /* In case W->start is out of the accessible range, do something
5607 reasonable. This happens in Info mode when Info-scroll-down
5608 calls (recenter -1) while W->start is 1. */
5609 if (XMARKER (w->start)->charpos < BEGV)
5610 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5611 else if (XMARKER (w->start)->charpos > ZV)
5612 SET_TEXT_POS (start, ZV, ZV_BYTE);
5613 else
5614 SET_TEXT_POS_FROM_MARKER (start, w->start);
5616 start_display (&it, w, start);
5617 move_it_vertically (&it, height);
5618 bottom_y = line_bottom_y (&it);
5620 /* rms: On a non-window display,
5621 the value of it.vpos at the bottom of the screen
5622 seems to be 1 larger than window_box_height (w).
5623 This kludge fixes a bug whereby (move-to-window-line -1)
5624 when ZV is on the last screen line
5625 moves to the previous screen line instead of the last one. */
5626 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5627 height++;
5629 /* Add in empty lines at the bottom of the window. */
5630 if (bottom_y < height)
5632 int uy = FRAME_LINE_HEIGHT (it.f);
5633 it.vpos += (height - bottom_y + uy - 1) / uy;
5636 if (old_buffer)
5637 set_buffer_internal (old_buffer);
5639 return it.vpos;
5643 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5644 doc: /* Center point in selected window and maybe redisplay frame.
5645 With prefix argument ARG, recenter putting point on screen line ARG
5646 relative to the selected window. If ARG is negative, it counts up from the
5647 bottom of the window. (ARG should be less than the height of the window.)
5649 If ARG is omitted or nil, then recenter with point on the middle line of
5650 the selected window; if the variable `recenter-redisplay' is non-nil,
5651 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5652 is set to `grow-only', this resets the tool-bar's height to the minimum
5653 height needed); if `recenter-redisplay' has the special value `tty',
5654 then only tty frame are redrawn.
5656 Just C-u as prefix means put point in the center of the window
5657 and redisplay normally--don't erase and redraw the frame. */)
5658 (arg)
5659 register Lisp_Object arg;
5661 struct window *w = XWINDOW (selected_window);
5662 struct buffer *buf = XBUFFER (w->buffer);
5663 struct buffer *obuf = current_buffer;
5664 int center_p = 0;
5665 int charpos, bytepos;
5666 int iarg;
5667 int this_scroll_margin;
5669 /* If redisplay is suppressed due to an error, try again. */
5670 obuf->display_error_modiff = 0;
5672 if (NILP (arg))
5674 if (!NILP (Vrecenter_redisplay)
5675 && (!EQ (Vrecenter_redisplay, Qtty)
5676 || !NILP (Ftty_type (selected_frame))))
5678 int i;
5680 /* Invalidate pixel data calculated for all compositions. */
5681 for (i = 0; i < n_compositions; i++)
5682 composition_table[i]->font = NULL;
5684 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5686 Fredraw_frame (WINDOW_FRAME (w));
5687 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5690 center_p = 1;
5692 else if (CONSP (arg)) /* Just C-u. */
5693 center_p = 1;
5694 else
5696 arg = Fprefix_numeric_value (arg);
5697 CHECK_NUMBER (arg);
5698 iarg = XINT (arg);
5701 set_buffer_internal (buf);
5703 /* Do this after making BUF current
5704 in case scroll_margin is buffer-local. */
5705 this_scroll_margin = max (0, scroll_margin);
5706 this_scroll_margin = min (this_scroll_margin,
5707 XFASTINT (w->total_lines) / 4);
5709 /* Handle centering on a graphical frame specially. Such frames can
5710 have variable-height lines and centering point on the basis of
5711 line counts would lead to strange effects. */
5712 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5714 if (center_p)
5716 struct it it;
5717 struct text_pos pt;
5719 SET_TEXT_POS (pt, PT, PT_BYTE);
5720 start_display (&it, w, pt);
5721 move_it_vertically_backward (&it, window_box_height (w) / 2);
5722 charpos = IT_CHARPOS (it);
5723 bytepos = IT_BYTEPOS (it);
5725 else if (iarg < 0)
5727 struct it it;
5728 struct text_pos pt;
5729 int nlines = -iarg;
5730 int extra_line_spacing;
5731 int h = window_box_height (w);
5733 iarg = - max (-iarg, this_scroll_margin);
5735 SET_TEXT_POS (pt, PT, PT_BYTE);
5736 start_display (&it, w, pt);
5738 /* Be sure we have the exact height of the full line containing PT. */
5739 move_it_by_lines (&it, 0, 1);
5741 /* The amount of pixels we have to move back is the window
5742 height minus what's displayed in the line containing PT,
5743 and the lines below. */
5744 it.current_y = 0;
5745 it.vpos = 0;
5746 move_it_by_lines (&it, nlines, 1);
5748 if (it.vpos == nlines)
5749 h -= it.current_y;
5750 else
5752 /* Last line has no newline */
5753 h -= line_bottom_y (&it);
5754 it.vpos++;
5757 /* Don't reserve space for extra line spacing of last line. */
5758 extra_line_spacing = it.max_extra_line_spacing;
5760 /* If we can't move down NLINES lines because we hit
5761 the end of the buffer, count in some empty lines. */
5762 if (it.vpos < nlines)
5764 nlines -= it.vpos;
5765 extra_line_spacing = it.extra_line_spacing;
5766 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5768 if (h <= 0)
5769 return Qnil;
5771 /* Now find the new top line (starting position) of the window. */
5772 start_display (&it, w, pt);
5773 it.current_y = 0;
5774 move_it_vertically_backward (&it, h);
5776 /* If extra line spacing is present, we may move too far
5777 back. This causes the last line to be only partially
5778 visible (which triggers redisplay to recenter that line
5779 in the middle), so move forward.
5780 But ignore extra line spacing on last line, as it is not
5781 considered to be part of the visible height of the line.
5783 h += extra_line_spacing;
5784 while (-it.current_y > h)
5785 move_it_by_lines (&it, 1, 1);
5787 charpos = IT_CHARPOS (it);
5788 bytepos = IT_BYTEPOS (it);
5790 else
5792 struct position pos;
5794 iarg = max (iarg, this_scroll_margin);
5796 pos = *vmotion (PT, -iarg, w);
5797 charpos = pos.bufpos;
5798 bytepos = pos.bytepos;
5801 else
5803 struct position pos;
5804 int ht = window_internal_height (w);
5806 if (center_p)
5807 iarg = ht / 2;
5808 else if (iarg < 0)
5809 iarg += ht;
5811 /* Don't let it get into the margin at either top or bottom. */
5812 iarg = max (iarg, this_scroll_margin);
5813 iarg = min (iarg, ht - this_scroll_margin - 1);
5815 pos = *vmotion (PT, - iarg, w);
5816 charpos = pos.bufpos;
5817 bytepos = pos.bytepos;
5820 /* Set the new window start. */
5821 set_marker_both (w->start, w->buffer, charpos, bytepos);
5822 w->window_end_valid = Qnil;
5824 w->optional_new_start = Qt;
5826 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5827 w->start_at_line_beg = Qt;
5828 else
5829 w->start_at_line_beg = Qnil;
5831 set_buffer_internal (obuf);
5832 return Qnil;
5836 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5837 0, 1, 0,
5838 doc: /* Return the height in lines of the text display area of WINDOW.
5839 WINDOW defaults to the selected window.
5841 The return value does not include the mode line, any header line, nor
5842 any partial-height lines in the text display area. */)
5843 (window)
5844 Lisp_Object window;
5846 struct window *w = decode_window (window);
5847 int pixel_height = window_box_height (w);
5848 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5849 return make_number (line_height);
5854 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5855 1, 1, "P",
5856 doc: /* Position point relative to window.
5857 With no argument, position point at center of window.
5858 An argument specifies vertical position within the window;
5859 zero means top of window, negative means relative to bottom of window. */)
5860 (arg)
5861 Lisp_Object arg;
5863 struct window *w = XWINDOW (selected_window);
5864 int lines, start;
5865 Lisp_Object window;
5866 #if 0
5867 int this_scroll_margin;
5868 #endif
5870 if (!(BUFFERP (w->buffer)
5871 && XBUFFER (w->buffer) == current_buffer))
5872 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5873 when passed below to set_marker_both. */
5874 error ("move-to-window-line called from unrelated buffer");
5876 window = selected_window;
5877 start = marker_position (w->start);
5878 if (start < BEGV || start > ZV)
5880 int height = window_internal_height (w);
5881 Fvertical_motion (make_number (- (height / 2)), window);
5882 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5883 w->start_at_line_beg = Fbolp ();
5884 w->force_start = Qt;
5886 else
5887 Fgoto_char (w->start);
5889 lines = displayed_window_lines (w);
5891 #if 0
5892 this_scroll_margin = max (0, scroll_margin);
5893 this_scroll_margin = min (this_scroll_margin, lines / 4);
5894 #endif
5896 if (NILP (arg))
5897 XSETFASTINT (arg, lines / 2);
5898 else
5900 int iarg = XINT (Fprefix_numeric_value (arg));
5902 if (iarg < 0)
5903 iarg = iarg + lines;
5905 #if 0 /* This code would prevent move-to-window-line from moving point
5906 to a place inside the scroll margins (which would cause the
5907 next redisplay to scroll). I wrote this code, but then concluded
5908 it is probably better not to install it. However, it is here
5909 inside #if 0 so as not to lose it. -- rms. */
5911 /* Don't let it get into the margin at either top or bottom. */
5912 iarg = max (iarg, this_scroll_margin);
5913 iarg = min (iarg, lines - this_scroll_margin - 1);
5914 #endif
5916 arg = make_number (iarg);
5919 /* Skip past a partially visible first line. */
5920 if (w->vscroll)
5921 XSETINT (arg, XINT (arg) + 1);
5923 return Fvertical_motion (arg, window);
5928 /***********************************************************************
5929 Window Configuration
5930 ***********************************************************************/
5932 struct save_window_data
5934 EMACS_UINT size;
5935 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5936 Lisp_Object selected_frame;
5937 Lisp_Object current_window;
5938 Lisp_Object current_buffer;
5939 Lisp_Object minibuf_scroll_window;
5940 Lisp_Object minibuf_selected_window;
5941 Lisp_Object root_window;
5942 Lisp_Object focus_frame;
5943 /* A vector, each of whose elements is a struct saved_window
5944 for one window. */
5945 Lisp_Object saved_windows;
5947 /* All fields above are traced by the GC.
5948 From `fame-cols' down, the fields are ignored by the GC. */
5950 int frame_cols, frame_lines, frame_menu_bar_lines;
5951 int frame_tool_bar_lines;
5954 /* This is saved as a Lisp_Vector */
5955 struct saved_window
5957 /* these first two must agree with struct Lisp_Vector in lisp.h */
5958 EMACS_UINT size;
5959 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5961 Lisp_Object window;
5962 Lisp_Object buffer, start, pointm, mark;
5963 Lisp_Object left_col, top_line, total_cols, total_lines;
5964 Lisp_Object hscroll, min_hscroll;
5965 Lisp_Object parent, prev;
5966 Lisp_Object start_at_line_beg;
5967 Lisp_Object display_table;
5968 Lisp_Object orig_top_line, orig_total_lines;
5969 Lisp_Object left_margin_cols, right_margin_cols;
5970 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5971 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5972 Lisp_Object dedicated, resize_proportionally;
5975 #define SAVED_WINDOW_N(swv,n) \
5976 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5978 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5979 doc: /* Return t if OBJECT is a window-configuration object. */)
5980 (object)
5981 Lisp_Object object;
5983 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5986 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5987 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5988 (config)
5989 Lisp_Object config;
5991 register struct save_window_data *data;
5992 struct Lisp_Vector *saved_windows;
5994 CHECK_WINDOW_CONFIGURATION (config);
5996 data = (struct save_window_data *) XVECTOR (config);
5997 saved_windows = XVECTOR (data->saved_windows);
5998 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6001 DEFUN ("set-window-configuration", Fset_window_configuration,
6002 Sset_window_configuration, 1, 1, 0,
6003 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6004 CONFIGURATION must be a value previously returned
6005 by `current-window-configuration' (which see).
6006 If CONFIGURATION was made from a frame that is now deleted,
6007 only frame-independent values can be restored. In this case,
6008 the return value is nil. Otherwise the value is t. */)
6009 (configuration)
6010 Lisp_Object configuration;
6012 register struct save_window_data *data;
6013 struct Lisp_Vector *saved_windows;
6014 Lisp_Object new_current_buffer;
6015 Lisp_Object frame;
6016 FRAME_PTR f;
6017 int old_point = -1;
6019 CHECK_WINDOW_CONFIGURATION (configuration);
6021 data = (struct save_window_data *) XVECTOR (configuration);
6022 saved_windows = XVECTOR (data->saved_windows);
6024 new_current_buffer = data->current_buffer;
6025 if (NILP (XBUFFER (new_current_buffer)->name))
6026 new_current_buffer = Qnil;
6027 else
6029 if (XBUFFER (new_current_buffer) == current_buffer)
6030 /* The code further down "preserves point" by saving here PT in
6031 old_point and then setting it later back into PT. When the
6032 current-selected-window and the final-selected-window both show
6033 the current buffer, this suffers from the problem that the
6034 current PT is the window-point of the current-selected-window,
6035 while the final PT is the point of the final-selected-window, so
6036 this copy from one PT to the other would end up moving the
6037 window-point of the final-selected-window to the window-point of
6038 the current-selected-window. So we have to be careful which
6039 point of the current-buffer we copy into old_point. */
6040 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6041 && WINDOWP (selected_window)
6042 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
6043 && !EQ (selected_window, data->current_window))
6044 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6045 else
6046 old_point = PT;
6047 else
6048 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6049 point in new_current_buffer as of the last time this buffer was
6050 used. This can be non-deterministic since it can be changed by
6051 things like jit-lock by mere temporary selection of some random
6052 window that happens to show this buffer.
6053 So if possible we want this arbitrary choice of "which point" to
6054 be the one from the to-be-selected-window so as to prevent this
6055 window's cursor from being copied from another window. */
6056 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6057 /* If current_window = selected_window, its point is in BUF_PT. */
6058 && !EQ (selected_window, data->current_window))
6059 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6060 else
6061 old_point = BUF_PT (XBUFFER (new_current_buffer));
6064 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6065 f = XFRAME (frame);
6067 /* If f is a dead frame, don't bother rebuilding its window tree.
6068 However, there is other stuff we should still try to do below. */
6069 if (FRAME_LIVE_P (f))
6071 register struct window *w;
6072 register struct saved_window *p;
6073 struct window *root_window;
6074 struct window **leaf_windows;
6075 int n_leaf_windows;
6076 int k, i, n;
6078 /* If the frame has been resized since this window configuration was
6079 made, we change the frame to the size specified in the
6080 configuration, restore the configuration, and then resize it
6081 back. We keep track of the prevailing height in these variables. */
6082 int previous_frame_lines = FRAME_LINES (f);
6083 int previous_frame_cols = FRAME_COLS (f);
6084 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6085 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6087 /* The mouse highlighting code could get screwed up
6088 if it runs during this. */
6089 BLOCK_INPUT;
6091 if (data->frame_lines != previous_frame_lines
6092 || data->frame_cols != previous_frame_cols)
6093 change_frame_size (f, data->frame_lines,
6094 data->frame_cols, 0, 0, 0);
6095 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6096 if (data->frame_menu_bar_lines
6097 != previous_frame_menu_bar_lines)
6098 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
6099 make_number (0));
6100 #ifdef HAVE_WINDOW_SYSTEM
6101 if (data->frame_tool_bar_lines
6102 != previous_frame_tool_bar_lines)
6103 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
6104 make_number (0));
6105 #endif
6106 #endif
6108 /* "Swap out" point from the selected window's buffer
6109 into the window itself. (Normally the pointm of the selected
6110 window holds garbage.) We do this now, before
6111 restoring the window contents, and prevent it from
6112 being done later on when we select a new window. */
6113 if (! NILP (XWINDOW (selected_window)->buffer))
6115 w = XWINDOW (selected_window);
6116 set_marker_both (w->pointm,
6117 w->buffer,
6118 BUF_PT (XBUFFER (w->buffer)),
6119 BUF_PT_BYTE (XBUFFER (w->buffer)));
6122 windows_or_buffers_changed++;
6123 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6125 /* Problem: Freeing all matrices and later allocating them again
6126 is a serious redisplay flickering problem. What we would
6127 really like to do is to free only those matrices not reused
6128 below. */
6129 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6130 leaf_windows
6131 = (struct window **) alloca (count_windows (root_window)
6132 * sizeof (struct window *));
6133 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6135 /* Kludge Alert!
6136 Mark all windows now on frame as "deleted".
6137 Restoring the new configuration "undeletes" any that are in it.
6139 Save their current buffers in their height fields, since we may
6140 need it later, if a buffer saved in the configuration is now
6141 dead. */
6142 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6144 for (k = 0; k < saved_windows->size; k++)
6146 p = SAVED_WINDOW_N (saved_windows, k);
6147 w = XWINDOW (p->window);
6148 w->next = Qnil;
6150 if (!NILP (p->parent))
6151 w->parent = SAVED_WINDOW_N (saved_windows,
6152 XFASTINT (p->parent))->window;
6153 else
6154 w->parent = Qnil;
6156 if (!NILP (p->prev))
6158 w->prev = SAVED_WINDOW_N (saved_windows,
6159 XFASTINT (p->prev))->window;
6160 XWINDOW (w->prev)->next = p->window;
6162 else
6164 w->prev = Qnil;
6165 if (!NILP (w->parent))
6167 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6169 XWINDOW (w->parent)->vchild = p->window;
6170 XWINDOW (w->parent)->hchild = Qnil;
6172 else
6174 XWINDOW (w->parent)->hchild = p->window;
6175 XWINDOW (w->parent)->vchild = Qnil;
6180 /* If we squirreled away the buffer in the window's height,
6181 restore it now. */
6182 if (BUFFERP (w->total_lines))
6183 w->buffer = w->total_lines;
6184 w->left_col = p->left_col;
6185 w->top_line = p->top_line;
6186 w->total_cols = p->total_cols;
6187 w->total_lines = p->total_lines;
6188 w->hscroll = p->hscroll;
6189 w->min_hscroll = p->min_hscroll;
6190 w->display_table = p->display_table;
6191 w->orig_top_line = p->orig_top_line;
6192 w->orig_total_lines = p->orig_total_lines;
6193 w->left_margin_cols = p->left_margin_cols;
6194 w->right_margin_cols = p->right_margin_cols;
6195 w->left_fringe_width = p->left_fringe_width;
6196 w->right_fringe_width = p->right_fringe_width;
6197 w->fringes_outside_margins = p->fringes_outside_margins;
6198 w->scroll_bar_width = p->scroll_bar_width;
6199 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6200 w->dedicated = p->dedicated;
6201 w->resize_proportionally = p->resize_proportionally;
6202 XSETFASTINT (w->last_modified, 0);
6203 XSETFASTINT (w->last_overlay_modified, 0);
6205 /* Reinstall the saved buffer and pointers into it. */
6206 if (NILP (p->buffer))
6207 w->buffer = p->buffer;
6208 else
6210 if (!NILP (XBUFFER (p->buffer)->name))
6211 /* If saved buffer is alive, install it. */
6213 w->buffer = p->buffer;
6214 w->start_at_line_beg = p->start_at_line_beg;
6215 set_marker_restricted (w->start, p->start, w->buffer);
6216 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6217 Fset_marker (XBUFFER (w->buffer)->mark,
6218 p->mark, w->buffer);
6220 /* As documented in Fcurrent_window_configuration, don't
6221 restore the location of point in the buffer which was
6222 current when the window configuration was recorded. */
6223 if (!EQ (p->buffer, new_current_buffer)
6224 && XBUFFER (p->buffer) == current_buffer)
6225 Fgoto_char (w->pointm);
6227 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6228 /* Else unless window has a live buffer, get one. */
6230 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6231 /* This will set the markers to beginning of visible
6232 range. */
6233 set_marker_restricted (w->start, make_number (0), w->buffer);
6234 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6235 w->start_at_line_beg = Qt;
6237 else
6238 /* Keeping window's old buffer; make sure the markers
6239 are real. */
6241 /* Set window markers at start of visible range. */
6242 if (XMARKER (w->start)->buffer == 0)
6243 set_marker_restricted (w->start, make_number (0),
6244 w->buffer);
6245 if (XMARKER (w->pointm)->buffer == 0)
6246 set_marker_restricted_both (w->pointm, w->buffer,
6247 BUF_PT (XBUFFER (w->buffer)),
6248 BUF_PT_BYTE (XBUFFER (w->buffer)));
6249 w->start_at_line_beg = Qt;
6254 FRAME_ROOT_WINDOW (f) = data->root_window;
6256 /* Arrange *not* to restore point in the buffer that was
6257 current when the window configuration was saved. */
6258 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6259 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6260 make_number (old_point),
6261 XWINDOW (data->current_window)->buffer);
6263 /* In the following call to `select-window, prevent "swapping
6264 out point" in the old selected window using the buffer that
6265 has been restored into it. We already swapped out that point
6266 from that window's old buffer. */
6267 select_window (data->current_window, Qnil, 1);
6268 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6269 = selected_window;
6271 if (NILP (data->focus_frame)
6272 || (FRAMEP (data->focus_frame)
6273 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6274 Fredirect_frame_focus (frame, data->focus_frame);
6276 /* Set the screen height to the value it had before this function. */
6277 if (previous_frame_lines != FRAME_LINES (f)
6278 || previous_frame_cols != FRAME_COLS (f))
6279 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6280 0, 0, 0);
6281 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6282 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6283 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6284 make_number (0));
6285 #ifdef HAVE_WINDOW_SYSTEM
6286 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6287 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6288 make_number (0));
6289 #endif
6290 #endif
6292 /* Now, free glyph matrices in windows that were not reused. */
6293 for (i = n = 0; i < n_leaf_windows; ++i)
6295 if (NILP (leaf_windows[i]->buffer))
6297 /* Assert it's not reused as a combination. */
6298 xassert (NILP (leaf_windows[i]->hchild)
6299 && NILP (leaf_windows[i]->vchild));
6300 free_window_matrices (leaf_windows[i]);
6302 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6303 ++n;
6306 adjust_glyphs (f);
6308 UNBLOCK_INPUT;
6310 /* Fselect_window will have made f the selected frame, so we
6311 reselect the proper frame here. Fhandle_switch_frame will change the
6312 selected window too, but that doesn't make the call to
6313 Fselect_window above totally superfluous; it still sets f's
6314 selected window. */
6315 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6316 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6318 run_window_configuration_change_hook (f);
6321 if (!NILP (new_current_buffer))
6322 Fset_buffer (new_current_buffer);
6324 Vminibuf_scroll_window = data->minibuf_scroll_window;
6325 minibuf_selected_window = data->minibuf_selected_window;
6327 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6330 /* Mark all windows now on frame as deleted
6331 by setting their buffers to nil. */
6333 void
6334 delete_all_subwindows (w)
6335 register struct window *w;
6337 if (!NILP (w->next))
6338 delete_all_subwindows (XWINDOW (w->next));
6339 if (!NILP (w->vchild))
6340 delete_all_subwindows (XWINDOW (w->vchild));
6341 if (!NILP (w->hchild))
6342 delete_all_subwindows (XWINDOW (w->hchild));
6344 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6346 if (!NILP (w->buffer))
6347 unshow_buffer (w);
6349 /* We set all three of these fields to nil, to make sure that we can
6350 distinguish this dead window from any live window. Live leaf
6351 windows will have buffer set, and combination windows will have
6352 vchild or hchild set. */
6353 w->buffer = Qnil;
6354 w->vchild = Qnil;
6355 w->hchild = Qnil;
6357 Vwindow_list = Qnil;
6360 static int
6361 count_windows (window)
6362 register struct window *window;
6364 register int count = 1;
6365 if (!NILP (window->next))
6366 count += count_windows (XWINDOW (window->next));
6367 if (!NILP (window->vchild))
6368 count += count_windows (XWINDOW (window->vchild));
6369 if (!NILP (window->hchild))
6370 count += count_windows (XWINDOW (window->hchild));
6371 return count;
6375 /* Fill vector FLAT with leaf windows under W, starting at index I.
6376 Value is last index + 1. */
6378 static int
6379 get_leaf_windows (w, flat, i)
6380 struct window *w;
6381 struct window **flat;
6382 int i;
6384 while (w)
6386 if (!NILP (w->hchild))
6387 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6388 else if (!NILP (w->vchild))
6389 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6390 else
6391 flat[i++] = w;
6393 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6396 return i;
6400 /* Return a pointer to the glyph W's physical cursor is on. Value is
6401 null if W's current matrix is invalid, so that no meaningfull glyph
6402 can be returned. */
6404 struct glyph *
6405 get_phys_cursor_glyph (w)
6406 struct window *w;
6408 struct glyph_row *row;
6409 struct glyph *glyph;
6411 if (w->phys_cursor.vpos >= 0
6412 && w->phys_cursor.vpos < w->current_matrix->nrows
6413 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6414 row->enabled_p)
6415 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6416 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6417 else
6418 glyph = NULL;
6420 return glyph;
6424 static int
6425 save_window_save (window, vector, i)
6426 Lisp_Object window;
6427 struct Lisp_Vector *vector;
6428 int i;
6430 register struct saved_window *p;
6431 register struct window *w;
6432 register Lisp_Object tem;
6434 for (;!NILP (window); window = w->next)
6436 p = SAVED_WINDOW_N (vector, i);
6437 w = XWINDOW (window);
6439 XSETFASTINT (w->temslot, i); i++;
6440 p->window = window;
6441 p->buffer = w->buffer;
6442 p->left_col = w->left_col;
6443 p->top_line = w->top_line;
6444 p->total_cols = w->total_cols;
6445 p->total_lines = w->total_lines;
6446 p->hscroll = w->hscroll;
6447 p->min_hscroll = w->min_hscroll;
6448 p->display_table = w->display_table;
6449 p->orig_top_line = w->orig_top_line;
6450 p->orig_total_lines = w->orig_total_lines;
6451 p->left_margin_cols = w->left_margin_cols;
6452 p->right_margin_cols = w->right_margin_cols;
6453 p->left_fringe_width = w->left_fringe_width;
6454 p->right_fringe_width = w->right_fringe_width;
6455 p->fringes_outside_margins = w->fringes_outside_margins;
6456 p->scroll_bar_width = w->scroll_bar_width;
6457 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6458 p->dedicated = w->dedicated;
6459 p->resize_proportionally = w->resize_proportionally;
6460 if (!NILP (w->buffer))
6462 /* Save w's value of point in the window configuration.
6463 If w is the selected window, then get the value of point
6464 from the buffer; pointm is garbage in the selected window. */
6465 if (EQ (window, selected_window))
6467 p->pointm = Fmake_marker ();
6468 set_marker_both (p->pointm, w->buffer,
6469 BUF_PT (XBUFFER (w->buffer)),
6470 BUF_PT_BYTE (XBUFFER (w->buffer)));
6472 else
6473 p->pointm = Fcopy_marker (w->pointm, Qnil);
6475 p->start = Fcopy_marker (w->start, Qnil);
6476 p->start_at_line_beg = w->start_at_line_beg;
6478 tem = XBUFFER (w->buffer)->mark;
6479 p->mark = Fcopy_marker (tem, Qnil);
6481 else
6483 p->pointm = Qnil;
6484 p->start = Qnil;
6485 p->mark = Qnil;
6486 p->start_at_line_beg = Qnil;
6489 if (NILP (w->parent))
6490 p->parent = Qnil;
6491 else
6492 p->parent = XWINDOW (w->parent)->temslot;
6494 if (NILP (w->prev))
6495 p->prev = Qnil;
6496 else
6497 p->prev = XWINDOW (w->prev)->temslot;
6499 if (!NILP (w->vchild))
6500 i = save_window_save (w->vchild, vector, i);
6501 if (!NILP (w->hchild))
6502 i = save_window_save (w->hchild, vector, i);
6505 return i;
6508 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6509 Scurrent_window_configuration, 0, 1, 0,
6510 doc: /* Return an object representing the current window configuration of FRAME.
6511 If FRAME is nil or omitted, use the selected frame.
6512 This describes the number of windows, their sizes and current buffers,
6513 and for each displayed buffer, where display starts, and the positions of
6514 point and mark. An exception is made for point in the current buffer:
6515 its value is -not- saved.
6516 This also records the currently selected frame, and FRAME's focus
6517 redirection (see `redirect-frame-focus'). */)
6518 (frame)
6519 Lisp_Object frame;
6521 register Lisp_Object tem;
6522 register int n_windows;
6523 register struct save_window_data *data;
6524 register int i;
6525 FRAME_PTR f;
6527 if (NILP (frame))
6528 frame = selected_frame;
6529 CHECK_LIVE_FRAME (frame);
6530 f = XFRAME (frame);
6532 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6533 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6534 PVEC_WINDOW_CONFIGURATION);
6536 data->frame_cols = FRAME_COLS (f);
6537 data->frame_lines = FRAME_LINES (f);
6538 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6539 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6540 data->selected_frame = selected_frame;
6541 data->current_window = FRAME_SELECTED_WINDOW (f);
6542 XSETBUFFER (data->current_buffer, current_buffer);
6543 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6544 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6545 data->root_window = FRAME_ROOT_WINDOW (f);
6546 data->focus_frame = FRAME_FOCUS_FRAME (f);
6547 tem = Fmake_vector (make_number (n_windows), Qnil);
6548 data->saved_windows = tem;
6549 for (i = 0; i < n_windows; i++)
6550 XVECTOR (tem)->contents[i]
6551 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6552 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6553 XSETWINDOW_CONFIGURATION (tem, data);
6554 return (tem);
6557 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6558 0, UNEVALLED, 0,
6559 doc: /* Execute BODY, preserving window sizes and contents.
6560 Return the value of the last form in BODY.
6561 Restore which buffer appears in which window, where display starts,
6562 and the value of point and mark for each window.
6563 Also restore the choice of selected window.
6564 Also restore which buffer is current.
6565 Does not restore the value of point in current buffer.
6566 usage: (save-window-excursion BODY...) */)
6567 (args)
6568 Lisp_Object args;
6570 register Lisp_Object val;
6571 register int count = SPECPDL_INDEX ();
6573 record_unwind_protect (Fset_window_configuration,
6574 Fcurrent_window_configuration (Qnil));
6575 val = Fprogn (args);
6576 return unbind_to (count, val);
6581 /***********************************************************************
6582 Window Split Tree
6583 ***********************************************************************/
6585 static Lisp_Object
6586 window_tree (w)
6587 struct window *w;
6589 Lisp_Object tail = Qnil;
6590 Lisp_Object result = Qnil;
6592 while (w)
6594 Lisp_Object wn;
6596 XSETWINDOW (wn, w);
6597 if (!NILP (w->hchild))
6598 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6599 window_tree (XWINDOW (w->hchild))));
6600 else if (!NILP (w->vchild))
6601 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6602 window_tree (XWINDOW (w->vchild))));
6604 if (NILP (result))
6606 result = tail = Fcons (wn, Qnil);
6608 else
6610 XSETCDR (tail, Fcons (wn, Qnil));
6611 tail = XCDR (tail);
6614 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6617 return result;
6622 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6623 0, 1, 0,
6624 doc: /* Return the window tree for frame FRAME.
6626 The return value is a list of the form (ROOT MINI), where ROOT
6627 represents the window tree of the frame's root window, and MINI
6628 is the frame's minibuffer window.
6630 If the root window is not split, ROOT is the root window itself.
6631 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6632 horizontal split, and t for a vertical split, EDGES gives the combined
6633 size and position of the subwindows in the split, and the rest of the
6634 elements are the subwindows in the split. Each of the subwindows may
6635 again be a window or a list representing a window split, and so on.
6636 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6638 If FRAME is nil or omitted, return information on the currently
6639 selected frame. */)
6640 (frame)
6641 Lisp_Object frame;
6643 FRAME_PTR f;
6645 if (NILP (frame))
6646 frame = selected_frame;
6648 CHECK_FRAME (frame);
6649 f = XFRAME (frame);
6651 if (!FRAME_LIVE_P (f))
6652 return Qnil;
6654 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6658 /***********************************************************************
6659 Marginal Areas
6660 ***********************************************************************/
6662 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6663 2, 3, 0,
6664 doc: /* Set width of marginal areas of window WINDOW.
6665 If WINDOW is nil, set margins of the currently selected window.
6666 Second arg LEFT-WIDTH specifies the number of character cells to
6667 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6668 does the same for the right marginal area. A nil width parameter
6669 means no margin. */)
6670 (window, left_width, right_width)
6671 Lisp_Object window, left_width, right_width;
6673 struct window *w = decode_window (window);
6675 /* Translate negative or zero widths to nil.
6676 Margins that are too wide have to be checked elsewhere. */
6678 if (!NILP (left_width))
6680 CHECK_NUMBER (left_width);
6681 if (XINT (left_width) <= 0)
6682 left_width = Qnil;
6685 if (!NILP (right_width))
6687 CHECK_NUMBER (right_width);
6688 if (XINT (right_width) <= 0)
6689 right_width = Qnil;
6692 if (!EQ (w->left_margin_cols, left_width)
6693 || !EQ (w->right_margin_cols, right_width))
6695 w->left_margin_cols = left_width;
6696 w->right_margin_cols = right_width;
6698 adjust_window_margins (w);
6700 ++windows_or_buffers_changed;
6701 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6704 return Qnil;
6708 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6709 0, 1, 0,
6710 doc: /* Get width of marginal areas of window WINDOW.
6711 If WINDOW is omitted or nil, use the currently selected window.
6712 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6713 If a marginal area does not exist, its width will be returned
6714 as nil. */)
6715 (window)
6716 Lisp_Object window;
6718 struct window *w = decode_window (window);
6719 return Fcons (w->left_margin_cols, w->right_margin_cols);
6724 /***********************************************************************
6725 Fringes
6726 ***********************************************************************/
6728 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6729 2, 4, 0,
6730 doc: /* Set the fringe widths of window WINDOW.
6731 If WINDOW is nil, set the fringe widths of the currently selected
6732 window.
6733 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6734 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6735 fringe width. If a fringe width arg is nil, that means to use the
6736 frame's default fringe width. Default fringe widths can be set with
6737 the command `set-fringe-style'.
6738 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6739 outside of the display margins. By default, fringes are drawn between
6740 display marginal areas and the text area. */)
6741 (window, left_width, right_width, outside_margins)
6742 Lisp_Object window, left_width, right_width, outside_margins;
6744 struct window *w = decode_window (window);
6746 if (!NILP (left_width))
6747 CHECK_NATNUM (left_width);
6748 if (!NILP (right_width))
6749 CHECK_NATNUM (right_width);
6751 /* Do nothing on a tty. */
6752 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6753 && (!EQ (w->left_fringe_width, left_width)
6754 || !EQ (w->right_fringe_width, right_width)
6755 || !EQ (w->fringes_outside_margins, outside_margins)))
6757 w->left_fringe_width = left_width;
6758 w->right_fringe_width = right_width;
6759 w->fringes_outside_margins = outside_margins;
6761 adjust_window_margins (w);
6763 clear_glyph_matrix (w->current_matrix);
6764 w->window_end_valid = Qnil;
6766 ++windows_or_buffers_changed;
6767 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6770 return Qnil;
6774 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6775 0, 1, 0,
6776 doc: /* Get width of fringes of window WINDOW.
6777 If WINDOW is omitted or nil, use the currently selected window.
6778 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6779 (window)
6780 Lisp_Object window;
6782 struct window *w = decode_window (window);
6784 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6785 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6786 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6787 ? Qt : Qnil), Qnil)));
6792 /***********************************************************************
6793 Scroll bars
6794 ***********************************************************************/
6796 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6797 2, 4, 0,
6798 doc: /* Set width and type of scroll bars of window WINDOW.
6799 If window is nil, set scroll bars of the currently selected window.
6800 Second parameter WIDTH specifies the pixel width for the scroll bar;
6801 this is automatically adjusted to a multiple of the frame column width.
6802 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6803 bar: left, right, or nil.
6804 If WIDTH is nil, use the frame's scroll-bar width.
6805 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6806 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6807 (window, width, vertical_type, horizontal_type)
6808 Lisp_Object window, width, vertical_type, horizontal_type;
6810 struct window *w = decode_window (window);
6812 if (!NILP (width))
6814 CHECK_NATNUM (width);
6816 if (XINT (width) == 0)
6817 vertical_type = Qnil;
6820 if (!(NILP (vertical_type)
6821 || EQ (vertical_type, Qleft)
6822 || EQ (vertical_type, Qright)
6823 || EQ (vertical_type, Qt)))
6824 error ("Invalid type of vertical scroll bar");
6826 if (!EQ (w->scroll_bar_width, width)
6827 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6829 w->scroll_bar_width = width;
6830 w->vertical_scroll_bar_type = vertical_type;
6832 adjust_window_margins (w);
6834 clear_glyph_matrix (w->current_matrix);
6835 w->window_end_valid = Qnil;
6837 ++windows_or_buffers_changed;
6838 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6841 return Qnil;
6845 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6846 0, 1, 0,
6847 doc: /* Get width and type of scroll bars of window WINDOW.
6848 If WINDOW is omitted or nil, use the currently selected window.
6849 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6850 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6851 value. */)
6852 (window)
6853 Lisp_Object window;
6855 struct window *w = decode_window (window);
6856 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6857 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6858 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6859 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6860 Fcons (w->vertical_scroll_bar_type,
6861 Fcons (Qnil, Qnil))));
6866 /***********************************************************************
6867 Smooth scrolling
6868 ***********************************************************************/
6870 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6871 doc: /* Return the amount by which WINDOW is scrolled vertically.
6872 Use the selected window if WINDOW is nil or omitted.
6873 Normally, value is a multiple of the canonical character height of WINDOW;
6874 optional second arg PIXELS-P means value is measured in pixels. */)
6875 (window, pixels_p)
6876 Lisp_Object window, pixels_p;
6878 Lisp_Object result;
6879 struct frame *f;
6880 struct window *w;
6882 if (NILP (window))
6883 window = selected_window;
6884 else
6885 CHECK_WINDOW (window);
6886 w = XWINDOW (window);
6887 f = XFRAME (w->frame);
6889 if (FRAME_WINDOW_P (f))
6890 result = (NILP (pixels_p)
6891 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6892 : make_number (-w->vscroll));
6893 else
6894 result = make_number (0);
6895 return result;
6899 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6900 2, 3, 0,
6901 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6902 WINDOW nil means use the selected window. Normally, VSCROLL is a
6903 non-negative multiple of the canonical character height of WINDOW;
6904 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6905 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6906 corresponds to an integral number of pixels. The return value is the
6907 result of this rounding.
6908 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6909 (window, vscroll, pixels_p)
6910 Lisp_Object window, vscroll, pixels_p;
6912 struct window *w;
6913 struct frame *f;
6915 if (NILP (window))
6916 window = selected_window;
6917 else
6918 CHECK_WINDOW (window);
6919 CHECK_NUMBER_OR_FLOAT (vscroll);
6921 w = XWINDOW (window);
6922 f = XFRAME (w->frame);
6924 if (FRAME_WINDOW_P (f))
6926 int old_dy = w->vscroll;
6928 w->vscroll = - (NILP (pixels_p)
6929 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6930 : XFLOATINT (vscroll));
6931 w->vscroll = min (w->vscroll, 0);
6933 if (w->vscroll != old_dy)
6935 /* Adjust glyph matrix of the frame if the virtual display
6936 area becomes larger than before. */
6937 if (w->vscroll < 0 && w->vscroll < old_dy)
6938 adjust_glyphs (f);
6940 /* Prevent redisplay shortcuts. */
6941 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6945 return Fwindow_vscroll (window, pixels_p);
6949 /* Call FN for all leaf windows on frame F. FN is called with the
6950 first argument being a pointer to the leaf window, and with
6951 additional argument USER_DATA. Stops when FN returns 0. */
6953 void
6954 foreach_window (f, fn, user_data)
6955 struct frame *f;
6956 int (* fn) P_ ((struct window *, void *));
6957 void *user_data;
6959 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6960 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6961 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6965 /* Helper function for foreach_window. Call FN for all leaf windows
6966 reachable from W. FN is called with the first argument being a
6967 pointer to the leaf window, and with additional argument USER_DATA.
6968 Stop when FN returns 0. Value is 0 if stopped by FN. */
6970 static int
6971 foreach_window_1 (w, fn, user_data)
6972 struct window *w;
6973 int (* fn) P_ ((struct window *, void *));
6974 void *user_data;
6976 int cont;
6978 for (cont = 1; w && cont;)
6980 if (!NILP (w->hchild))
6981 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6982 else if (!NILP (w->vchild))
6983 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6984 else
6985 cont = fn (w, user_data);
6987 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6990 return cont;
6994 /* Freeze or unfreeze the window start of W unless it is a
6995 mini-window or the selected window. FREEZE_P non-null means freeze
6996 the window start. */
6998 static int
6999 freeze_window_start (w, freeze_p)
7000 struct window *w;
7001 void *freeze_p;
7003 if (MINI_WINDOW_P (w)
7004 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
7005 && (w == XWINDOW (selected_window)
7006 || (MINI_WINDOW_P (XWINDOW (selected_window))
7007 && ! NILP (Vminibuf_scroll_window)
7008 && w == XWINDOW (Vminibuf_scroll_window)))))
7009 freeze_p = NULL;
7011 w->frozen_window_start_p = freeze_p != NULL;
7012 return 1;
7016 /* Freeze or unfreeze the window starts of all leaf windows on frame
7017 F, except the selected window and a mini-window. FREEZE_P non-zero
7018 means freeze the window start. */
7020 void
7021 freeze_window_starts (f, freeze_p)
7022 struct frame *f;
7023 int freeze_p;
7025 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7029 /***********************************************************************
7030 Initialization
7031 ***********************************************************************/
7033 /* Return 1 if window configurations C1 and C2
7034 describe the same state of affairs. This is used by Fequal. */
7037 compare_window_configurations (c1, c2, ignore_positions)
7038 Lisp_Object c1, c2;
7039 int ignore_positions;
7041 register struct save_window_data *d1, *d2;
7042 struct Lisp_Vector *sw1, *sw2;
7043 int i;
7045 CHECK_WINDOW_CONFIGURATION (c1);
7046 CHECK_WINDOW_CONFIGURATION (c2);
7048 d1 = (struct save_window_data *) XVECTOR (c1);
7049 d2 = (struct save_window_data *) XVECTOR (c2);
7050 sw1 = XVECTOR (d1->saved_windows);
7051 sw2 = XVECTOR (d2->saved_windows);
7053 if (d1->frame_cols != d2->frame_cols)
7054 return 0;
7055 if (d1->frame_lines != d2->frame_lines)
7056 return 0;
7057 if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines)
7058 return 0;
7059 if (! EQ (d1->selected_frame, d2->selected_frame))
7060 return 0;
7061 /* Don't compare the current_window field directly.
7062 Instead see w1_is_current and w2_is_current, below. */
7063 if (! EQ (d1->current_buffer, d2->current_buffer))
7064 return 0;
7065 if (! ignore_positions)
7067 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
7068 return 0;
7069 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
7070 return 0;
7072 /* Don't compare the root_window field.
7073 We don't require the two configurations
7074 to use the same window object,
7075 and the two root windows must be equivalent
7076 if everything else compares equal. */
7077 if (! EQ (d1->focus_frame, d2->focus_frame))
7078 return 0;
7080 /* Verify that the two confis have the same number of windows. */
7081 if (sw1->size != sw2->size)
7082 return 0;
7084 for (i = 0; i < sw1->size; i++)
7086 struct saved_window *p1, *p2;
7087 int w1_is_current, w2_is_current;
7089 p1 = SAVED_WINDOW_N (sw1, i);
7090 p2 = SAVED_WINDOW_N (sw2, i);
7092 /* Verify that the current windows in the two
7093 configurations correspond to each other. */
7094 w1_is_current = EQ (d1->current_window, p1->window);
7095 w2_is_current = EQ (d2->current_window, p2->window);
7097 if (w1_is_current != w2_is_current)
7098 return 0;
7100 /* Verify that the corresponding windows do match. */
7101 if (! EQ (p1->buffer, p2->buffer))
7102 return 0;
7103 if (! EQ (p1->left_col, p2->left_col))
7104 return 0;
7105 if (! EQ (p1->top_line, p2->top_line))
7106 return 0;
7107 if (! EQ (p1->total_cols, p2->total_cols))
7108 return 0;
7109 if (! EQ (p1->total_lines, p2->total_lines))
7110 return 0;
7111 if (! EQ (p1->display_table, p2->display_table))
7112 return 0;
7113 if (! EQ (p1->parent, p2->parent))
7114 return 0;
7115 if (! EQ (p1->prev, p2->prev))
7116 return 0;
7117 if (! ignore_positions)
7119 if (! EQ (p1->hscroll, p2->hscroll))
7120 return 0;
7121 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7122 return 0;
7123 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7124 return 0;
7125 if (NILP (Fequal (p1->start, p2->start)))
7126 return 0;
7127 if (NILP (Fequal (p1->pointm, p2->pointm)))
7128 return 0;
7129 if (NILP (Fequal (p1->mark, p2->mark)))
7130 return 0;
7132 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7133 return 0;
7134 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7135 return 0;
7136 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7137 return 0;
7138 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7139 return 0;
7140 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7141 return 0;
7142 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7143 return 0;
7144 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7145 return 0;
7148 return 1;
7151 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7152 Scompare_window_configurations, 2, 2, 0,
7153 doc: /* Compare two window configurations as regards the structure of windows.
7154 This function ignores details such as the values of point and mark
7155 and scrolling positions. */)
7156 (x, y)
7157 Lisp_Object x, y;
7159 if (compare_window_configurations (x, y, 1))
7160 return Qt;
7161 return Qnil;
7164 void
7165 init_window_once ()
7167 struct frame *f = make_initial_frame ();
7168 XSETFRAME (selected_frame, f);
7169 Vterminal_frame = selected_frame;
7170 minibuf_window = f->minibuffer_window;
7171 selected_window = f->selected_window;
7172 last_nonminibuf_frame = f;
7174 window_initialized = 1;
7177 void
7178 init_window ()
7180 Vwindow_list = Qnil;
7183 void
7184 syms_of_window ()
7186 Qscroll_up = intern_c_string ("scroll-up");
7187 staticpro (&Qscroll_up);
7189 Qscroll_down = intern_c_string ("scroll-down");
7190 staticpro (&Qscroll_down);
7192 Qwindow_size_fixed = intern_c_string ("window-size-fixed");
7193 staticpro (&Qwindow_size_fixed);
7194 Fset (Qwindow_size_fixed, Qnil);
7196 staticpro (&Qwindow_configuration_change_hook);
7197 Qwindow_configuration_change_hook
7198 = intern_c_string ("window-configuration-change-hook");
7200 Qwindowp = intern_c_string ("windowp");
7201 staticpro (&Qwindowp);
7203 Qwindow_configuration_p = intern_c_string ("window-configuration-p");
7204 staticpro (&Qwindow_configuration_p);
7206 Qwindow_live_p = intern_c_string ("window-live-p");
7207 staticpro (&Qwindow_live_p);
7209 Qdisplay_buffer = intern_c_string ("display-buffer");
7210 staticpro (&Qdisplay_buffer);
7212 Qtemp_buffer_show_hook = intern_c_string ("temp-buffer-show-hook");
7213 staticpro (&Qtemp_buffer_show_hook);
7215 staticpro (&Vwindow_list);
7217 minibuf_selected_window = Qnil;
7218 staticpro (&minibuf_selected_window);
7220 window_scroll_pixel_based_preserve_x = -1;
7221 window_scroll_pixel_based_preserve_y = -1;
7222 window_scroll_preserve_hpos = -1;
7223 window_scroll_preserve_vpos = -1;
7225 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7226 doc: /* Non-nil means call as function to display a help buffer.
7227 The function is called with one argument, the buffer to be displayed.
7228 Used by `with-output-to-temp-buffer'.
7229 If this function is used, then it must do the entire job of showing
7230 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7231 Vtemp_buffer_show_function = Qnil;
7233 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7234 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7235 Vminibuf_scroll_window = Qnil;
7237 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7238 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7239 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7240 is displayed in the `mode-line' face. */);
7241 mode_line_in_non_selected_windows = 1;
7243 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7244 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7245 Vother_window_scroll_buffer = Qnil;
7247 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7248 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7249 auto_window_vscroll_p = 1;
7251 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7252 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7253 next_screen_context_lines = 2;
7255 DEFVAR_INT ("window-min-height", &window_min_height,
7256 doc: /* Allow deleting windows less than this tall.
7257 The value is measured in line units. If a window wants a modeline it
7258 is counted as one line.
7260 Emacs honors settings of this variable when enlarging or shrinking
7261 windows vertically. A value less than 1 is invalid. */);
7262 window_min_height = 4;
7264 DEFVAR_INT ("window-min-width", &window_min_width,
7265 doc: /* Allow deleting windows less than this wide.
7266 The value is measured in characters and includes any fringes or
7267 the scrollbar.
7269 Emacs honors settings of this variable when enlarging or shrinking
7270 windows horizontally. A value less than 2 is invalid. */);
7271 window_min_width = 10;
7273 DEFVAR_LISP ("scroll-preserve-screen-position",
7274 &Vscroll_preserve_screen_position,
7275 doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
7276 A value of nil means point does not keep its screen position except
7277 at the scroll margin or window boundary respectively.
7278 A value of t means point keeps its screen position if the scroll
7279 command moved it vertically out of the window, e.g. when scrolling
7280 by full screens.
7281 Any other value means point always keeps its screen position. */);
7282 Vscroll_preserve_screen_position = Qnil;
7284 DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type,
7285 doc: /* Type of marker to use for `window-point'. */);
7286 Vwindow_point_insertion_type = Qnil;
7288 DEFVAR_LISP ("window-configuration-change-hook",
7289 &Vwindow_configuration_change_hook,
7290 doc: /* Functions to call when window configuration changes.
7291 The buffer-local part is run once per window, with the relevant window
7292 selected; while the global part is run only once for the modified frame,
7293 with the relevant frame selected. */);
7294 Vwindow_configuration_change_hook = Qnil;
7296 DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay,
7297 doc: /* If non-nil, then the `recenter' command with a nil argument
7298 the entire frame to be redrawn; the special value `tty' causes the
7299 frame to be redrawn only if it is a tty frame. */);
7300 Vrecenter_redisplay = Qtty;
7303 defsubr (&Sselected_window);
7304 defsubr (&Sminibuffer_window);
7305 defsubr (&Swindow_minibuffer_p);
7306 defsubr (&Swindowp);
7307 defsubr (&Swindow_live_p);
7308 defsubr (&Spos_visible_in_window_p);
7309 defsubr (&Swindow_line_height);
7310 defsubr (&Swindow_buffer);
7311 defsubr (&Swindow_height);
7312 defsubr (&Swindow_width);
7313 defsubr (&Swindow_full_width_p);
7314 defsubr (&Swindow_hscroll);
7315 defsubr (&Sset_window_hscroll);
7316 defsubr (&Swindow_redisplay_end_trigger);
7317 defsubr (&Sset_window_redisplay_end_trigger);
7318 defsubr (&Swindow_edges);
7319 defsubr (&Swindow_pixel_edges);
7320 defsubr (&Swindow_inside_edges);
7321 defsubr (&Swindow_inside_pixel_edges);
7322 defsubr (&Scoordinates_in_window_p);
7323 defsubr (&Swindow_at);
7324 defsubr (&Swindow_point);
7325 defsubr (&Swindow_start);
7326 defsubr (&Swindow_end);
7327 defsubr (&Sset_window_point);
7328 defsubr (&Sset_window_start);
7329 defsubr (&Swindow_dedicated_p);
7330 defsubr (&Sset_window_dedicated_p);
7331 defsubr (&Swindow_display_table);
7332 defsubr (&Sset_window_display_table);
7333 defsubr (&Snext_window);
7334 defsubr (&Sprevious_window);
7335 defsubr (&Sother_window);
7336 defsubr (&Sget_lru_window);
7337 defsubr (&Sget_largest_window);
7338 defsubr (&Sget_buffer_window);
7339 defsubr (&Sdelete_other_windows);
7340 defsubr (&Sdelete_windows_on);
7341 defsubr (&Sreplace_buffer_in_windows);
7342 defsubr (&Sdelete_window);
7343 defsubr (&Sset_window_buffer);
7344 defsubr (&Sselect_window);
7345 defsubr (&Sforce_window_update);
7346 defsubr (&Ssplit_window);
7347 defsubr (&Senlarge_window);
7348 defsubr (&Sshrink_window);
7349 defsubr (&Sadjust_window_trailing_edge);
7350 defsubr (&Sscroll_up);
7351 defsubr (&Sscroll_down);
7352 defsubr (&Sscroll_left);
7353 defsubr (&Sscroll_right);
7354 defsubr (&Sother_window_for_scrolling);
7355 defsubr (&Sscroll_other_window);
7356 defsubr (&Sminibuffer_selected_window);
7357 defsubr (&Srecenter);
7358 defsubr (&Swindow_text_height);
7359 defsubr (&Smove_to_window_line);
7360 defsubr (&Swindow_configuration_p);
7361 defsubr (&Swindow_configuration_frame);
7362 defsubr (&Sset_window_configuration);
7363 defsubr (&Scurrent_window_configuration);
7364 defsubr (&Ssave_window_excursion);
7365 defsubr (&Swindow_tree);
7366 defsubr (&Sset_window_margins);
7367 defsubr (&Swindow_margins);
7368 defsubr (&Sset_window_fringes);
7369 defsubr (&Swindow_fringes);
7370 defsubr (&Sset_window_scroll_bars);
7371 defsubr (&Swindow_scroll_bars);
7372 defsubr (&Swindow_vscroll);
7373 defsubr (&Sset_window_vscroll);
7374 defsubr (&Scompare_window_configurations);
7375 defsubr (&Swindow_list);
7376 defsubr (&Swindow_parameters);
7377 defsubr (&Swindow_parameter);
7378 defsubr (&Sset_window_parameter);
7382 void
7383 keys_of_window ()
7385 initial_define_key (control_x_map, '1', "delete-other-windows");
7386 initial_define_key (control_x_map, '2', "split-window");
7387 initial_define_key (control_x_map, '0', "delete-window");
7388 initial_define_key (control_x_map, 'o', "other-window");
7389 initial_define_key (control_x_map, '^', "enlarge-window");
7390 initial_define_key (control_x_map, '<', "scroll-left");
7391 initial_define_key (control_x_map, '>', "scroll-right");
7393 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7394 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7395 initial_define_key (meta_map, 'v', "scroll-down");
7397 initial_define_key (global_map, Ctl('L'), "recenter");
7398 initial_define_key (meta_map, 'r', "move-to-window-line");
7401 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7402 (do not change this comment) */