* lisp/emacs-lisp/unsafep.el (unsafep): Handle backquoted forms.
[emacs.git] / src / window.c
blobb01714360886ff9c99adba401bdfd16b0fc60e32
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
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
54 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
55 Lisp_Object Qdisplay_buffer;
56 Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
57 Lisp_Object Qwindow_size_fixed;
59 static int displayed_window_lines (struct window *);
60 static struct window *decode_window (Lisp_Object);
61 static int count_windows (struct window *);
62 static int get_leaf_windows (struct window *, struct window **, int);
63 static void window_scroll (Lisp_Object, int, int, int);
64 static void window_scroll_pixel_based (Lisp_Object, int, int, int);
65 static void window_scroll_line_based (Lisp_Object, int, int, int);
66 static int window_min_size_1 (struct window *, int, int);
67 static int window_min_size_2 (struct window *, int, int);
68 static int window_min_size (struct window *, int, int, int, int *);
69 static void size_window (Lisp_Object, int, int, int, int, int);
70 static int freeze_window_start (struct window *, void *);
71 static int window_fixed_size_p (struct window *, int, int);
72 static void enlarge_window (Lisp_Object, int, int);
73 static Lisp_Object window_list (void);
74 static int add_window_to_list (struct window *, void *);
75 static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
76 Lisp_Object);
77 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
78 Lisp_Object, int);
79 static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
80 Lisp_Object *);
81 static void foreach_window (struct frame *,
82 int (* fn) (struct window *, void *),
83 void *);
84 static int foreach_window_1 (struct window *,
85 int (* fn) (struct window *, void *),
86 void *);
87 static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
89 /* This is the window in which the terminal's cursor should
90 be left when nothing is being done with it. This must
91 always be a leaf window, and its buffer is selected by
92 the top level editing loop at the end of each command.
94 This value is always the same as
95 FRAME_SELECTED_WINDOW (selected_frame). */
97 Lisp_Object selected_window;
99 /* A list of all windows for use by next_window and Fwindow_list.
100 Functions creating or deleting windows should invalidate this cache
101 by setting it to nil. */
103 Lisp_Object Vwindow_list;
105 /* The mini-buffer window of the selected frame.
106 Note that you cannot test for mini-bufferness of an arbitrary window
107 by comparing against this; but you can test for mini-bufferness of
108 the selected window. */
110 Lisp_Object minibuf_window;
112 /* Non-nil means it is the window whose mode line should be
113 shown as the selected window when the minibuffer is selected. */
115 Lisp_Object minibuf_selected_window;
117 /* Non-nil means it is the window for C-M-v to scroll
118 when the mini-buffer is selected. */
120 Lisp_Object Vminibuf_scroll_window;
122 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
124 Lisp_Object Vother_window_scroll_buffer;
126 /* Non-nil means it's function to call to display temp buffers. */
128 Lisp_Object Vtemp_buffer_show_function;
130 /* Non-zero means line and page scrolling on tall lines (with images)
131 does partial scrolling by modifying window-vscroll. */
133 int auto_window_vscroll_p;
135 /* Non-zero means to use mode-line-inactive face in all windows but the
136 selected-window and the minibuffer-scroll-window when the
137 minibuffer is active. */
138 int mode_line_in_non_selected_windows;
140 /* If a window gets smaller than either of these, it is removed. */
142 EMACS_INT window_min_height;
143 EMACS_INT window_min_width;
145 /* Hook run at end of temp_output_buffer_show. */
147 Lisp_Object Qtemp_buffer_show_hook;
149 /* Number of lines of continuity in scrolling by screenfuls. */
151 EMACS_INT next_screen_context_lines;
153 /* Incremented for each window created. */
155 static int sequence_number;
157 /* Nonzero after init_window_once has finished. */
159 static int window_initialized;
161 /* Hook to run when window config changes. */
163 static Lisp_Object Qwindow_configuration_change_hook;
164 static Lisp_Object Vwindow_configuration_change_hook;
166 /* Non-nil means scroll commands try to put point
167 at the same screen height as previously. */
169 Lisp_Object Vscroll_preserve_screen_position;
171 /* Non-nil means that text is inserted before window's markers. */
173 Lisp_Object Vwindow_point_insertion_type;
175 /* Incremented by 1 whenever a window is deleted. */
177 int window_deletion_count;
179 /* Used by the function window_scroll_pixel_based */
181 static int window_scroll_pixel_based_preserve_x;
182 static int window_scroll_pixel_based_preserve_y;
184 /* Same for window_scroll_line_based. */
186 static int window_scroll_preserve_hpos;
187 static int window_scroll_preserve_vpos;
189 #if 0 /* This isn't used anywhere. */
190 /* Nonzero means we can split a frame even if it is "unsplittable". */
191 static int inhibit_frame_unsplittable;
192 #endif /* 0 */
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;
201 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
202 doc: /* Return t if OBJECT is a window. */)
203 (Lisp_Object object)
205 return WINDOWP (object) ? Qt : Qnil;
208 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
209 doc: /* Return t if OBJECT is a window which is currently visible. */)
210 (Lisp_Object object)
212 return WINDOW_LIVE_P (object) ? Qt : Qnil;
215 Lisp_Object
216 make_window (void)
218 Lisp_Object val;
219 register struct window *p;
221 p = allocate_window ();
222 ++sequence_number;
223 XSETFASTINT (p->sequence_number, sequence_number);
224 XSETFASTINT (p->left_col, 0);
225 XSETFASTINT (p->top_line, 0);
226 XSETFASTINT (p->total_lines, 0);
227 XSETFASTINT (p->total_cols, 0);
228 XSETFASTINT (p->hscroll, 0);
229 XSETFASTINT (p->min_hscroll, 0);
230 p->orig_top_line = p->orig_total_lines = Qnil;
231 p->start = Fmake_marker ();
232 p->pointm = Fmake_marker ();
233 XSETFASTINT (p->use_time, 0);
234 p->frame = Qnil;
235 p->display_table = Qnil;
236 p->dedicated = Qnil;
237 p->window_parameters = Qnil;
238 p->pseudo_window_p = 0;
239 memset (&p->cursor, 0, sizeof (p->cursor));
240 memset (&p->last_cursor, 0, sizeof (p->last_cursor));
241 memset (&p->phys_cursor, 0, sizeof (p->phys_cursor));
242 p->desired_matrix = p->current_matrix = 0;
243 p->nrows_scale_factor = p->ncols_scale_factor = 1;
244 p->phys_cursor_type = -1;
245 p->phys_cursor_width = -1;
246 p->must_be_updated_p = 0;
247 XSETFASTINT (p->window_end_vpos, 0);
248 XSETFASTINT (p->window_end_pos, 0);
249 p->window_end_valid = Qnil;
250 p->vscroll = 0;
251 XSETWINDOW (val, p);
252 XSETFASTINT (p->last_point, 0);
253 p->frozen_window_start_p = 0;
254 p->last_cursor_off_p = p->cursor_off_p = 0;
255 p->left_margin_cols = Qnil;
256 p->right_margin_cols = Qnil;
257 p->left_fringe_width = Qnil;
258 p->right_fringe_width = Qnil;
259 p->fringes_outside_margins = Qnil;
260 p->scroll_bar_width = Qnil;
261 p->vertical_scroll_bar_type = Qt;
262 p->resize_proportionally = Qnil;
264 Vwindow_list = Qnil;
265 return val;
268 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
269 doc: /* Return the window that the cursor now appears in and commands apply to. */)
270 (void)
272 return selected_window;
275 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
276 doc: /* Return the window used now for minibuffers.
277 If the optional argument FRAME is specified, return the minibuffer window
278 used by that frame. */)
279 (Lisp_Object frame)
281 if (NILP (frame))
282 frame = selected_frame;
283 CHECK_LIVE_FRAME (frame);
284 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
287 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
288 doc: /* Return non-nil if WINDOW is a minibuffer window.
289 WINDOW defaults to the selected window. */)
290 (Lisp_Object window)
292 struct window *w = decode_window (window);
293 return MINI_WINDOW_P (w) ? Qt : Qnil;
297 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
298 Spos_visible_in_window_p, 0, 3, 0,
299 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
300 Return nil if that position is scrolled vertically out of view.
301 If a character is only partially visible, nil is returned, unless the
302 optional argument PARTIALLY is non-nil.
303 If POS is only out of view because of horizontal scrolling, return non-nil.
304 If POS is t, it specifies the position of the last visible glyph in WINDOW.
305 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
307 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
308 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
309 where X and Y are the pixel coordinates relative to the top left corner
310 of the window. The remaining elements are omitted if the character after
311 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
312 off-window at the top and bottom of the row, ROWH is the height of the
313 display row, and VPOS is the row number (0-based) containing POS. */)
314 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
316 register struct window *w;
317 register EMACS_INT posint;
318 register struct buffer *buf;
319 struct text_pos top;
320 Lisp_Object in_window = Qnil;
321 int rtop, rbot, rowh, vpos, fully_p = 1;
322 int x, y;
324 w = decode_window (window);
325 buf = XBUFFER (w->buffer);
326 SET_TEXT_POS_FROM_MARKER (top, w->start);
328 if (EQ (pos, Qt))
329 posint = -1;
330 else if (!NILP (pos))
332 CHECK_NUMBER_COERCE_MARKER (pos);
333 posint = XINT (pos);
335 else if (w == XWINDOW (selected_window))
336 posint = PT;
337 else
338 posint = XMARKER (w->pointm)->charpos;
340 /* If position is above window start or outside buffer boundaries,
341 or if window start is out of range, position is not visible. */
342 if ((EQ (pos, Qt)
343 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
344 && CHARPOS (top) >= BUF_BEGV (buf)
345 && CHARPOS (top) <= BUF_ZV (buf)
346 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
347 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
348 in_window = Qt;
350 if (!NILP (in_window) && !NILP (partially))
352 Lisp_Object part = Qnil;
353 if (!fully_p)
354 part = list4 (make_number (rtop), make_number (rbot),
355 make_number (rowh), make_number (vpos));
356 in_window = Fcons (make_number (x),
357 Fcons (make_number (y), part));
360 return in_window;
363 DEFUN ("window-line-height", Fwindow_line_height,
364 Swindow_line_height, 0, 2, 0,
365 doc: /* Return height in pixels of text line LINE in window WINDOW.
366 If WINDOW is nil or omitted, use selected window.
368 Return height of current line if LINE is omitted or nil. Return height of
369 header or mode line if LINE is `header-line' and `mode-line'.
370 Otherwise, LINE is a text line number starting from 0. A negative number
371 counts from the end of the window.
373 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
374 in pixels of the visible part of the line, VPOS and YPOS are the
375 vertical position in lines and pixels of the line, relative to the top
376 of the first text line, and OFFBOT is the number of off-window pixels at
377 the bottom of the text line. If there are off-window pixels at the top
378 of the (first) text line, YPOS is negative.
380 Return nil if window display is not up-to-date. In that case, use
381 `pos-visible-in-window-p' to obtain the information. */)
382 (Lisp_Object line, Lisp_Object window)
384 register struct window *w;
385 register struct buffer *b;
386 struct glyph_row *row, *end_row;
387 int max_y, crop, i, n;
389 w = decode_window (window);
391 if (noninteractive
392 || w->pseudo_window_p)
393 return Qnil;
395 CHECK_BUFFER (w->buffer);
396 b = XBUFFER (w->buffer);
398 /* Fail if current matrix is not up-to-date. */
399 if (NILP (w->window_end_valid)
400 || current_buffer->clip_changed
401 || current_buffer->prevent_redisplay_optimizations_p
402 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
403 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
404 return Qnil;
406 if (NILP (line))
408 i = w->cursor.vpos;
409 if (i < 0 || i >= w->current_matrix->nrows
410 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
411 return Qnil;
412 max_y = window_text_bottom_y (w);
413 goto found_row;
416 if (EQ (line, Qheader_line))
418 if (!WINDOW_WANTS_HEADER_LINE_P (w))
419 return Qnil;
420 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
421 if (!row->enabled_p)
422 return Qnil;
423 return list4 (make_number (row->height),
424 make_number (0), make_number (0),
425 make_number (0));
428 if (EQ (line, Qmode_line))
430 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
431 if (!row->enabled_p)
432 return Qnil;
433 return list4 (make_number (row->height),
434 make_number (0), /* not accurate */
435 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
436 + window_text_bottom_y (w)),
437 make_number (0));
440 CHECK_NUMBER (line);
441 n = XINT (line);
443 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
444 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
445 max_y = window_text_bottom_y (w);
446 i = 0;
448 while ((n < 0 || i < n)
449 && row <= end_row && row->enabled_p
450 && row->y + row->height < max_y)
451 row++, i++;
453 if (row > end_row || !row->enabled_p)
454 return Qnil;
456 if (++n < 0)
458 if (-n > i)
459 return Qnil;
460 row += n;
461 i += n;
464 found_row:
465 crop = max (0, (row->y + row->height) - max_y);
466 return list4 (make_number (row->height + min (0, row->y) - crop),
467 make_number (i),
468 make_number (row->y),
469 make_number (crop));
474 static struct window *
475 decode_window (register Lisp_Object window)
477 if (NILP (window))
478 return XWINDOW (selected_window);
480 CHECK_LIVE_WINDOW (window);
481 return XWINDOW (window);
484 static struct window *
485 decode_any_window (register Lisp_Object window)
487 if (NILP (window))
488 return XWINDOW (selected_window);
490 CHECK_WINDOW (window);
491 return XWINDOW (window);
494 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
495 doc: /* Return the buffer that WINDOW is displaying.
496 WINDOW defaults to the selected window. */)
497 (Lisp_Object window)
499 return decode_window (window)->buffer;
502 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
503 doc: /* Return the number of lines in WINDOW.
504 WINDOW defaults to the selected window.
506 The return value includes WINDOW's mode line and header line, if any.
508 Note: The function does not take into account the value of `line-spacing'
509 when calculating the number of lines in WINDOW. */)
510 (Lisp_Object window)
512 return decode_any_window (window)->total_lines;
515 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
516 doc: /* Return the number of display columns in WINDOW.
517 WINDOW defaults to the selected window.
519 Note: The return value is the number of columns available for text in
520 WINDOW. If you want to find out how many columns WINDOW takes up, use
521 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
522 (Lisp_Object window)
524 return make_number (window_box_text_cols (decode_any_window (window)));
527 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
528 doc: /* Return t if WINDOW is as wide as its frame.
529 WINDOW defaults to the selected window. */)
530 (Lisp_Object window)
532 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
535 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
536 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
537 WINDOW defaults to the selected window. */)
538 (Lisp_Object window)
540 return decode_window (window)->hscroll;
543 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
544 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
545 Return NCOL. NCOL should be zero or positive.
547 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
548 window so that the location of point moves off-window. */)
549 (Lisp_Object window, Lisp_Object ncol)
551 struct window *w = decode_window (window);
552 int hscroll;
554 CHECK_NUMBER (ncol);
555 hscroll = max (0, XINT (ncol));
557 /* Prevent redisplay shortcuts when changing the hscroll. */
558 if (XINT (w->hscroll) != hscroll)
559 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
561 w->hscroll = make_number (hscroll);
562 return ncol;
565 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
566 Swindow_redisplay_end_trigger, 0, 1, 0,
567 doc: /* Return WINDOW's redisplay end trigger value.
568 WINDOW defaults to the selected window.
569 See `set-window-redisplay-end-trigger' for more information. */)
570 (Lisp_Object window)
572 return decode_window (window)->redisplay_end_trigger;
575 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
576 Sset_window_redisplay_end_trigger, 2, 2, 0,
577 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
578 VALUE should be a buffer position (typically a marker) or nil.
579 If it is a buffer position, then if redisplay in WINDOW reaches a position
580 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
581 with two arguments: WINDOW, and the end trigger value.
582 Afterwards the end-trigger value is reset to nil. */)
583 (register Lisp_Object window, Lisp_Object value)
585 register struct window *w;
587 w = decode_window (window);
588 w->redisplay_end_trigger = value;
589 return value;
592 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
593 doc: /* Return a list of the edge coordinates of WINDOW.
594 The list has the form (LEFT TOP RIGHT BOTTOM).
595 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
596 all relative to 0, 0 at top left corner of frame.
598 RIGHT is one more than the rightmost column occupied by WINDOW.
599 BOTTOM is one more than the bottommost row occupied by WINDOW.
600 The edges include the space used by WINDOW's scroll bar, display
601 margins, fringes, header line, and/or mode line. For the edges of
602 just the text area, use `window-inside-edges'. */)
603 (Lisp_Object window)
605 register struct window *w = decode_any_window (window);
607 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
608 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
609 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
610 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
611 Qnil))));
614 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
615 doc: /* Return a list of the edge pixel coordinates of WINDOW.
616 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
617 the top left corner of the frame.
619 RIGHT is one more than the rightmost x position occupied by WINDOW.
620 BOTTOM is one more than the bottommost y position occupied by WINDOW.
621 The pixel edges include the space used by WINDOW's scroll bar, display
622 margins, fringes, header line, and/or mode line. For the pixel edges
623 of just the text area, use `window-inside-pixel-edges'. */)
624 (Lisp_Object window)
626 register struct window *w = decode_any_window (window);
628 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
629 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
630 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
631 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
632 Qnil))));
635 static void
636 calc_absolute_offset(struct window *w, int *add_x, int *add_y)
638 struct frame *f = XFRAME (w->frame);
639 *add_y = f->top_pos;
640 #ifdef FRAME_MENUBAR_HEIGHT
641 *add_y += FRAME_MENUBAR_HEIGHT (f);
642 #endif
643 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
644 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
645 #elif FRAME_TOOLBAR_HEIGHT
646 *add_y += FRAME_TOOLBAR_HEIGHT (f);
647 #endif
648 #ifdef FRAME_NS_TITLEBAR_HEIGHT
649 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
650 #endif
651 *add_x = f->left_pos;
652 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
653 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
654 #endif
657 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
658 Swindow_absolute_pixel_edges, 0, 1, 0,
659 doc: /* Return a list of the edge pixel coordinates of WINDOW.
660 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
661 the top left corner of the display.
663 RIGHT is one more than the rightmost x position occupied by WINDOW.
664 BOTTOM is one more than the bottommost y position occupied by WINDOW.
665 The pixel edges include the space used by WINDOW's scroll bar, display
666 margins, fringes, header line, and/or mode line. For the pixel edges
667 of just the text area, use `window-inside-absolute-pixel-edges'. */)
668 (Lisp_Object window)
670 register struct window *w = decode_any_window (window);
671 int add_x, add_y;
672 calc_absolute_offset (w, &add_x, &add_y);
674 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
675 Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
676 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
677 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
678 Qnil))));
681 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
682 doc: /* Return a list of the edge coordinates of WINDOW.
683 The list has the form (LEFT TOP RIGHT BOTTOM).
684 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
685 all relative to 0, 0 at top left corner of frame.
687 RIGHT is one more than the rightmost column of WINDOW's text area.
688 BOTTOM is one more than the bottommost row of WINDOW's text area.
689 The inside edges do not include the space used by the WINDOW's scroll
690 bar, display margins, fringes, header line, and/or mode line. */)
691 (Lisp_Object window)
693 register struct window *w = decode_any_window (window);
695 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
696 + WINDOW_LEFT_MARGIN_COLS (w)
697 + WINDOW_LEFT_FRINGE_COLS (w)),
698 make_number (WINDOW_TOP_EDGE_LINE (w)
699 + WINDOW_HEADER_LINE_LINES (w)),
700 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
701 - WINDOW_RIGHT_MARGIN_COLS (w)
702 - WINDOW_RIGHT_FRINGE_COLS (w)),
703 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
704 - WINDOW_MODE_LINE_LINES (w)));
707 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
708 doc: /* Return a list of the edge pixel coordinates of WINDOW.
709 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
710 the top left corner of the frame.
712 RIGHT is one more than the rightmost x position of WINDOW's text area.
713 BOTTOM is one more than the bottommost y position of WINDOW's text area.
714 The inside edges do not include the space used by WINDOW's scroll bar,
715 display margins, fringes, header line, and/or mode line. */)
716 (Lisp_Object window)
718 register struct window *w = decode_any_window (window);
720 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
721 + WINDOW_LEFT_MARGIN_WIDTH (w)
722 + WINDOW_LEFT_FRINGE_WIDTH (w)),
723 make_number (WINDOW_TOP_EDGE_Y (w)
724 + WINDOW_HEADER_LINE_HEIGHT (w)),
725 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
726 - WINDOW_RIGHT_MARGIN_WIDTH (w)
727 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
728 make_number (WINDOW_BOTTOM_EDGE_Y (w)
729 - WINDOW_MODE_LINE_HEIGHT (w)));
732 DEFUN ("window-inside-absolute-pixel-edges",
733 Fwindow_inside_absolute_pixel_edges,
734 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
735 doc: /* Return a list of the edge pixel coordinates of WINDOW.
736 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
737 the top left corner of the display.
739 RIGHT is one more than the rightmost x position of WINDOW's text area.
740 BOTTOM is one more than the bottommost y position of WINDOW's text area.
741 The inside edges do not include the space used by WINDOW's scroll bar,
742 display margins, fringes, header line, and/or mode line. */)
743 (Lisp_Object window)
745 register struct window *w = decode_any_window (window);
746 int add_x, add_y;
747 calc_absolute_offset (w, &add_x, &add_y);
749 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
750 + WINDOW_LEFT_MARGIN_WIDTH (w)
751 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
752 make_number (WINDOW_TOP_EDGE_Y (w)
753 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
754 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
755 - WINDOW_RIGHT_MARGIN_WIDTH (w)
756 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
757 make_number (WINDOW_BOTTOM_EDGE_Y (w)
758 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
761 /* Test if the character at column X, row Y is within window W.
762 If it is not, return ON_NOTHING;
763 if it is in the window's text area, return ON_TEXT;
764 if it is on the window's modeline, return ON_MODE_LINE;
765 if it is on the border between the window and its right sibling,
766 return ON_VERTICAL_BORDER.
767 if it is on a scroll bar, return ON_SCROLL_BAR.
768 if it is on the window's top line, return ON_HEADER_LINE;
769 if it is in left or right fringe of the window,
770 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
771 if it is in the marginal area to the left/right of the window,
772 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
774 X and Y are frame relative pixel coordinates. */
776 static enum window_part
777 coordinates_in_window (register struct window *w, int x, int y)
779 struct frame *f = XFRAME (WINDOW_FRAME (w));
780 int left_x, right_x;
781 enum window_part part;
782 int ux = FRAME_COLUMN_WIDTH (f);
783 int x0 = WINDOW_LEFT_EDGE_X (w);
784 int x1 = WINDOW_RIGHT_EDGE_X (w);
785 /* The width of the area where the vertical line can be dragged.
786 (Between mode lines for instance. */
787 int grabbable_width = ux;
788 int lmargin_width, rmargin_width, text_left, text_right;
789 int top_y = WINDOW_TOP_EDGE_Y (w);
790 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
792 /* Outside any interesting row? */
793 if (y < top_y || y >= bottom_y)
794 return ON_NOTHING;
796 /* In what's below, we subtract 1 when computing right_x because we
797 want the rightmost pixel, which is given by left_pixel+width-1. */
798 if (w->pseudo_window_p)
800 left_x = 0;
801 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
803 else
805 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
806 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
809 /* On the mode line or header line? If it's near the start of
810 the mode or header line of window that's has a horizontal
811 sibling, say it's on the vertical line. That's to be able
812 to resize windows horizontally in case we're using toolkit
813 scroll bars. */
815 if (WINDOW_WANTS_MODELINE_P (w)
816 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
818 part = ON_MODE_LINE;
820 header_vertical_border_check:
821 /* We're somewhere on the mode line. We consider the place
822 between mode lines of horizontally adjacent mode lines
823 as the vertical border. If scroll bars on the left,
824 return the right window. */
825 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
826 || WINDOW_RIGHTMOST_P (w))
827 && !WINDOW_LEFTMOST_P (w)
828 && eabs (x - x0) < grabbable_width)
829 return ON_VERTICAL_BORDER;
831 /* Make sure we're not at the rightmost position of a
832 mode-/header-line and there's yet another window on the
833 right. (Bug#1372) */
834 else if ((WINDOW_RIGHTMOST_P (w) || x < x1)
835 && eabs (x - x1) < grabbable_width)
836 return ON_VERTICAL_BORDER;
838 if (x < x0 || x >= x1)
839 return ON_NOTHING;
841 return part;
844 if (WINDOW_WANTS_HEADER_LINE_P (w)
845 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
847 part = ON_HEADER_LINE;
848 goto header_vertical_border_check;
851 if (x < x0 || x >= x1) return ON_NOTHING;
853 /* Outside any interesting column? */
854 if (x < left_x || x > right_x)
855 return ON_SCROLL_BAR;
857 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
858 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
860 text_left = window_box_left (w, TEXT_AREA);
861 text_right = text_left + window_box_width (w, TEXT_AREA);
863 if (FRAME_WINDOW_P (f))
865 if (!w->pseudo_window_p
866 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
867 && !WINDOW_RIGHTMOST_P (w)
868 && (eabs (x - right_x) < grabbable_width))
869 return ON_VERTICAL_BORDER;
871 /* Need to say "x > right_x" rather than >=, since on character
872 terminals, the vertical line's x coordinate is right_x. */
873 else if (!w->pseudo_window_p
874 && !WINDOW_RIGHTMOST_P (w)
875 && x > right_x - ux)
876 return ON_VERTICAL_BORDER;
878 if (x < text_left)
880 if (lmargin_width > 0
881 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
882 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
883 : (x < left_x + lmargin_width)))
884 return ON_LEFT_MARGIN;
886 return ON_LEFT_FRINGE;
889 if (x >= text_right)
891 if (rmargin_width > 0
892 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
893 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
894 : (x >= right_x - rmargin_width)))
895 return ON_RIGHT_MARGIN;
897 return ON_RIGHT_FRINGE;
900 /* Everything special ruled out - must be on text area */
901 return ON_TEXT;
904 /* Take X is the frame-relative pixel x-coordinate, and return the
905 x-coordinate relative to part PART of window W. */
907 window_relative_x_coord (struct window *w, enum window_part part, int x)
909 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
911 switch (part)
913 case ON_TEXT:
914 return x - window_box_left (w, TEXT_AREA);
916 case ON_LEFT_FRINGE:
917 return x - left_x;
919 case ON_RIGHT_FRINGE:
920 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
922 case ON_LEFT_MARGIN:
923 return (x - left_x
924 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
925 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
927 case ON_RIGHT_MARGIN:
928 return (x + 1
929 - ((w->pseudo_window_p)
930 ? WINDOW_TOTAL_WIDTH (w)
931 : WINDOW_BOX_RIGHT_EDGE_X (w))
932 + window_box_width (w, RIGHT_MARGIN_AREA)
933 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
934 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
937 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
938 return 0;
942 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
943 Scoordinates_in_window_p, 2, 2, 0,
944 doc: /* Return non-nil if COORDINATES are in WINDOW.
945 COORDINATES is a cons of the form (X . Y), X and Y being distances
946 measured in characters from the upper-left corner of the frame.
947 \(0 . 0) denotes the character in the upper left corner of the
948 frame.
949 If COORDINATES are in the text portion of WINDOW,
950 the coordinates relative to the window are returned.
951 If they are in the mode line of WINDOW, `mode-line' is returned.
952 If they are in the top mode line of WINDOW, `header-line' is returned.
953 If they are in the left fringe of WINDOW, `left-fringe' is returned.
954 If they are in the right fringe of WINDOW, `right-fringe' is returned.
955 If they are on the border between WINDOW and its right sibling,
956 `vertical-line' is returned.
957 If they are in the windows's left or right marginal areas, `left-margin'\n\
958 or `right-margin' is returned. */)
959 (register Lisp_Object coordinates, Lisp_Object window)
961 struct window *w;
962 struct frame *f;
963 int x, y;
964 Lisp_Object lx, ly;
966 CHECK_WINDOW (window);
967 w = XWINDOW (window);
968 f = XFRAME (w->frame);
969 CHECK_CONS (coordinates);
970 lx = Fcar (coordinates);
971 ly = Fcdr (coordinates);
972 CHECK_NUMBER_OR_FLOAT (lx);
973 CHECK_NUMBER_OR_FLOAT (ly);
974 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
975 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
977 switch (coordinates_in_window (w, x, y))
979 case ON_NOTHING:
980 return Qnil;
982 case ON_TEXT:
983 /* Convert X and Y to window relative pixel coordinates, and
984 return the canonical char units. */
985 x -= window_box_left (w, TEXT_AREA);
986 y -= WINDOW_TOP_EDGE_Y (w);
987 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
988 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
990 case ON_MODE_LINE:
991 return Qmode_line;
993 case ON_VERTICAL_BORDER:
994 return Qvertical_line;
996 case ON_HEADER_LINE:
997 return Qheader_line;
999 case ON_LEFT_FRINGE:
1000 return Qleft_fringe;
1002 case ON_RIGHT_FRINGE:
1003 return Qright_fringe;
1005 case ON_LEFT_MARGIN:
1006 return Qleft_margin;
1008 case ON_RIGHT_MARGIN:
1009 return Qright_margin;
1011 case ON_SCROLL_BAR:
1012 /* Historically we are supposed to return nil in this case. */
1013 return Qnil;
1015 default:
1016 abort ();
1021 /* Callback for foreach_window, used in window_from_coordinates.
1022 Check if window W contains coordinates specified by USER_DATA which
1023 is actually a pointer to a struct check_window_data CW.
1025 Check if window W contains coordinates *CW->x and *CW->y. If it
1026 does, return W in *CW->window, as Lisp_Object, and return in
1027 *CW->part the part of the window under coordinates *X,*Y. Return
1028 zero from this function to stop iterating over windows. */
1030 struct check_window_data
1032 Lisp_Object *window;
1033 int x, y;
1034 enum window_part *part;
1037 static int
1038 check_window_containing (struct window *w, void *user_data)
1040 struct check_window_data *cw = (struct check_window_data *) user_data;
1041 enum window_part found;
1042 int continue_p = 1;
1044 found = coordinates_in_window (w, cw->x, cw->y);
1045 if (found != ON_NOTHING)
1047 *cw->part = found;
1048 XSETWINDOW (*cw->window, w);
1049 continue_p = 0;
1052 return continue_p;
1056 /* Find the window containing frame-relative pixel position X/Y and
1057 return it as a Lisp_Object.
1059 If X, Y is on one of the window's special `window_part' elements,
1060 set *PART to the id of that element.
1062 If there is no window under X, Y return nil and leave *PART
1063 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1065 This function was previously implemented with a loop cycling over
1066 windows with Fnext_window, and starting with the frame's selected
1067 window. It turned out that this doesn't work with an
1068 implementation of next_window using Vwindow_list, because
1069 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1070 tree of F when this function is called asynchronously from
1071 note_mouse_highlight. The original loop didn't terminate in this
1072 case. */
1074 Lisp_Object
1075 window_from_coordinates (struct frame *f, int x, int y,
1076 enum window_part *part, int tool_bar_p)
1078 Lisp_Object window;
1079 struct check_window_data cw;
1080 enum window_part dummy;
1082 if (part == 0)
1083 part = &dummy;
1085 window = Qnil;
1086 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1087 foreach_window (f, check_window_containing, &cw);
1089 /* If not found above, see if it's in the tool bar window, if a tool
1090 bar exists. */
1091 if (NILP (window)
1092 && tool_bar_p
1093 && WINDOWP (f->tool_bar_window)
1094 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1095 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1096 != ON_NOTHING))
1098 *part = ON_TEXT;
1099 window = f->tool_bar_window;
1102 return window;
1105 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1106 doc: /* Return window containing coordinates X and Y on FRAME.
1107 If omitted, FRAME defaults to the currently selected frame.
1108 The top left corner of the frame is considered to be row 0,
1109 column 0. */)
1110 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1112 struct frame *f;
1114 if (NILP (frame))
1115 frame = selected_frame;
1116 CHECK_LIVE_FRAME (frame);
1117 f = XFRAME (frame);
1119 /* Check that arguments are integers or floats. */
1120 CHECK_NUMBER_OR_FLOAT (x);
1121 CHECK_NUMBER_OR_FLOAT (y);
1123 return window_from_coordinates (f,
1124 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1125 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1126 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1127 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1128 0, 0);
1131 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1132 doc: /* Return current value of point in WINDOW.
1133 WINDOW defaults to the selected window.
1135 For a nonselected window, this is the value point would have
1136 if that window were selected.
1138 Note that, when WINDOW is the selected window and its buffer
1139 is also currently selected, the value returned is the same as (point).
1140 It would be more strictly correct to return the `top-level' value
1141 of point, outside of any save-excursion forms.
1142 But that is hard to define. */)
1143 (Lisp_Object window)
1145 register struct window *w = decode_window (window);
1147 if (w == XWINDOW (selected_window)
1148 && current_buffer == XBUFFER (w->buffer))
1149 return Fpoint ();
1150 return Fmarker_position (w->pointm);
1153 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1154 doc: /* Return position at which display currently starts in WINDOW.
1155 WINDOW defaults to the selected window.
1156 This is updated by redisplay or by calling `set-window-start'. */)
1157 (Lisp_Object window)
1159 return Fmarker_position (decode_window (window)->start);
1162 /* This is text temporarily removed from the doc string below.
1164 This function returns nil if the position is not currently known.
1165 That happens when redisplay is preempted and doesn't finish.
1166 If in that case you want to compute where the end of the window would
1167 have been if redisplay had finished, do this:
1168 (save-excursion
1169 (goto-char (window-start window))
1170 (vertical-motion (1- (window-height window)) window)
1171 (point))") */
1173 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1174 doc: /* Return position at which display currently ends in WINDOW.
1175 WINDOW defaults to the selected window.
1176 This is updated by redisplay, when it runs to completion.
1177 Simply changing the buffer text or setting `window-start'
1178 does not update this value.
1179 Return nil if there is no recorded value. \(This can happen if the
1180 last redisplay of WINDOW was preempted, and did not finish.)
1181 If UPDATE is non-nil, compute the up-to-date position
1182 if it isn't already recorded. */)
1183 (Lisp_Object window, Lisp_Object update)
1185 Lisp_Object value;
1186 struct window *w = decode_window (window);
1187 Lisp_Object buf;
1188 struct buffer *b;
1190 buf = w->buffer;
1191 CHECK_BUFFER (buf);
1192 b = XBUFFER (buf);
1194 #if 0 /* This change broke some things. We should make it later. */
1195 /* If we don't know the end position, return nil.
1196 The user can compute it with vertical-motion if he wants to.
1197 It would be nicer to do it automatically,
1198 but that's so slow that it would probably bother people. */
1199 if (NILP (w->window_end_valid))
1200 return Qnil;
1201 #endif
1203 if (! NILP (update)
1204 && ! (! NILP (w->window_end_valid)
1205 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1206 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1207 && !noninteractive)
1209 struct text_pos startp;
1210 struct it it;
1211 struct buffer *old_buffer = NULL;
1213 /* Cannot use Fvertical_motion because that function doesn't
1214 cope with variable-height lines. */
1215 if (b != current_buffer)
1217 old_buffer = current_buffer;
1218 set_buffer_internal (b);
1221 /* In case W->start is out of the range, use something
1222 reasonable. This situation occurred when loading a file with
1223 `-l' containing a call to `rmail' with subsequent other
1224 commands. At the end, W->start happened to be BEG, while
1225 rmail had already narrowed the buffer. */
1226 if (XMARKER (w->start)->charpos < BEGV)
1227 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1228 else if (XMARKER (w->start)->charpos > ZV)
1229 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1230 else
1231 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1233 start_display (&it, w, startp);
1234 move_it_vertically (&it, window_box_height (w));
1235 if (it.current_y < it.last_visible_y)
1236 move_it_past_eol (&it);
1237 value = make_number (IT_CHARPOS (it));
1239 if (old_buffer)
1240 set_buffer_internal (old_buffer);
1242 else
1243 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1245 return value;
1248 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1249 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1250 Return POS. */)
1251 (Lisp_Object window, Lisp_Object pos)
1253 register struct window *w = decode_window (window);
1255 CHECK_NUMBER_COERCE_MARKER (pos);
1256 if (w == XWINDOW (selected_window)
1257 && XBUFFER (w->buffer) == current_buffer)
1258 Fgoto_char (pos);
1259 else
1260 set_marker_restricted (w->pointm, pos, w->buffer);
1262 /* We have to make sure that redisplay updates the window to show
1263 the new value of point. */
1264 if (!EQ (window, selected_window))
1265 ++windows_or_buffers_changed;
1267 return pos;
1270 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1271 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1272 WINDOW defaults to the selected window. Return POS.
1273 Optional third arg NOFORCE non-nil inhibits next redisplay from
1274 overriding motion of point in order to display at this exact start. */)
1275 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1277 register struct window *w = decode_window (window);
1279 CHECK_NUMBER_COERCE_MARKER (pos);
1280 set_marker_restricted (w->start, pos, w->buffer);
1281 /* this is not right, but much easier than doing what is right. */
1282 w->start_at_line_beg = Qnil;
1283 if (NILP (noforce))
1284 w->force_start = Qt;
1285 w->update_mode_line = Qt;
1286 XSETFASTINT (w->last_modified, 0);
1287 XSETFASTINT (w->last_overlay_modified, 0);
1288 if (!EQ (window, selected_window))
1289 windows_or_buffers_changed++;
1291 return pos;
1295 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1296 0, 1, 0,
1297 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1298 More precisely, return the value assigned by the last call of
1299 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1300 never called with WINDOW as its argument, or the value set by that
1301 function was internally reset since its last call. WINDOW defaults to
1302 the selected window.
1304 When a window is dedicated to its buffer, `display-buffer' will refrain
1305 from displaying another buffer in it. `get-lru-window' and
1306 `get-largest-window' treat dedicated windows specially.
1307 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1308 `kill-buffer' can delete a dedicated window and the containing frame.
1310 Functions like `set-window-buffer' may change the buffer displayed by a
1311 window, unless that window is "strongly" dedicated to its buffer, that
1312 is the value returned by `window-dedicated-p' is t. */)
1313 (Lisp_Object window)
1315 return decode_window (window)->dedicated;
1318 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1319 Sset_window_dedicated_p, 2, 2, 0,
1320 doc: /* Mark WINDOW as dedicated according to FLAG.
1321 WINDOW defaults to the selected window. FLAG non-nil means mark WINDOW
1322 as dedicated to its buffer. FLAG nil means mark WINDOW as non-dedicated.
1323 Return FLAG.
1325 When a window is dedicated to its buffer, `display-buffer' will refrain
1326 from displaying another buffer in it. `get-lru-window' and
1327 `get-largest-window' treat dedicated windows specially.
1328 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1329 `kill-buffer' can delete a dedicated window and the containing
1330 frame.
1332 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1333 its buffer. Functions like `set-window-buffer' may change the buffer
1334 displayed by a window, unless that window is strongly dedicated to its
1335 buffer. If and when `set-window-buffer' displays another buffer in a
1336 window, it also makes sure that the window is not marked as dedicated. */)
1337 (Lisp_Object window, Lisp_Object flag)
1339 register struct window *w = decode_window (window);
1341 w->dedicated = flag;
1342 return w->dedicated;
1346 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1347 0, 1, 0,
1348 doc: /* Return the parameters of WINDOW and their values.
1349 WINDOW defaults to the selected window. The return value is a list of
1350 elements of the form (PARAMETER . VALUE). */)
1351 (Lisp_Object window)
1353 return Fcopy_alist (decode_window (window)->window_parameters);
1356 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1357 2, 2, 0,
1358 doc: /* Return WINDOW's value for PARAMETER.
1359 WINDOW defaults to the selected window. */)
1360 (Lisp_Object window, Lisp_Object parameter)
1362 Lisp_Object result;
1364 result = Fassq (parameter, decode_window (window)->window_parameters);
1365 return CDR_SAFE (result);
1368 DEFUN ("set-window-parameter", Fset_window_parameter,
1369 Sset_window_parameter, 3, 3, 0,
1370 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1371 WINDOW defaults to the selected window. Return VALUE. */)
1372 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1374 register struct window *w = decode_window (window);
1375 Lisp_Object old_alist_elt;
1377 old_alist_elt = Fassq (parameter, w->window_parameters);
1378 if (NILP (old_alist_elt))
1379 w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
1380 else
1381 Fsetcdr (old_alist_elt, value);
1382 return value;
1386 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1387 0, 1, 0,
1388 doc: /* Return the display-table that WINDOW is using.
1389 WINDOW defaults to the selected window. */)
1390 (Lisp_Object window)
1392 return decode_window (window)->display_table;
1395 /* Get the display table for use on window W. This is either W's
1396 display table or W's buffer's display table. Ignore the specified
1397 tables if they are not valid; if no valid table is specified,
1398 return 0. */
1400 struct Lisp_Char_Table *
1401 window_display_table (struct window *w)
1403 struct Lisp_Char_Table *dp = NULL;
1405 if (DISP_TABLE_P (w->display_table))
1406 dp = XCHAR_TABLE (w->display_table);
1407 else if (BUFFERP (w->buffer))
1409 struct buffer *b = XBUFFER (w->buffer);
1411 if (DISP_TABLE_P (b->display_table))
1412 dp = XCHAR_TABLE (b->display_table);
1413 else if (DISP_TABLE_P (Vstandard_display_table))
1414 dp = XCHAR_TABLE (Vstandard_display_table);
1417 return dp;
1420 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1421 doc: /* Set WINDOW's display-table to TABLE. */)
1422 (register Lisp_Object window, Lisp_Object table)
1424 register struct window *w;
1426 w = decode_window (window);
1427 w->display_table = table;
1428 return table;
1431 static void delete_window (Lisp_Object);
1433 /* Record info on buffer window w is displaying
1434 when it is about to cease to display that buffer. */
1435 static void
1436 unshow_buffer (register struct window *w)
1438 Lisp_Object buf;
1439 struct buffer *b;
1441 buf = w->buffer;
1442 b = XBUFFER (buf);
1443 if (b != XMARKER (w->pointm)->buffer)
1444 abort ();
1446 #if 0
1447 if (w == XWINDOW (selected_window)
1448 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1449 /* Do this except when the selected window's buffer
1450 is being removed from some other window. */
1451 #endif
1452 /* last_window_start records the start position that this buffer
1453 had in the last window to be disconnected from it.
1454 Now that this statement is unconditional,
1455 it is possible for the buffer to be displayed in the
1456 selected window, while last_window_start reflects another
1457 window which was recently showing the same buffer.
1458 Some people might say that might be a good thing. Let's see. */
1459 b->last_window_start = marker_position (w->start);
1461 /* Point in the selected window's buffer
1462 is actually stored in that buffer, and the window's pointm isn't used.
1463 So don't clobber point in that buffer. */
1464 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1465 /* This line helps to fix Horsley's testbug.el bug. */
1466 && !(WINDOWP (b->last_selected_window)
1467 && w != XWINDOW (b->last_selected_window)
1468 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1469 temp_set_point_both (b,
1470 clip_to_bounds (BUF_BEGV (b),
1471 XMARKER (w->pointm)->charpos,
1472 BUF_ZV (b)),
1473 clip_to_bounds (BUF_BEGV_BYTE (b),
1474 marker_byte_position (w->pointm),
1475 BUF_ZV_BYTE (b)));
1477 if (WINDOWP (b->last_selected_window)
1478 && w == XWINDOW (b->last_selected_window))
1479 b->last_selected_window = Qnil;
1482 /* Put replacement into the window structure in place of old. */
1483 static void
1484 replace_window (Lisp_Object old, Lisp_Object 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 memset (&p->cursor, 0, sizeof (p->cursor));
1502 memset (&p->last_cursor, 0, sizeof (p->last_cursor));
1503 memset (&p->phys_cursor, 0, 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 (register Lisp_Object window)
1542 struct frame *f;
1543 if (NILP (window))
1544 window = selected_window;
1545 else
1546 CHECK_LIVE_WINDOW (window);
1548 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1549 delete_window (window);
1551 run_window_configuration_change_hook (f);
1553 return Qnil;
1556 static void
1557 delete_window (register Lisp_Object window)
1559 register Lisp_Object tem, parent, sib;
1560 register struct window *p;
1561 register struct window *par;
1562 struct frame *f;
1564 /* Because this function is called by other C code on non-leaf
1565 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1566 so we can't decode_window here. */
1567 CHECK_WINDOW (window);
1568 p = XWINDOW (window);
1570 /* It's a no-op to delete an already-deleted window. */
1571 if (NILP (p->buffer)
1572 && NILP (p->hchild)
1573 && NILP (p->vchild))
1574 return;
1576 parent = p->parent;
1577 if (NILP (parent))
1578 error ("Attempt to delete minibuffer or sole ordinary window");
1579 par = XWINDOW (parent);
1581 windows_or_buffers_changed++;
1582 Vwindow_list = Qnil;
1583 f = XFRAME (WINDOW_FRAME (p));
1584 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1586 /* Are we trying to delete any frame's selected window? */
1588 Lisp_Object swindow, pwindow;
1590 /* See if the frame's selected window is either WINDOW
1591 or any subwindow of it, by finding all that window's parents
1592 and comparing each one with WINDOW. */
1593 swindow = FRAME_SELECTED_WINDOW (f);
1595 while (1)
1597 pwindow = swindow;
1598 while (!NILP (pwindow))
1600 if (EQ (window, pwindow))
1601 break;
1602 pwindow = XWINDOW (pwindow)->parent;
1605 /* If the window being deleted is not a parent of SWINDOW,
1606 then SWINDOW is ok as the new selected window. */
1607 if (!EQ (window, pwindow))
1608 break;
1609 /* Otherwise, try another window for SWINDOW. */
1610 swindow = Fnext_window (swindow, Qlambda, Qnil);
1612 /* If we get back to the frame's selected window,
1613 it means there was no acceptable alternative,
1614 so we cannot delete. */
1615 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1616 error ("Cannot delete window");
1619 /* If we need to change SWINDOW, do it. */
1620 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1622 /* If we're about to delete the selected window on the
1623 selected frame, then we should use Fselect_window to select
1624 the new window. On the other hand, if we're about to
1625 delete the selected window on any other frame, we shouldn't do
1626 anything but set the frame's selected_window slot. */
1627 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1628 Fselect_window (swindow, Qnil);
1629 else
1630 FRAME_SELECTED_WINDOW (f) = swindow;
1634 /* Now we know we can delete this one. */
1635 window_deletion_count++;
1637 tem = p->buffer;
1638 /* tem is null for dummy parent windows
1639 (which have inferiors but not any contents themselves) */
1640 if (!NILP (tem))
1642 unshow_buffer (p);
1643 unchain_marker (XMARKER (p->pointm));
1644 unchain_marker (XMARKER (p->start));
1647 /* Free window glyph matrices. It is sure that they are allocated
1648 again when ADJUST_GLYPHS is called. Block input so that expose
1649 events and other events that access glyph matrices are not
1650 processed while we are changing them. */
1651 BLOCK_INPUT;
1652 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1654 tem = p->next;
1655 if (!NILP (tem))
1656 XWINDOW (tem)->prev = p->prev;
1658 tem = p->prev;
1659 if (!NILP (tem))
1660 XWINDOW (tem)->next = p->next;
1662 if (EQ (window, par->hchild))
1663 par->hchild = p->next;
1664 if (EQ (window, par->vchild))
1665 par->vchild = p->next;
1667 /* Find one of our siblings to give our space to. */
1668 sib = p->prev;
1669 if (NILP (sib))
1671 /* If p gives its space to its next sibling, that sibling needs
1672 to have its top/left side pulled back to where p's is.
1673 set_window_{height,width} will re-position the sibling's
1674 children. */
1675 sib = p->next;
1676 XWINDOW (sib)->top_line = p->top_line;
1677 XWINDOW (sib)->left_col = p->left_col;
1680 /* Stretch that sibling. */
1681 if (!NILP (par->vchild))
1682 set_window_height (sib,
1683 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1685 if (!NILP (par->hchild))
1686 set_window_width (sib,
1687 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1690 /* If parent now has only one child,
1691 put the child into the parent's place. */
1692 tem = par->hchild;
1693 if (NILP (tem))
1694 tem = par->vchild;
1695 if (NILP (XWINDOW (tem)->next)) {
1696 replace_window (parent, tem);
1697 par = XWINDOW (tem);
1700 /* Since we may be deleting combination windows, we must make sure that
1701 not only p but all its children have been marked as deleted. */
1702 if (! NILP (p->hchild))
1703 delete_all_subwindows (XWINDOW (p->hchild));
1704 else if (! NILP (p->vchild))
1705 delete_all_subwindows (XWINDOW (p->vchild));
1707 /* Mark this window as deleted. */
1708 p->buffer = p->hchild = p->vchild = Qnil;
1710 if (! NILP (par->parent))
1711 par = XWINDOW (par->parent);
1713 /* Check if we have a v/hchild with a v/hchild. In that case remove
1714 one of them. */
1716 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1718 p = XWINDOW (par->vchild);
1719 par->vchild = p->vchild;
1720 tem = p->vchild;
1722 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1724 p = XWINDOW (par->hchild);
1725 par->hchild = p->hchild;
1726 tem = p->hchild;
1728 else
1729 p = 0;
1731 if (p)
1733 while (! NILP (tem)) {
1734 XWINDOW (tem)->parent = p->parent;
1735 if (NILP (XWINDOW (tem)->next))
1736 break;
1737 tem = XWINDOW (tem)->next;
1739 if (! NILP (tem)) {
1740 /* The next of the v/hchild we are removing is now the next of the
1741 last child for the v/hchild:
1742 Before v/hchild -> v/hchild -> next1 -> next2
1744 -> next3
1745 After: v/hchild -> next1 -> next2 -> next3
1747 XWINDOW (tem)->next = p->next;
1748 if (! NILP (p->next))
1749 XWINDOW (p->next)->prev = tem;
1751 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1755 /* Adjust glyph matrices. */
1756 adjust_glyphs (f);
1757 UNBLOCK_INPUT;
1762 /***********************************************************************
1763 Window List
1764 ***********************************************************************/
1766 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1767 pointer. This is a callback function for foreach_window, used in
1768 function window_list. */
1770 static int
1771 add_window_to_list (struct window *w, void *user_data)
1773 Lisp_Object *list = (Lisp_Object *) user_data;
1774 Lisp_Object window;
1775 XSETWINDOW (window, w);
1776 *list = Fcons (window, *list);
1777 return 1;
1781 /* Return a list of all windows, for use by next_window. If
1782 Vwindow_list is a list, return that list. Otherwise, build a new
1783 list, cache it in Vwindow_list, and return that. */
1785 static Lisp_Object
1786 window_list (void)
1788 if (!CONSP (Vwindow_list))
1790 Lisp_Object tail;
1792 Vwindow_list = Qnil;
1793 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1795 Lisp_Object args[2];
1797 /* We are visiting windows in canonical order, and add
1798 new windows at the front of args[1], which means we
1799 have to reverse this list at the end. */
1800 args[1] = Qnil;
1801 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1802 args[0] = Vwindow_list;
1803 args[1] = Fnreverse (args[1]);
1804 Vwindow_list = Fnconc (2, args);
1808 return Vwindow_list;
1812 /* Value is non-zero if WINDOW satisfies the constraints given by
1813 OWINDOW, MINIBUF and ALL_FRAMES.
1815 MINIBUF t means WINDOW may be minibuffer windows.
1816 `lambda' means WINDOW may not be a minibuffer window.
1817 a window means a specific minibuffer window
1819 ALL_FRAMES t means search all frames,
1820 nil means search just current frame,
1821 `visible' means search just visible frames,
1822 0 means search visible and iconified frames,
1823 a window means search the frame that window belongs to,
1824 a frame means consider windows on that frame, only. */
1826 static int
1827 candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
1829 struct window *w = XWINDOW (window);
1830 struct frame *f = XFRAME (w->frame);
1831 int candidate_p = 1;
1833 if (!BUFFERP (w->buffer))
1834 candidate_p = 0;
1835 else if (MINI_WINDOW_P (w)
1836 && (EQ (minibuf, Qlambda)
1837 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1839 /* If MINIBUF is `lambda' don't consider any mini-windows.
1840 If it is a window, consider only that one. */
1841 candidate_p = 0;
1843 else if (EQ (all_frames, Qt))
1844 candidate_p = 1;
1845 else if (NILP (all_frames))
1847 xassert (WINDOWP (owindow));
1848 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1850 else if (EQ (all_frames, Qvisible))
1852 FRAME_SAMPLE_VISIBILITY (f);
1853 candidate_p = FRAME_VISIBLE_P (f)
1854 && (FRAME_TERMINAL (XFRAME (w->frame))
1855 == FRAME_TERMINAL (XFRAME (selected_frame)));
1858 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1860 FRAME_SAMPLE_VISIBILITY (f);
1861 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
1862 #ifdef HAVE_X_WINDOWS
1863 /* Yuck!! If we've just created the frame and the
1864 window-manager requested the user to place it
1865 manually, the window may still not be considered
1866 `visible'. I'd argue it should be at least
1867 something like `iconified', but don't know how to do
1868 that yet. --Stef */
1869 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
1870 && !f->output_data.x->has_been_visible)
1871 #endif
1873 && (FRAME_TERMINAL (XFRAME (w->frame))
1874 == FRAME_TERMINAL (XFRAME (selected_frame)));
1876 else if (WINDOWP (all_frames))
1877 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1878 || EQ (XWINDOW (all_frames)->frame, w->frame)
1879 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1880 else if (FRAMEP (all_frames))
1881 candidate_p = EQ (all_frames, w->frame);
1883 return candidate_p;
1887 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1888 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1889 ALL_FRAMES. */
1891 static void
1892 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
1894 if (NILP (*window))
1895 *window = selected_window;
1896 else
1897 CHECK_LIVE_WINDOW (*window);
1899 /* MINIBUF nil may or may not include minibuffers. Decide if it
1900 does. */
1901 if (NILP (*minibuf))
1902 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1903 else if (!EQ (*minibuf, Qt))
1904 *minibuf = Qlambda;
1906 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1907 => count none of them, or a specific minibuffer window (the
1908 active one) to count. */
1910 /* ALL_FRAMES nil doesn't specify which frames to include. */
1911 if (NILP (*all_frames))
1912 *all_frames = (!EQ (*minibuf, Qlambda)
1913 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1914 : Qnil);
1915 else if (EQ (*all_frames, Qvisible))
1917 else if (EQ (*all_frames, make_number (0)))
1919 else if (FRAMEP (*all_frames))
1921 else if (!EQ (*all_frames, Qt))
1922 *all_frames = Qnil;
1924 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1925 search just current frame, `visible' meaning search just visible
1926 frames, 0 meaning search visible and iconified frames, or a
1927 window, meaning search the frame that window belongs to, or a
1928 frame, meaning consider windows on that frame, only. */
1932 /* Return the next or previous window of WINDOW in cyclic ordering
1933 of windows. NEXT_P non-zero means return the next window. See the
1934 documentation string of next-window for the meaning of MINIBUF and
1935 ALL_FRAMES. */
1937 static Lisp_Object
1938 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
1940 decode_next_window_args (&window, &minibuf, &all_frames);
1942 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1943 return the first window on the frame. */
1944 if (FRAMEP (all_frames)
1945 && !EQ (all_frames, XWINDOW (window)->frame))
1946 return Fframe_first_window (all_frames);
1948 if (next_p)
1950 Lisp_Object list;
1952 /* Find WINDOW in the list of all windows. */
1953 list = Fmemq (window, window_list ());
1955 /* Scan forward from WINDOW to the end of the window list. */
1956 if (CONSP (list))
1957 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1958 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1959 break;
1961 /* Scan from the start of the window list up to WINDOW. */
1962 if (!CONSP (list))
1963 for (list = Vwindow_list;
1964 CONSP (list) && !EQ (XCAR (list), window);
1965 list = XCDR (list))
1966 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1967 break;
1969 if (CONSP (list))
1970 window = XCAR (list);
1972 else
1974 Lisp_Object candidate, list;
1976 /* Scan through the list of windows for candidates. If there are
1977 candidate windows in front of WINDOW, the last one of these
1978 is the one we want. If there are candidates following WINDOW
1979 in the list, again the last one of these is the one we want. */
1980 candidate = Qnil;
1981 for (list = window_list (); CONSP (list); list = XCDR (list))
1983 if (EQ (XCAR (list), window))
1985 if (WINDOWP (candidate))
1986 break;
1988 else if (candidate_window_p (XCAR (list), window, minibuf,
1989 all_frames))
1990 candidate = XCAR (list);
1993 if (WINDOWP (candidate))
1994 window = candidate;
1997 return window;
2001 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2002 doc: /* Return window following WINDOW in cyclic ordering of windows.
2003 WINDOW defaults to the selected window. The optional arguments
2004 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2006 MINIBUF t means consider the minibuffer window even if the
2007 minibuffer is not active. MINIBUF nil or omitted means consider
2008 the minibuffer window only if the minibuffer is active. Any
2009 other value means do not consider the minibuffer window even if
2010 the minibuffer is active.
2012 Several frames may share a single minibuffer; if the minibuffer
2013 is active, all windows on all frames that share that minibuffer
2014 are considered too. Therefore, if you are using a separate
2015 minibuffer frame and the minibuffer is active and MINIBUF says it
2016 counts, `next-window' considers the windows in the frame from
2017 which you entered the minibuffer, as well as the minibuffer
2018 window.
2020 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
2021 frame, plus the minibuffer window if specified by the MINIBUF
2022 argument, see above. If the minibuffer counts, consider all
2023 windows on all frames that share that minibuffer too.
2024 ALL-FRAMES t means consider all windows on all existing frames.
2025 ALL-FRAMES `visible' means consider all windows on all visible
2026 frames.
2027 ALL-FRAMES 0 means consider all windows on all visible and
2028 iconified frames.
2029 ALL-FRAMES a frame means consider all windows on that frame only.
2030 Anything else means consider all windows on WINDOW's frame and no
2031 others.
2033 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2034 `next-window' to iterate through the entire cycle of acceptable
2035 windows, eventually ending up back at the window you started with.
2036 `previous-window' traverses the same cycle, in the reverse order. */)
2037 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2039 return next_window (window, minibuf, all_frames, 1);
2043 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2044 doc: /* Return window preceding WINDOW in cyclic ordering of windows.
2045 WINDOW defaults to the selected window. The optional arguments
2046 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2047 For the precise meaning of these arguments see `next-window'.
2049 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2050 use `previous-window' to iterate through the entire cycle of
2051 acceptable windows, eventually ending up back at the window you
2052 started with. `next-window' traverses the same cycle, in the
2053 reverse order. */)
2054 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2056 return next_window (window, minibuf, all_frames, 0);
2060 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2061 doc: /* Select another window in cyclic ordering of windows.
2062 COUNT specifies the number of windows to skip, starting with the
2063 selected window, before making the selection. If COUNT is
2064 positive, skip COUNT windows forwards. If COUNT is negative,
2065 skip -COUNT windows backwards. COUNT zero means do not skip any
2066 window, so select the selected window. In an interactive call,
2067 COUNT is the numeric prefix argument. Return nil.
2069 This function uses `next-window' for finding the window to select.
2070 The argument ALL-FRAMES has the same meaning as in `next-window',
2071 but the MINIBUF argument of `next-window' is always effectively
2072 nil. */)
2073 (Lisp_Object count, Lisp_Object all_frames)
2075 Lisp_Object window;
2076 int i;
2078 CHECK_NUMBER (count);
2079 window = selected_window;
2081 for (i = XINT (count); i > 0; --i)
2082 window = Fnext_window (window, Qnil, all_frames);
2083 for (; i < 0; ++i)
2084 window = Fprevious_window (window, Qnil, all_frames);
2086 Fselect_window (window, Qnil);
2087 return Qnil;
2091 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2092 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2093 FRAME nil or omitted means use the selected frame.
2094 WINDOW nil or omitted means use the selected window.
2095 MINIBUF t means include the minibuffer window, even if it isn't active.
2096 MINIBUF nil or omitted means include the minibuffer window only
2097 if it's active.
2098 MINIBUF neither nil nor t means never include the minibuffer window. */)
2099 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2101 if (NILP (window))
2102 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2103 CHECK_WINDOW (window);
2104 if (NILP (frame))
2105 frame = selected_frame;
2107 if (!EQ (frame, XWINDOW (window)->frame))
2108 error ("Window is on a different frame");
2110 return window_list_1 (window, minibuf, frame);
2114 /* Return a list of windows in cyclic ordering. Arguments are like
2115 for `next-window'. */
2117 static Lisp_Object
2118 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2120 Lisp_Object tail, list, rest;
2122 decode_next_window_args (&window, &minibuf, &all_frames);
2123 list = Qnil;
2125 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2126 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2127 list = Fcons (XCAR (tail), list);
2129 /* Rotate the list to start with WINDOW. */
2130 list = Fnreverse (list);
2131 rest = Fmemq (window, list);
2132 if (!NILP (rest) && !EQ (rest, list))
2134 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2136 XSETCDR (tail, Qnil);
2137 list = nconc2 (rest, list);
2139 return list;
2144 /* Look at all windows, performing an operation specified by TYPE
2145 with argument OBJ.
2146 If FRAMES is Qt, look at all frames;
2147 Qnil, look at just the selected frame;
2148 Qvisible, look at visible frames;
2149 a frame, just look at windows on that frame.
2150 If MINI is non-zero, perform the operation on minibuffer windows too. */
2152 enum window_loop
2154 WINDOW_LOOP_UNUSED,
2155 GET_BUFFER_WINDOW, /* Arg is buffer */
2156 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2157 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2158 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2159 GET_LARGEST_WINDOW,
2160 UNSHOW_BUFFER, /* Arg is buffer */
2161 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2162 CHECK_ALL_WINDOWS
2165 static Lisp_Object
2166 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2168 Lisp_Object window, windows, best_window, frame_arg;
2169 struct frame *f;
2170 struct gcpro gcpro1;
2172 /* If we're only looping through windows on a particular frame,
2173 frame points to that frame. If we're looping through windows
2174 on all frames, frame is 0. */
2175 if (FRAMEP (frames))
2176 f = XFRAME (frames);
2177 else if (NILP (frames))
2178 f = SELECTED_FRAME ();
2179 else
2180 f = NULL;
2182 if (f)
2183 frame_arg = Qlambda;
2184 else if (EQ (frames, make_number (0)))
2185 frame_arg = frames;
2186 else if (EQ (frames, Qvisible))
2187 frame_arg = frames;
2188 else
2189 frame_arg = Qt;
2191 /* frame_arg is Qlambda to stick to one frame,
2192 Qvisible to consider all visible frames,
2193 or Qt otherwise. */
2195 /* Pick a window to start with. */
2196 if (WINDOWP (obj))
2197 window = obj;
2198 else if (f)
2199 window = FRAME_SELECTED_WINDOW (f);
2200 else
2201 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2203 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2204 GCPRO1 (windows);
2205 best_window = Qnil;
2207 for (; CONSP (windows); windows = XCDR (windows))
2209 struct window *w;
2211 window = XCAR (windows);
2212 w = XWINDOW (window);
2214 /* Note that we do not pay attention here to whether the frame
2215 is visible, since Fwindow_list skips non-visible frames if
2216 that is desired, under the control of frame_arg. */
2217 if (!MINI_WINDOW_P (w)
2218 /* For UNSHOW_BUFFER, we must always consider all windows. */
2219 || type == UNSHOW_BUFFER
2220 || (mini && minibuf_level > 0))
2221 switch (type)
2223 case GET_BUFFER_WINDOW:
2224 if (EQ (w->buffer, obj)
2225 /* Don't find any minibuffer window
2226 except the one that is currently in use. */
2227 && (MINI_WINDOW_P (w)
2228 ? EQ (window, minibuf_window)
2229 : 1))
2231 if (NILP (best_window))
2232 best_window = window;
2233 else if (EQ (window, selected_window))
2234 /* Prefer to return selected-window. */
2235 RETURN_UNGCPRO (window);
2236 else if (EQ (Fwindow_frame (window), selected_frame))
2237 /* Prefer windows on the current frame. */
2238 best_window = window;
2240 break;
2242 case GET_LRU_WINDOW:
2243 /* `obj' is an integer encoding a bitvector.
2244 `obj & 1' means consider only full-width windows.
2245 `obj & 2' means consider also dedicated windows. */
2246 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2247 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2248 /* Minibuffer windows are always ignored. */
2249 || MINI_WINDOW_P (w))
2250 break;
2251 if (NILP (best_window)
2252 || (XFASTINT (XWINDOW (best_window)->use_time)
2253 > XFASTINT (w->use_time)))
2254 best_window = window;
2255 break;
2257 case DELETE_OTHER_WINDOWS:
2258 if (!EQ (window, obj))
2259 Fdelete_window (window);
2260 break;
2262 case DELETE_BUFFER_WINDOWS:
2263 if (EQ (w->buffer, obj))
2265 struct frame *f = XFRAME (WINDOW_FRAME (w));
2267 /* If this window is dedicated, and in a frame of its own,
2268 kill the frame. */
2269 if (EQ (window, FRAME_ROOT_WINDOW (f))
2270 && !NILP (w->dedicated)
2271 && other_visible_frames (f))
2273 /* Skip the other windows on this frame.
2274 There might be one, the minibuffer! */
2275 while (CONSP (XCDR (windows))
2276 && EQ (XWINDOW (XCAR (windows))->frame,
2277 XWINDOW (XCAR (XCDR (windows)))->frame))
2278 windows = XCDR (windows);
2280 /* Now we can safely delete the frame. */
2281 delete_frame (w->frame, Qnil);
2283 else if (NILP (w->parent))
2285 /* If we're deleting the buffer displayed in the
2286 only window on the frame, find a new buffer to
2287 display there. */
2288 Lisp_Object buffer;
2289 buffer = Fother_buffer (obj, Qnil, w->frame);
2290 /* Reset dedicated state of window. */
2291 w->dedicated = Qnil;
2292 Fset_window_buffer (window, buffer, Qnil);
2293 if (EQ (window, selected_window))
2294 Fset_buffer (w->buffer);
2296 else
2297 Fdelete_window (window);
2299 break;
2301 case GET_LARGEST_WINDOW:
2302 { /* nil `obj' means to ignore dedicated windows. */
2303 /* Ignore dedicated windows and minibuffers. */
2304 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2305 break;
2307 if (NILP (best_window))
2308 best_window = window;
2309 else
2311 struct window *b = XWINDOW (best_window);
2312 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2313 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2314 best_window = window;
2317 break;
2319 case UNSHOW_BUFFER:
2320 if (EQ (w->buffer, obj))
2322 Lisp_Object buffer;
2323 struct frame *f = XFRAME (w->frame);
2325 /* Find another buffer to show in this window. */
2326 buffer = Fother_buffer (obj, Qnil, w->frame);
2328 /* If this window is dedicated, and in a frame of its own,
2329 kill the frame. */
2330 if (EQ (window, FRAME_ROOT_WINDOW (f))
2331 && !NILP (w->dedicated)
2332 && other_visible_frames (f))
2334 /* Skip the other windows on this frame.
2335 There might be one, the minibuffer! */
2336 while (CONSP (XCDR (windows))
2337 && EQ (XWINDOW (XCAR (windows))->frame,
2338 XWINDOW (XCAR (XCDR (windows)))->frame))
2339 windows = XCDR (windows);
2341 /* Now we can safely delete the frame. */
2342 delete_frame (w->frame, Qnil);
2344 else if (!NILP (w->dedicated) && !NILP (w->parent))
2346 Lisp_Object window;
2347 XSETWINDOW (window, w);
2348 /* If this window is dedicated and not the only window
2349 in its frame, then kill it. */
2350 Fdelete_window (window);
2352 else
2354 /* Otherwise show a different buffer in the window. */
2355 w->dedicated = Qnil;
2356 Fset_window_buffer (window, buffer, Qnil);
2357 if (EQ (window, selected_window))
2358 Fset_buffer (w->buffer);
2361 break;
2363 case REDISPLAY_BUFFER_WINDOWS:
2364 if (EQ (w->buffer, obj))
2366 mark_window_display_accurate (window, 0);
2367 w->update_mode_line = Qt;
2368 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2369 ++update_mode_lines;
2370 best_window = window;
2372 break;
2374 /* Check for a window that has a killed buffer. */
2375 case CHECK_ALL_WINDOWS:
2376 if (! NILP (w->buffer)
2377 && NILP (XBUFFER (w->buffer)->name))
2378 abort ();
2379 break;
2381 case WINDOW_LOOP_UNUSED:
2382 break;
2386 UNGCPRO;
2387 return best_window;
2390 /* Used for debugging. Abort if any window has a dead buffer. */
2392 void
2393 check_all_windows (void)
2395 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2398 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
2399 doc: /* Return WINDOW's use time.
2400 WINDOW defaults to the selected window. The window with the highest use
2401 time is the most recently selected one. The window with the lowest use
2402 time is the least recently selected one. */)
2403 (Lisp_Object window)
2405 return decode_window (window)->use_time;
2408 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2409 doc: /* Return the window least recently selected or used for display.
2410 \(LRU means Least Recently Used.)
2412 Return a full-width window if possible.
2413 A minibuffer window is never a candidate.
2414 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2415 so if all windows are dedicated, the value is nil.
2416 If optional argument FRAME is `visible', search all visible frames.
2417 If FRAME is 0, search all visible and iconified frames.
2418 If FRAME is t, search all frames.
2419 If FRAME is nil, search only the selected frame.
2420 If FRAME is a frame, search only that frame. */)
2421 (Lisp_Object frame, Lisp_Object dedicated)
2423 register Lisp_Object w;
2424 /* First try for a window that is full-width */
2425 w = window_loop (GET_LRU_WINDOW,
2426 NILP (dedicated) ? make_number (1) : make_number (3),
2427 0, frame);
2428 if (!NILP (w) && !EQ (w, selected_window))
2429 return w;
2430 /* If none of them, try the rest */
2431 return window_loop (GET_LRU_WINDOW,
2432 NILP (dedicated) ? make_number (0) : make_number (2),
2433 0, frame);
2436 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2437 doc: /* Return the largest window in area.
2438 A minibuffer window is never a candidate.
2439 A dedicated window is never a candidate unless DEDICATED is non-nil,
2440 so if all windows are dedicated, the value is nil.
2441 If optional argument FRAME is `visible', search all visible frames.
2442 If FRAME is 0, search all visible and iconified frames.
2443 If FRAME is t, search all frames.
2444 If FRAME is nil, search only the selected frame.
2445 If FRAME is a frame, search only that frame. */)
2446 (Lisp_Object frame, Lisp_Object dedicated)
2448 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2449 frame);
2452 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2453 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2454 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
2455 current buffer.
2456 If optional argument FRAME is `visible', search all visible frames.
2457 If optional argument FRAME is 0, search all visible and iconified frames.
2458 If FRAME is t, search all frames.
2459 If FRAME is nil, search only the selected frame.
2460 If FRAME is a frame, search only that frame. */)
2461 (Lisp_Object buffer_or_name, Lisp_Object frame)
2463 Lisp_Object buffer;
2465 if (NILP (buffer_or_name))
2466 buffer = Fcurrent_buffer ();
2467 else
2468 buffer = Fget_buffer (buffer_or_name);
2470 if (BUFFERP (buffer))
2471 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2472 else
2473 return Qnil;
2476 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2477 0, 1, "",
2478 doc: /* Make WINDOW (or the selected window) fill its frame.
2479 Only the frame WINDOW is on is affected.
2480 This function tries to reduce display jumps by keeping the text
2481 previously visible in WINDOW in the same place on the frame. Doing this
2482 depends on the value of (window-start WINDOW), so if calling this
2483 function in a program gives strange scrolling, make sure the
2484 window-start value is reasonable when this function is called. */)
2485 (Lisp_Object window)
2487 struct window *w;
2488 EMACS_INT startpos;
2489 int top, new_top;
2491 if (NILP (window))
2492 window = selected_window;
2493 else
2494 CHECK_LIVE_WINDOW (window);
2495 w = XWINDOW (window);
2497 startpos = marker_position (w->start);
2498 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2500 if (MINI_WINDOW_P (w) && top > 0)
2501 error ("Can't expand minibuffer to full frame");
2503 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2505 /* Try to minimize scrolling, by setting the window start to the point
2506 will cause the text at the old window start to be at the same place
2507 on the frame. But don't try to do this if the window start is
2508 outside the visible portion (as might happen when the display is
2509 not current, due to typeahead). */
2510 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2511 if (new_top != top
2512 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2513 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2515 struct position pos;
2516 struct buffer *obuf = current_buffer;
2518 Fset_buffer (w->buffer);
2519 /* This computation used to temporarily move point, but that can
2520 have unwanted side effects due to text properties. */
2521 pos = *vmotion (startpos, -top, w);
2523 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2524 w->window_end_valid = Qnil;
2525 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2526 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2527 : Qnil);
2528 /* We need to do this, so that the window-scroll-functions
2529 get called. */
2530 w->optional_new_start = Qt;
2532 set_buffer_internal (obuf);
2535 return Qnil;
2538 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2539 0, 2, "bDelete windows on (buffer): ",
2540 doc: /* Delete all windows showing BUFFER-OR-NAME.
2541 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2542 defaults to the current buffer.
2544 Optional second argument FRAME controls which frames are affected.
2545 If optional argument FRAME is `visible', search all visible frames.
2546 If FRAME is 0, search all visible and iconified frames.
2547 If FRAME is nil, search all frames.
2548 If FRAME is t, search only the selected frame.
2549 If FRAME is a frame, search only that frame.
2550 When a window showing BUFFER-OR-NAME is dedicated and the only window of
2551 its frame, that frame is deleted when there are other frames left. */)
2552 (Lisp_Object buffer_or_name, Lisp_Object frame)
2554 Lisp_Object buffer;
2556 /* FRAME uses t and nil to mean the opposite of what window_loop
2557 expects. */
2558 if (NILP (frame))
2559 frame = Qt;
2560 else if (EQ (frame, Qt))
2561 frame = Qnil;
2563 if (NILP (buffer_or_name))
2564 buffer = Fcurrent_buffer ();
2565 else
2567 buffer = Fget_buffer (buffer_or_name);
2568 CHECK_BUFFER (buffer);
2571 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2573 return Qnil;
2576 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2577 Sreplace_buffer_in_windows,
2578 0, 1, "bReplace buffer in windows: ",
2579 doc: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2580 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2581 defaults to the current buffer.
2583 When a window showing BUFFER-OR-NAME is dedicated that window is
2584 deleted. If that window is the only window on its frame, that frame is
2585 deleted too when there are other frames left. If there are no other
2586 frames left, some other buffer is displayed in that window. */)
2587 (Lisp_Object buffer_or_name)
2589 Lisp_Object buffer;
2591 if (NILP (buffer_or_name))
2592 buffer = Fcurrent_buffer ();
2593 else
2595 buffer = Fget_buffer (buffer_or_name);
2596 CHECK_BUFFER (buffer);
2599 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2601 return Qnil;
2604 /* Replace BUFFER with some other buffer in all windows
2605 of all frames, even those on other keyboards. */
2607 void
2608 replace_buffer_in_all_windows (Lisp_Object buffer)
2610 Lisp_Object tail, frame;
2612 /* A single call to window_loop won't do the job
2613 because it only considers frames on the current keyboard.
2614 So loop manually over frames, and handle each one. */
2615 FOR_EACH_FRAME (tail, frame)
2616 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2619 /* Set the height of WINDOW and all its inferiors. */
2621 /* The smallest acceptable dimensions for a window. Anything smaller
2622 might crash Emacs. */
2624 #define MIN_SAFE_WINDOW_WIDTH (2)
2625 #define MIN_SAFE_WINDOW_HEIGHT (1)
2627 /* For wp non-zero the total number of columns of window w. Otherwise
2628 the total number of lines of w. */
2630 #define WINDOW_TOTAL_SIZE(w, wp) \
2631 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2633 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2634 minimum allowable size. */
2636 void
2637 check_frame_size (FRAME_PTR frame, int *rows, int *cols)
2639 /* For height, we have to see:
2640 how many windows the frame has at minimum (one or two),
2641 and whether it has a menu bar or other special stuff at the top. */
2642 int min_height
2643 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2644 ? MIN_SAFE_WINDOW_HEIGHT
2645 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2647 if (FRAME_TOP_MARGIN (frame) > 0)
2648 min_height += FRAME_TOP_MARGIN (frame);
2650 if (*rows < min_height)
2651 *rows = min_height;
2652 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2653 *cols = MIN_SAFE_WINDOW_WIDTH;
2656 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2657 check if W's width can be changed, otherwise check W's height.
2658 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2659 siblings, too. If none of the siblings is resizable, WINDOW isn't
2660 either. */
2662 static int
2663 window_fixed_size_p (struct window *w, int width_p, int check_siblings_p)
2665 int fixed_p;
2666 struct window *c;
2668 if (!NILP (w->hchild))
2670 c = XWINDOW (w->hchild);
2672 if (width_p)
2674 /* A horizontal combination is fixed-width if all of if its
2675 children are. */
2676 while (c && window_fixed_size_p (c, width_p, 0))
2677 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2678 fixed_p = c == NULL;
2680 else
2682 /* A horizontal combination is fixed-height if one of if its
2683 children is. */
2684 while (c && !window_fixed_size_p (c, width_p, 0))
2685 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2686 fixed_p = c != NULL;
2689 else if (!NILP (w->vchild))
2691 c = XWINDOW (w->vchild);
2693 if (width_p)
2695 /* A vertical combination is fixed-width if one of if its
2696 children is. */
2697 while (c && !window_fixed_size_p (c, width_p, 0))
2698 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2699 fixed_p = c != NULL;
2701 else
2703 /* A vertical combination is fixed-height if all of if its
2704 children are. */
2705 while (c && window_fixed_size_p (c, width_p, 0))
2706 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2707 fixed_p = c == NULL;
2710 else if (BUFFERP (w->buffer))
2712 struct buffer *old = current_buffer;
2713 Lisp_Object val;
2715 current_buffer = XBUFFER (w->buffer);
2716 val = find_symbol_value (Qwindow_size_fixed);
2717 current_buffer = old;
2719 fixed_p = 0;
2720 if (!EQ (val, Qunbound))
2722 fixed_p = !NILP (val);
2724 if (fixed_p
2725 && ((EQ (val, Qheight) && width_p)
2726 || (EQ (val, Qwidth) && !width_p)))
2727 fixed_p = 0;
2730 /* Can't tell if this one is resizable without looking at
2731 siblings. If all siblings are fixed-size this one is too. */
2732 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2734 Lisp_Object child;
2736 for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev)
2737 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2738 break;
2740 if (NILP (child))
2741 for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next)
2742 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2743 break;
2745 if (NILP (child))
2746 fixed_p = 1;
2749 else
2750 fixed_p = 1;
2752 return fixed_p;
2755 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2756 the minimum width of W, WIDTH_P zero means return the minimum height
2757 of W. SAFE_P non-zero means ignore window-min-height|width but just
2758 return values that won't crash Emacs and don't hide components like
2759 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2760 minibuffer window, always return 1. */
2762 static int
2763 window_min_size_2 (struct window *w, int width_p, int safe_p)
2765 /* We should consider buffer-local values of window_min_height and
2766 window_min_width here. */
2767 if (width_p)
2769 int safe_size = (MIN_SAFE_WINDOW_WIDTH
2770 + WINDOW_FRINGE_COLS (w)
2771 + WINDOW_SCROLL_BAR_COLS (w));
2773 return safe_p ? safe_size : max (window_min_width, safe_size);
2775 else if (MINI_WINDOW_P (w))
2776 return 1;
2777 else
2779 int safe_size = (MIN_SAFE_WINDOW_HEIGHT
2780 + ((BUFFERP (w->buffer)
2781 && !NILP (XBUFFER (w->buffer)->mode_line_format))
2782 ? 1 : 0));
2784 return safe_p ? safe_size : max (window_min_height, safe_size);
2788 /* Return minimum size of window W, not taking fixed-width windows into
2789 account. WIDTH_P non-zero means return the minimum width, otherwise
2790 return the minimum height. SAFE_P non-zero means ignore
2791 window-min-height|width but just return values that won't crash Emacs
2792 and don't hide components like fringes, scrollbars, or modelines. If
2793 W is a combination window, compute the minimum size from the minimum
2794 sizes of W's children. */
2796 static int
2797 window_min_size_1 (struct window *w, int width_p, int safe_p)
2799 struct window *c;
2800 int size;
2802 if (!NILP (w->hchild))
2804 /* W is a horizontal combination. */
2805 c = XWINDOW (w->hchild);
2806 size = 0;
2808 if (width_p)
2810 /* The minimum width of a horizontal combination is the sum of
2811 the minimum widths of its children. */
2812 while (c)
2814 size += window_min_size_1 (c, 1, safe_p);
2815 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2818 else
2820 /* The minimum height of a horizontal combination is the
2821 maximum of the minimum heights of its children. */
2822 while (c)
2824 size = max (window_min_size_1 (c, 0, safe_p), size);
2825 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2829 else if (!NILP (w->vchild))
2831 /* W is a vertical combination. */
2832 c = XWINDOW (w->vchild);
2833 size = 0;
2835 if (width_p)
2837 /* The minimum width of a vertical combination is the maximum
2838 of the minimum widths of its children. */
2839 while (c)
2841 size = max (window_min_size_1 (c, 1, safe_p), size);
2842 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2845 else
2847 /* The minimum height of a vertical combination is the sum of
2848 the minimum height of its children. */
2849 while (c)
2851 size += window_min_size_1 (c, 0, safe_p);
2852 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2856 else
2857 /* W is a leaf window. */
2858 size = window_min_size_2 (w, width_p, safe_p);
2860 return size;
2863 /* Return the minimum size of window W, taking fixed-size windows into
2864 account. WIDTH_P non-zero means return the minimum width, otherwise
2865 return the minimum height. SAFE_P non-zero means ignore
2866 window-min-height|width but just return values that won't crash Emacs
2867 and don't hide components like fringes, scrollbars, or modelines.
2868 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2869 to 1 if W is fixed-size unless FIXED is null. */
2871 static int
2872 window_min_size (struct window *w, int width_p, int safe_p, int ignore_fixed_p, int *fixed)
2874 int size, fixed_p;
2876 if (ignore_fixed_p)
2877 fixed_p = 0;
2878 else
2879 fixed_p = window_fixed_size_p (w, width_p, 1);
2881 if (fixed)
2882 *fixed = fixed_p;
2884 if (fixed_p)
2885 size = WINDOW_TOTAL_SIZE (w, width_p);
2886 else
2887 size = window_min_size_1 (w, width_p, safe_p);
2889 return size;
2893 /* Adjust the margins of window W if text area is too small.
2894 Return 1 if window width is ok after adjustment; 0 if window
2895 is still too narrow. */
2897 static int
2898 adjust_window_margins (struct window *w)
2900 int box_cols = (WINDOW_TOTAL_COLS (w)
2901 - WINDOW_FRINGE_COLS (w)
2902 - WINDOW_SCROLL_BAR_COLS (w));
2903 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2904 + WINDOW_RIGHT_MARGIN_COLS (w));
2906 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2907 return 1;
2909 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2910 return 0;
2912 /* Window's text area is too narrow, but reducing the window
2913 margins will fix that. */
2914 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2915 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2917 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2918 w->left_margin_cols = w->right_margin_cols
2919 = make_number (margin_cols/2);
2920 else
2921 w->right_margin_cols = make_number (margin_cols);
2923 else
2924 w->left_margin_cols = make_number (margin_cols);
2925 return 1;
2928 /* Calculate new sizes for windows in the list FORWARD when their
2929 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2930 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2931 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2932 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2933 shrink columns, otherwise shrink lines.
2935 SAFE_P zero means windows may be sized down to window-min-height
2936 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2937 non-zero means windows may be sized down to their minimum safe sizes
2938 taking into account the space needed to display modelines, fringes,
2939 and scrollbars.
2941 This function returns an allocated array of new sizes that the caller
2942 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2943 zero. A size zero means the window shall be deleted. Array index 0
2944 refers to the first window in FORWARD, 1 to the second, and so on.
2946 This function resizes windows proportionally to their size. It also
2947 tries to preserve smaller windows by resizing larger windows before
2948 resizing any window to zero. If resize_proportionally is non-nil for
2949 a specific window, it will attempt to strictly resize that window
2950 proportionally, even at the expense of deleting smaller windows. */
2951 static int *
2952 shrink_windows (int total, int size, int nchildren, int shrinkable,
2953 int resize_fixed_p, Lisp_Object forward, int width_p, int safe_p)
2955 int available_resize = 0;
2956 int *new_sizes, *min_sizes;
2957 struct window *c;
2958 Lisp_Object child;
2959 int smallest = total;
2960 int total_removed = 0;
2961 int total_shrink = total - size;
2962 int i;
2964 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2965 min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
2967 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2969 int child_size;
2971 c = XWINDOW (child);
2972 child_size = WINDOW_TOTAL_SIZE (c, width_p);
2974 if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2975 new_sizes[i] = -1;
2976 else
2978 new_sizes[i] = child_size;
2979 min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
2980 if (child_size > min_sizes[i]
2981 && NILP (c->resize_proportionally))
2982 available_resize += child_size - min_sizes[i];
2985 /* We might need to shrink some windows to zero. Find the smallest
2986 windows and set them to 0 until we can fulfil the new size. */
2988 while (shrinkable > 1 && size + available_resize < total)
2990 for (i = 0; i < nchildren; ++i)
2991 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2992 smallest = new_sizes[i];
2994 for (i = 0; i < nchildren; ++i)
2995 if (new_sizes[i] == smallest)
2997 /* Resize this window down to zero. */
2998 new_sizes[i] = 0;
2999 if (smallest > min_sizes[i])
3000 available_resize -= smallest - min_sizes[i];
3001 available_resize += smallest;
3002 --shrinkable;
3003 total_removed += smallest;
3005 /* We don't know what the smallest is now. */
3006 smallest = total;
3008 /* Out of for, just remove one window at the time and
3009 check again if we have enough space. */
3010 break;
3014 /* Now, calculate the new sizes. Try to shrink each window
3015 proportional to its size. */
3016 for (i = 0; i < nchildren; ++i)
3018 if (new_sizes[i] > min_sizes[i])
3020 int to_shrink = total_shrink * new_sizes[i] / total;
3022 if (new_sizes[i] - to_shrink < min_sizes[i])
3023 to_shrink = new_sizes[i] - min_sizes[i];
3024 new_sizes[i] -= to_shrink;
3025 total_removed += to_shrink;
3029 /* Any reminder due to rounding, we just subtract from windows
3030 that are left and still can be shrunk. */
3031 while (total_shrink > total_removed)
3033 int nonzero_sizes = 0;
3034 int nonzero_idx = -1;
3036 for (i = 0; i < nchildren; ++i)
3037 if (new_sizes[i] > 0)
3039 ++nonzero_sizes;
3040 nonzero_idx = i;
3043 for (i = 0; i < nchildren; ++i)
3044 if (new_sizes[i] > min_sizes[i])
3046 --new_sizes[i];
3047 ++total_removed;
3049 /* Out of for, just shrink one window at the time and
3050 check again if we have enough space. */
3051 break;
3054 /* Special case, only one window left. */
3055 if (nonzero_sizes == 1)
3056 break;
3059 /* Any surplus due to rounding, we add to windows that are left. */
3060 while (total_shrink < total_removed)
3062 for (i = 0; i < nchildren; ++i)
3064 if (new_sizes[i] != 0 && total_shrink < total_removed)
3066 ++new_sizes[i];
3067 --total_removed;
3068 break;
3073 xfree (min_sizes);
3075 return new_sizes;
3078 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3079 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3080 their proportionate size relative to WINDOW.
3082 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3083 they are in series. If LAST_ONLY is 1, change only the last of
3084 WINDOW's children when they are in series.
3086 Propagate WINDOW's top or left edge position to children. Delete
3087 windows that become too small unless NODELETE_P is 1. When
3088 NODELETE_P equals 2 do not honor settings for window-min-height and
3089 window-min-width when resizing windows but use safe defaults instead.
3090 This should give better behavior when resizing frames. */
3092 static void
3093 size_window (Lisp_Object window, int size, int width_p, int nodelete_p, int first_only, int last_only)
3095 struct window *w = XWINDOW (window);
3096 struct window *c;
3097 Lisp_Object child, *forward, *sideward;
3098 int old_size = WINDOW_TOTAL_SIZE (w, width_p);
3100 size = max (0, size);
3102 /* Delete WINDOW if it's too small. */
3103 if (nodelete_p != 1 && !NILP (w->parent)
3104 && size < window_min_size_1 (w, width_p, nodelete_p == 2))
3106 delete_window (window);
3107 return;
3110 /* Set redisplay hints. */
3111 w->last_modified = make_number (0);
3112 w->last_overlay_modified = make_number (0);
3113 windows_or_buffers_changed++;
3114 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3116 if (width_p)
3118 sideward = &w->vchild;
3119 forward = &w->hchild;
3120 w->total_cols = make_number (size);
3121 adjust_window_margins (w);
3123 else
3125 sideward = &w->hchild;
3126 forward = &w->vchild;
3127 w->total_lines = make_number (size);
3128 w->orig_total_lines = Qnil;
3131 if (!NILP (*sideward))
3133 /* We have a chain of parallel siblings whose size should all change. */
3134 for (child = *sideward; !NILP (child); child = c->next)
3136 c = XWINDOW (child);
3137 if (width_p)
3138 c->left_col = w->left_col;
3139 else
3140 c->top_line = w->top_line;
3141 size_window (child, size, width_p, nodelete_p,
3142 first_only, last_only);
3145 else if (!NILP (*forward) && last_only)
3147 /* Change the last in a series of siblings. */
3148 Lisp_Object last_child;
3149 int child_size;
3151 for (child = *forward; !NILP (child); child = c->next)
3153 c = XWINDOW (child);
3154 last_child = child;
3157 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3158 size_window (last_child, size - old_size + child_size,
3159 width_p, nodelete_p, first_only, last_only);
3161 else if (!NILP (*forward) && first_only)
3163 /* Change the first in a series of siblings. */
3164 int child_size;
3166 child = *forward;
3167 c = XWINDOW (child);
3169 if (width_p)
3170 c->left_col = w->left_col;
3171 else
3172 c->top_line = w->top_line;
3174 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3175 size_window (child, size - old_size + child_size,
3176 width_p, nodelete_p, first_only, last_only);
3178 else if (!NILP (*forward))
3180 int fixed_size, each, extra, n;
3181 int resize_fixed_p, nfixed;
3182 int last_pos, first_pos, nchildren, total;
3183 int *new_sizes = NULL;
3185 /* Determine the fixed-size portion of this window, and the
3186 number of child windows. */
3187 fixed_size = nchildren = nfixed = total = 0;
3188 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3190 int child_size;
3192 c = XWINDOW (child);
3193 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3194 total += child_size;
3196 if (window_fixed_size_p (c, width_p, 0))
3198 fixed_size += child_size;
3199 ++nfixed;
3203 /* If the new size is smaller than fixed_size, or if there
3204 aren't any resizable windows, allow resizing fixed-size
3205 windows. */
3206 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3208 /* Compute how many lines/columns to add/remove to each child. The
3209 value of extra takes care of rounding errors. */
3210 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3211 if (size < total && n > 1)
3212 new_sizes = shrink_windows (total, size, nchildren, n,
3213 resize_fixed_p, *forward, width_p,
3214 nodelete_p == 2);
3215 else
3217 each = (size - total) / n;
3218 extra = (size - total) - n * each;
3221 /* Compute new children heights and edge positions. */
3222 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3223 last_pos = first_pos;
3224 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3226 int new_size, old_size;
3228 c = XWINDOW (child);
3229 old_size = WINDOW_TOTAL_SIZE (c, width_p);
3230 new_size = old_size;
3232 /* The top or left edge position of this child equals the
3233 bottom or right edge of its predecessor. */
3234 if (width_p)
3235 c->left_col = make_number (last_pos);
3236 else
3237 c->top_line = make_number (last_pos);
3239 /* If this child can be resized, do it. */
3240 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3242 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3243 extra = 0;
3246 /* Set new size. Note that size_window also propagates
3247 edge positions to children, so it's not a no-op if we
3248 didn't change the child's size. */
3249 size_window (child, new_size, width_p, 1, first_only, last_only);
3251 /* Remember the bottom/right edge position of this child; it
3252 will be used to set the top/left edge of the next child. */
3253 last_pos += new_size;
3256 xfree (new_sizes);
3258 /* We should have covered the parent exactly with child windows. */
3259 xassert (size == last_pos - first_pos);
3261 /* Now delete any children that became too small. */
3262 if (nodelete_p != 1)
3263 for (child = *forward; !NILP (child); child = c->next)
3265 int child_size;
3267 c = XWINDOW (child);
3268 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3269 size_window (child, child_size, width_p, nodelete_p,
3270 first_only, last_only);
3275 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3276 WINDOW's children. NODELETE zero means windows that have become
3277 smaller than window-min-height in the process may be deleted.
3278 NODELETE 1 means never delete windows that become too small in the
3279 process. (The caller should check later and do so if appropriate.)
3280 NODELETE 2 means delete only windows that have become too small to be
3281 displayed correctly. */
3283 void
3284 set_window_height (Lisp_Object window, int height, int nodelete)
3286 size_window (window, height, 0, nodelete, 0, 0);
3289 /* Set WINDOW's width to WIDTH, and recursively change the width of
3290 WINDOW's children. NODELETE zero means windows that have become
3291 smaller than window-min-width in the process may be deleted.
3292 NODELETE 1 means never delete windows that become too small in the
3293 process. (The caller should check later and do so if appropriate.)
3294 NODELETE 2 means delete only windows that have become too small to be
3295 displayed correctly. */
3297 void
3298 set_window_width (Lisp_Object window, int width, int nodelete)
3300 size_window (window, width, 1, nodelete, 0, 0);
3303 /* Change window heights in windows rooted in WINDOW by N lines. */
3305 void
3306 change_window_heights (Lisp_Object window, int n)
3308 struct window *w = XWINDOW (window);
3310 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3311 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3313 if (INTEGERP (w->orig_top_line))
3314 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3315 if (INTEGERP (w->orig_total_lines))
3316 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3318 /* Handle just the top child in a vertical split. */
3319 if (!NILP (w->vchild))
3320 change_window_heights (w->vchild, n);
3322 /* Adjust all children in a horizontal split. */
3323 for (window = w->hchild; !NILP (window); window = w->next)
3325 w = XWINDOW (window);
3326 change_window_heights (window, n);
3331 int window_select_count;
3333 EXFUN (Fset_window_fringes, 4);
3334 EXFUN (Fset_window_scroll_bars, 4);
3336 static void
3337 run_funs (Lisp_Object funs)
3339 for (; CONSP (funs); funs = XCDR (funs))
3340 if (!EQ (XCAR (funs), Qt))
3341 call0 (XCAR (funs));
3344 static Lisp_Object select_window_norecord (Lisp_Object window);
3345 static Lisp_Object select_frame_norecord (Lisp_Object frame);
3347 void
3348 run_window_configuration_change_hook (struct frame *f)
3350 int count = SPECPDL_INDEX ();
3351 Lisp_Object frame, global_wcch
3352 = Fdefault_value (Qwindow_configuration_change_hook);
3353 XSETFRAME (frame, f);
3355 if (NILP (Vrun_hooks))
3356 return;
3358 if (SELECTED_FRAME () != f)
3360 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3361 Fselect_frame (frame, Qt);
3364 /* Use the right buffer. Matters when running the local hooks. */
3365 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3367 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3368 Fset_buffer (Fwindow_buffer (Qnil));
3371 /* Look for buffer-local values. */
3373 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3374 for (; CONSP (windows); windows = XCDR (windows))
3376 Lisp_Object window = XCAR (windows);
3377 Lisp_Object buffer = Fwindow_buffer (window);
3378 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3379 buffer)))
3381 int count = SPECPDL_INDEX ();
3382 record_unwind_protect (select_window_norecord, Fselected_window ());
3383 select_window_norecord (window);
3384 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3385 buffer));
3386 unbind_to (count, Qnil);
3391 run_funs (global_wcch);
3392 unbind_to (count, Qnil);
3395 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3396 means it's allowed to run hooks. See make_frame for a case where
3397 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3398 margins, fringes, and scroll-bar settings of the window are not
3399 reset from the buffer's local settings. */
3401 void
3402 set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
3404 struct window *w = XWINDOW (window);
3405 struct buffer *b = XBUFFER (buffer);
3406 int count = SPECPDL_INDEX ();
3407 int samebuf = EQ (buffer, w->buffer);
3409 w->buffer = buffer;
3411 if (EQ (window, selected_window))
3412 b->last_selected_window = window;
3414 /* Let redisplay errors through. */
3415 b->display_error_modiff = 0;
3417 /* Update time stamps of buffer display. */
3418 if (INTEGERP (b->display_count))
3419 XSETINT (b->display_count, XINT (b->display_count) + 1);
3420 b->display_time = Fcurrent_time ();
3422 XSETFASTINT (w->window_end_pos, 0);
3423 XSETFASTINT (w->window_end_vpos, 0);
3424 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3425 w->window_end_valid = Qnil;
3426 if (!(keep_margins_p && samebuf))
3427 { /* If we're not actually changing the buffer, don't reset hscroll and
3428 vscroll. This case happens for example when called from
3429 change_frame_size_1, where we use a dummy call to
3430 Fset_window_buffer on the frame's selected window (and no other)
3431 just in order to run window-configuration-change-hook.
3432 Resetting hscroll and vscroll here is problematic for things like
3433 image-mode and doc-view-mode since it resets the image's position
3434 whenever we resize the frame. */
3435 w->hscroll = w->min_hscroll = make_number (0);
3436 w->vscroll = 0;
3437 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3438 set_marker_restricted (w->start,
3439 make_number (b->last_window_start),
3440 buffer);
3441 w->start_at_line_beg = Qnil;
3442 w->force_start = Qnil;
3443 XSETFASTINT (w->last_modified, 0);
3444 XSETFASTINT (w->last_overlay_modified, 0);
3446 /* Maybe we could move this into the `if' but it's not obviously safe and
3447 I doubt it's worth the trouble. */
3448 windows_or_buffers_changed++;
3450 /* We must select BUFFER for running the window-scroll-functions. */
3451 /* We can't check ! NILP (Vwindow_scroll_functions) here
3452 because that might itself be a local variable. */
3453 if (window_initialized)
3455 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3456 Fset_buffer (buffer);
3459 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3461 if (!keep_margins_p)
3463 /* Set left and right marginal area width etc. from buffer. */
3465 /* This may call adjust_window_margins three times, so
3466 temporarily disable window margins. */
3467 Lisp_Object save_left = w->left_margin_cols;
3468 Lisp_Object save_right = w->right_margin_cols;
3470 w->left_margin_cols = w->right_margin_cols = Qnil;
3472 Fset_window_fringes (window,
3473 b->left_fringe_width, b->right_fringe_width,
3474 b->fringes_outside_margins);
3476 Fset_window_scroll_bars (window,
3477 b->scroll_bar_width,
3478 b->vertical_scroll_bar_type, Qnil);
3480 w->left_margin_cols = save_left;
3481 w->right_margin_cols = save_right;
3483 Fset_window_margins (window,
3484 b->left_margin_cols, b->right_margin_cols);
3487 if (run_hooks_p)
3489 if (! NILP (Vwindow_scroll_functions))
3490 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3491 Fmarker_position (w->start));
3492 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3495 unbind_to (count, Qnil);
3499 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3500 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3501 WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
3502 or the name of an existing buffer. Optional third argument KEEP-MARGINS
3503 non-nil means that WINDOW's current display margins, fringe widths, and
3504 scroll bar settings are preserved; the default is to reset these from
3505 the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
3507 This function throws an error when WINDOW is strongly dedicated to its
3508 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3509 already display BUFFER-OR-NAME.
3511 This function runs `window-scroll-functions' before running
3512 `window-configuration-change-hook'. */)
3513 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3515 register Lisp_Object tem, buffer;
3516 register struct window *w = decode_window (window);
3518 XSETWINDOW (window, w);
3519 buffer = Fget_buffer (buffer_or_name);
3520 CHECK_BUFFER (buffer);
3521 if (NILP (XBUFFER (buffer)->name))
3522 error ("Attempt to display deleted buffer");
3524 tem = w->buffer;
3525 if (NILP (tem))
3526 error ("Window is deleted");
3527 else if (!EQ (tem, Qt))
3528 /* w->buffer is t when the window is first being set up. */
3530 if (EQ (tem, buffer))
3531 return Qnil;
3532 else if (EQ (w->dedicated, Qt))
3533 error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem)->name));
3534 else
3535 w->dedicated = Qnil;
3537 unshow_buffer (w);
3540 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3541 return Qnil;
3544 /* Note that selected_window can be nil when this is called from
3545 Fset_window_configuration. */
3547 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3548 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3549 If WINDOW is not already selected, make WINDOW's buffer current
3550 and make WINDOW the frame's selected window. Return WINDOW.
3551 Optional second arg NORECORD non-nil means do not put this buffer
3552 at the front of the list of recently selected ones and do not
3553 make this window the most recently selected one.
3555 Note that the main editor command loop selects the buffer of the
3556 selected window before each command. */)
3557 (register Lisp_Object window, Lisp_Object norecord)
3559 register struct window *w;
3560 register struct window *ow;
3561 struct frame *sf;
3563 CHECK_LIVE_WINDOW (window);
3565 w = XWINDOW (window);
3566 w->frozen_window_start_p = 0;
3568 if (NILP (norecord))
3570 ++window_select_count;
3571 XSETFASTINT (w->use_time, window_select_count);
3572 record_buffer (w->buffer);
3575 if (EQ (window, selected_window))
3576 return window;
3578 sf = SELECTED_FRAME ();
3579 if (XFRAME (WINDOW_FRAME (w)) != sf)
3581 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3582 /* Use this rather than Fhandle_switch_frame
3583 so that FRAME_FOCUS_FRAME is moved appropriately as we
3584 move around in the state where a minibuffer in a separate
3585 frame is active. */
3586 Fselect_frame (WINDOW_FRAME (w), norecord);
3587 /* Fselect_frame called us back so we've done all the work already. */
3588 eassert (EQ (window, selected_window));
3589 return window;
3591 else
3592 sf->selected_window = window;
3594 /* Store the current buffer's actual point into the
3595 old selected window. It belongs to that window,
3596 and when the window is not selected, must be in the window. */
3597 if (!NILP (selected_window))
3599 ow = XWINDOW (selected_window);
3600 if (! NILP (ow->buffer))
3601 set_marker_both (ow->pointm, ow->buffer,
3602 BUF_PT (XBUFFER (ow->buffer)),
3603 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3606 selected_window = window;
3608 Fset_buffer (w->buffer);
3610 XBUFFER (w->buffer)->last_selected_window = window;
3612 /* Go to the point recorded in the window.
3613 This is important when the buffer is in more
3614 than one window. It also matters when
3615 redisplay_window has altered point after scrolling,
3616 because it makes the change only in the window. */
3618 register EMACS_INT new_point = marker_position (w->pointm);
3619 if (new_point < BEGV)
3620 SET_PT (BEGV);
3621 else if (new_point > ZV)
3622 SET_PT (ZV);
3623 else
3624 SET_PT (new_point);
3627 windows_or_buffers_changed++;
3628 return window;
3631 static Lisp_Object
3632 select_window_norecord (Lisp_Object window)
3634 return WINDOW_LIVE_P (window)
3635 ? Fselect_window (window, Qt) : selected_window;
3638 static Lisp_Object
3639 select_frame_norecord (Lisp_Object frame)
3641 return FRAME_LIVE_P (XFRAME (frame))
3642 ? Fselect_frame (frame, Qt) : selected_frame;
3645 Lisp_Object
3646 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3648 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3651 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3652 0, 1, 0,
3653 doc: /* Force all windows to be updated on next redisplay.
3654 If optional arg OBJECT is a window, force redisplay of that window only.
3655 If OBJECT is a buffer or buffer name, force redisplay of all windows
3656 displaying that buffer. */)
3657 (Lisp_Object object)
3659 if (NILP (object))
3661 windows_or_buffers_changed++;
3662 update_mode_lines++;
3663 return Qt;
3666 if (WINDOWP (object))
3668 struct window *w = XWINDOW (object);
3669 mark_window_display_accurate (object, 0);
3670 w->update_mode_line = Qt;
3671 if (BUFFERP (w->buffer))
3672 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3673 ++update_mode_lines;
3674 return Qt;
3677 if (STRINGP (object))
3678 object = Fget_buffer (object);
3679 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3681 /* Walk all windows looking for buffer, and force update
3682 of each of those windows. */
3684 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3685 return NILP (object) ? Qnil : Qt;
3688 /* If nothing suitable was found, just return.
3689 We could signal an error, but this feature will typically be used
3690 asynchronously in timers or process sentinels, so we don't. */
3691 return Qnil;
3695 void
3696 temp_output_buffer_show (register Lisp_Object buf)
3698 register struct buffer *old = current_buffer;
3699 register Lisp_Object window;
3700 register struct window *w;
3702 XBUFFER (buf)->directory = current_buffer->directory;
3704 Fset_buffer (buf);
3705 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3706 BEGV = BEG;
3707 ZV = Z;
3708 SET_PT (BEG);
3709 #if 0 /* rms: there should be no reason for this. */
3710 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3711 #endif
3712 set_buffer_internal (old);
3714 if (!NILP (Vtemp_buffer_show_function))
3715 call1 (Vtemp_buffer_show_function, buf);
3716 else
3718 window = display_buffer (buf, Qnil, Qnil);
3720 if (!EQ (XWINDOW (window)->frame, selected_frame))
3721 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3722 Vminibuf_scroll_window = window;
3723 w = XWINDOW (window);
3724 XSETFASTINT (w->hscroll, 0);
3725 XSETFASTINT (w->min_hscroll, 0);
3726 set_marker_restricted_both (w->start, buf, BEG, BEG);
3727 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3729 /* Run temp-buffer-show-hook, with the chosen window selected
3730 and its buffer current. */
3732 if (!NILP (Vrun_hooks)
3733 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3734 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3736 int count = SPECPDL_INDEX ();
3737 Lisp_Object prev_window, prev_buffer;
3738 prev_window = selected_window;
3739 XSETBUFFER (prev_buffer, old);
3741 /* Select the window that was chosen, for running the hook.
3742 Note: Both Fselect_window and select_window_norecord may
3743 set-buffer to the buffer displayed in the window,
3744 so we need to save the current buffer. --stef */
3745 record_unwind_protect (Fset_buffer, prev_buffer);
3746 record_unwind_protect (select_window_norecord, prev_window);
3747 Fselect_window (window, Qt);
3748 Fset_buffer (w->buffer);
3749 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3750 unbind_to (count, Qnil);
3755 static void
3756 make_dummy_parent (Lisp_Object window)
3758 Lisp_Object new;
3759 register struct window *o, *p;
3760 int i;
3762 o = XWINDOW (window);
3763 p = allocate_window ();
3764 for (i = 0; i < VECSIZE (struct window); ++i)
3765 ((struct Lisp_Vector *) p)->contents[i]
3766 = ((struct Lisp_Vector *)o)->contents[i];
3767 XSETWINDOW (new, p);
3769 ++sequence_number;
3770 XSETFASTINT (p->sequence_number, sequence_number);
3772 /* Put new into window structure in place of window */
3773 replace_window (window, new);
3775 o->next = Qnil;
3776 o->prev = Qnil;
3777 o->vchild = Qnil;
3778 o->hchild = Qnil;
3779 o->parent = new;
3781 p->start = Qnil;
3782 p->pointm = Qnil;
3783 p->buffer = Qnil;
3786 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3787 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3788 WINDOW defaults to selected one and SIZE to half its size.
3789 If optional third arg HORIZONTAL is non-nil, split side by side and put
3790 SIZE columns in the first of the pair. In that case, SIZE includes that
3791 window's scroll bar, or the divider column to its right.
3792 Interactively, all arguments are nil.
3793 Returns the newly created window (which is the lower or rightmost one).
3794 The upper or leftmost window is the original one, and remains selected
3795 if it was selected before.
3797 See Info node `(elisp)Splitting Windows' for more details and examples. */)
3798 (Lisp_Object window, Lisp_Object size, Lisp_Object horizontal)
3800 register Lisp_Object new;
3801 register struct window *o, *p;
3802 FRAME_PTR fo;
3803 register int size_int;
3805 if (NILP (window))
3806 window = selected_window;
3807 else
3808 CHECK_LIVE_WINDOW (window);
3810 o = XWINDOW (window);
3811 fo = XFRAME (WINDOW_FRAME (o));
3813 if (NILP (size))
3815 if (!NILP (horizontal))
3816 /* Calculate the size of the left-hand window, by dividing
3817 the usable space in columns by two.
3818 We round up, since the left-hand window may include
3819 a dividing line, while the right-hand may not. */
3820 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3821 else
3822 size_int = XFASTINT (o->total_lines) >> 1;
3824 else
3826 CHECK_NUMBER (size);
3827 size_int = XINT (size);
3830 if (MINI_WINDOW_P (o))
3831 error ("Attempt to split minibuffer window");
3832 else if (window_fixed_size_p (o, !NILP (horizontal), 0))
3833 error ("Attempt to split fixed-size window");
3835 if (NILP (horizontal))
3837 int window_safe_height = window_min_size_2 (o, 0, 0);
3839 if (size_int < window_safe_height)
3840 error ("Window height %d too small (after splitting)", size_int);
3841 if (size_int + window_safe_height > XFASTINT (o->total_lines))
3842 error ("Window height %d too small (after splitting)",
3843 XFASTINT (o->total_lines) - size_int);
3844 if (NILP (o->parent)
3845 || NILP (XWINDOW (o->parent)->vchild))
3847 make_dummy_parent (window);
3848 new = o->parent;
3849 XWINDOW (new)->vchild = window;
3852 else
3854 int window_safe_width = window_min_size_2 (o, 1, 0);
3856 if (size_int < window_safe_width)
3857 error ("Window width %d too small (after splitting)", size_int);
3858 if (size_int + window_safe_width > XFASTINT (o->total_cols))
3859 error ("Window width %d too small (after splitting)",
3860 XFASTINT (o->total_cols) - size_int);
3861 if (NILP (o->parent)
3862 || NILP (XWINDOW (o->parent)->hchild))
3864 make_dummy_parent (window);
3865 new = o->parent;
3866 XWINDOW (new)->hchild = window;
3870 /* Now we know that window's parent is a vertical combination
3871 if we are dividing vertically, or a horizontal combination
3872 if we are making side-by-side windows */
3874 windows_or_buffers_changed++;
3875 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3876 new = make_window ();
3877 p = XWINDOW (new);
3879 p->frame = o->frame;
3880 p->next = o->next;
3881 if (!NILP (p->next))
3882 XWINDOW (p->next)->prev = new;
3883 p->prev = window;
3884 o->next = new;
3885 p->parent = o->parent;
3886 p->buffer = Qt;
3887 p->window_end_valid = Qnil;
3888 memset (&p->last_cursor, 0, sizeof p->last_cursor);
3890 /* Duplicate special geometry settings. */
3892 p->left_margin_cols = o->left_margin_cols;
3893 p->right_margin_cols = o->right_margin_cols;
3894 p->left_fringe_width = o->left_fringe_width;
3895 p->right_fringe_width = o->right_fringe_width;
3896 p->fringes_outside_margins = o->fringes_outside_margins;
3897 p->scroll_bar_width = o->scroll_bar_width;
3898 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3900 /* Apportion the available frame space among the two new windows */
3902 if (!NILP (horizontal))
3904 p->total_lines = o->total_lines;
3905 p->top_line = o->top_line;
3906 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3907 XSETFASTINT (o->total_cols, size_int);
3908 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3909 adjust_window_margins (p);
3910 adjust_window_margins (o);
3912 else
3914 p->left_col = o->left_col;
3915 p->total_cols = o->total_cols;
3916 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3917 XSETFASTINT (o->total_lines, size_int);
3918 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3921 /* Adjust glyph matrices. */
3922 adjust_glyphs (fo);
3924 Fset_window_buffer (new, o->buffer, Qt);
3925 return new;
3928 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3929 doc: /* Make selected window SIZE lines taller.
3930 Interactively, if no argument is given, make the selected window one
3931 line taller. If optional argument HORIZONTAL is non-nil, make selected
3932 window wider by SIZE columns. If SIZE is negative, shrink the window by
3933 -SIZE lines or columns. Return nil.
3935 This function can delete windows if they get too small. The size of
3936 fixed size windows is not altered by this function. */)
3937 (Lisp_Object size, Lisp_Object horizontal)
3939 CHECK_NUMBER (size);
3940 enlarge_window (selected_window, XINT (size), !NILP (horizontal));
3942 run_window_configuration_change_hook (SELECTED_FRAME ());
3944 return Qnil;
3947 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3948 doc: /* Make selected window SIZE lines smaller.
3949 Interactively, if no argument is given, make the selected window one
3950 line smaller. If optional argument HORIZONTAL is non-nil, make the
3951 window narrower by SIZE columns. If SIZE is negative, enlarge selected
3952 window by -SIZE lines or columns. Return nil.
3954 This function can delete windows if they get too small. The size of
3955 fixed size windows is not altered by this function. */)
3956 (Lisp_Object size, Lisp_Object horizontal)
3958 CHECK_NUMBER (size);
3959 enlarge_window (selected_window, -XINT (size), !NILP (horizontal));
3961 run_window_configuration_change_hook (SELECTED_FRAME ());
3963 return Qnil;
3966 static int
3967 window_height (Lisp_Object window)
3969 register struct window *p = XWINDOW (window);
3970 return WINDOW_TOTAL_LINES (p);
3973 static int
3974 window_width (Lisp_Object window)
3976 register struct window *p = XWINDOW (window);
3977 return WINDOW_TOTAL_COLS (p);
3981 #define CURBEG(w) \
3982 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3984 #define CURSIZE(w) \
3985 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3988 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
3989 horizontally; zero means do it vertically.
3991 Siblings of the selected window are resized to fulfill the size
3992 request. If they become too small in the process, they may be
3993 deleted. */
3995 static void
3996 enlarge_window (Lisp_Object window, int delta, int horiz_flag)
3998 Lisp_Object parent, next, prev;
3999 struct window *p;
4000 Lisp_Object *sizep;
4001 int maximum;
4002 int (*sizefun) (Lisp_Object)
4003 = horiz_flag ? window_width : window_height;
4004 void (*setsizefun) (Lisp_Object, int, int)
4005 = (horiz_flag ? set_window_width : set_window_height);
4007 /* Give up if this window cannot be resized. */
4008 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4009 error ("Window is not resizable");
4011 /* Find the parent of the selected window. */
4012 while (1)
4014 p = XWINDOW (window);
4015 parent = p->parent;
4017 if (NILP (parent))
4019 if (horiz_flag)
4020 error ("No other window to side of this one");
4021 break;
4024 if (horiz_flag
4025 ? !NILP (XWINDOW (parent)->hchild)
4026 : !NILP (XWINDOW (parent)->vchild))
4027 break;
4029 window = parent;
4032 sizep = &CURSIZE (window);
4035 register int maxdelta;
4037 /* Compute the maximum size increment this window can have. */
4039 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4040 /* This is a main window followed by a minibuffer. */
4041 : !NILP (p->next) ? ((*sizefun) (p->next)
4042 - window_min_size (XWINDOW (p->next),
4043 horiz_flag, 0, 0, 0))
4044 /* This is a minibuffer following a main window. */
4045 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4046 - window_min_size (XWINDOW (p->prev),
4047 horiz_flag, 0, 0, 0))
4048 /* This is a frame with only one window, a minibuffer-only
4049 or a minibufferless frame. */
4050 : (delta = 0));
4052 if (delta > maxdelta)
4053 /* This case traps trying to make the minibuffer
4054 the full frame, or make the only window aside from the
4055 minibuffer the full frame. */
4056 delta = maxdelta;
4059 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
4060 horiz_flag, 0, 0, 0))
4062 delete_window (window);
4063 return;
4066 if (delta == 0)
4067 return;
4069 /* Find the total we can get from other siblings without deleting them. */
4070 maximum = 0;
4071 for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
4072 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4073 horiz_flag, 0, 0, 0);
4074 for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
4075 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4076 horiz_flag, 0, 0, 0);
4078 /* If we can get it all from them without deleting them, do so. */
4079 if (delta <= maximum)
4081 Lisp_Object first_unaffected;
4082 Lisp_Object first_affected;
4083 int fixed_p;
4085 next = p->next;
4086 prev = p->prev;
4087 first_affected = window;
4088 /* Look at one sibling at a time,
4089 moving away from this window in both directions alternately,
4090 and take as much as we can get without deleting that sibling. */
4091 while (delta != 0
4092 && (!NILP (next) || !NILP (prev)))
4094 if (! NILP (next))
4096 int this_one = ((*sizefun) (next)
4097 - window_min_size (XWINDOW (next), horiz_flag,
4098 0, 0, &fixed_p));
4099 if (!fixed_p)
4101 if (this_one > delta)
4102 this_one = delta;
4104 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4105 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4107 delta -= this_one;
4110 next = XWINDOW (next)->next;
4113 if (delta == 0)
4114 break;
4116 if (! NILP (prev))
4118 int this_one = ((*sizefun) (prev)
4119 - window_min_size (XWINDOW (prev), horiz_flag,
4120 0, 0, &fixed_p));
4121 if (!fixed_p)
4123 if (this_one > delta)
4124 this_one = delta;
4126 first_affected = prev;
4128 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4129 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4131 delta -= this_one;
4134 prev = XWINDOW (prev)->prev;
4138 xassert (delta == 0);
4140 /* Now recalculate the edge positions of all the windows affected,
4141 based on the new sizes. */
4142 first_unaffected = next;
4143 prev = first_affected;
4144 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4145 prev = next, next = XWINDOW (next)->next)
4147 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4148 /* This does not change size of NEXT,
4149 but it propagates the new top edge to its children */
4150 (*setsizefun) (next, (*sizefun) (next), 0);
4153 else
4155 register int delta1;
4156 register int opht = (*sizefun) (parent);
4158 if (opht <= XINT (*sizep) + delta)
4160 /* If trying to grow this window to or beyond size of the parent,
4161 just delete all the sibling windows. */
4162 Lisp_Object start, tem, next;
4164 start = XWINDOW (parent)->vchild;
4165 if (NILP (start))
4166 start = XWINDOW (parent)->hchild;
4168 /* Delete any siblings that come after WINDOW. */
4169 tem = XWINDOW (window)->next;
4170 while (! NILP (tem))
4172 next = XWINDOW (tem)->next;
4173 delete_window (tem);
4174 tem = next;
4177 /* Delete any siblings that come after WINDOW.
4178 Note that if START is not WINDOW, then WINDOW still
4179 has siblings, so WINDOW has not yet replaced its parent. */
4180 tem = start;
4181 while (! EQ (tem, window))
4183 next = XWINDOW (tem)->next;
4184 delete_window (tem);
4185 tem = next;
4188 else
4190 /* Otherwise, make delta1 just right so that if we add
4191 delta1 lines to this window and to the parent, and then
4192 shrink the parent back to its original size, the new
4193 proportional size of this window will increase by delta.
4195 The function size_window will compute the new height h'
4196 of the window from delta1 as:
4198 e = delta1/n
4199 x = delta1 - delta1/n * n for the 1st resizable child
4200 h' = h + e + x
4202 where n is the number of children that can be resized.
4203 We can ignore x by choosing a delta1 that is a multiple of
4204 n. We want the height of this window to come out as
4206 h' = h + delta
4208 So, delta1 must be
4210 h + e = h + delta
4211 delta1/n = delta
4212 delta1 = n * delta.
4214 The number of children n equals the number of resizable
4215 children of this window + 1 because we know window itself
4216 is resizable (otherwise we would have signaled an error).
4218 This reasoning is not correct when other windows become too
4219 small and shrink_windows refuses to delete them. Below we
4220 use resize_proportionally to work around this problem. */
4222 struct window *w = XWINDOW (window);
4223 Lisp_Object s;
4224 int n = 1;
4226 for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next)
4227 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4228 ++n;
4229 for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev)
4230 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4231 ++n;
4233 delta1 = n * delta;
4235 /* Add delta1 lines or columns to this window, and to the parent,
4236 keeping things consistent while not affecting siblings. */
4237 XSETINT (CURSIZE (parent), opht + delta1);
4238 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4240 /* Squeeze out delta1 lines or columns from our parent,
4241 shrinking this window and siblings proportionately. This
4242 brings parent back to correct size. Delta1 was calculated
4243 so this makes this window the desired size, taking it all
4244 out of the siblings.
4246 Temporarily set resize_proportionally to Qt to assure that,
4247 if necessary, shrink_windows deletes smaller windows rather
4248 than shrink this window. */
4249 w->resize_proportionally = Qt;
4250 (*setsizefun) (parent, opht, 0);
4251 w->resize_proportionally = Qnil;
4255 XSETFASTINT (p->last_modified, 0);
4256 XSETFASTINT (p->last_overlay_modified, 0);
4258 /* Adjust glyph matrices. */
4259 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4263 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4264 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4265 zero means adjust the height, moving the bottom edge.
4267 Following siblings of the selected window are resized to fulfill
4268 the size request. If they become too small in the process, they
4269 are not deleted; instead, we signal an error. */
4271 static void
4272 adjust_window_trailing_edge (Lisp_Object window, int delta, int horiz_flag)
4274 Lisp_Object parent, child;
4275 struct window *p;
4276 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4277 int delcount = window_deletion_count;
4279 CHECK_WINDOW (window);
4281 /* Give up if this window cannot be resized. */
4282 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4283 error ("Window is not resizable");
4285 while (1)
4287 Lisp_Object first_parallel = Qnil;
4289 if (NILP (window))
4291 /* This happens if WINDOW on the previous iteration was
4292 at top level of the window tree. */
4293 Fset_window_configuration (old_config);
4294 error ("Specified window edge is fixed");
4297 p = XWINDOW (window);
4298 parent = p->parent;
4300 /* See if this level has windows in parallel in the specified
4301 direction. If so, set FIRST_PARALLEL to the first one. */
4302 if (horiz_flag)
4304 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4305 first_parallel = XWINDOW (parent)->vchild;
4306 else if (NILP (parent) && !NILP (p->next))
4308 /* Handle the vertical chain of main window and minibuffer
4309 which has no parent. */
4310 first_parallel = window;
4311 while (! NILP (XWINDOW (first_parallel)->prev))
4312 first_parallel = XWINDOW (first_parallel)->prev;
4315 else
4317 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4318 first_parallel = XWINDOW (parent)->hchild;
4321 /* If this level's succession is in the desired dimension,
4322 and this window is the last one, and there is no higher level,
4323 its trailing edge is fixed. */
4324 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4325 && NILP (parent))
4327 Fset_window_configuration (old_config);
4328 error ("Specified window edge is fixed");
4331 /* Don't make this window too small. */
4332 if (XINT (CURSIZE (window)) + delta
4333 < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
4335 Fset_window_configuration (old_config);
4336 error ("Cannot adjust window size as specified");
4339 /* Clear out some redisplay caches. */
4340 XSETFASTINT (p->last_modified, 0);
4341 XSETFASTINT (p->last_overlay_modified, 0);
4343 /* Adjust this window's edge. */
4344 XSETINT (CURSIZE (window),
4345 XINT (CURSIZE (window)) + delta);
4347 /* If this window has following siblings in the desired dimension,
4348 make them smaller, and exit the loop.
4350 (If we reach the top of the tree and can never do this,
4351 we will fail and report an error, above.) */
4352 if (NILP (first_parallel))
4354 if (!NILP (p->next))
4356 /* This may happen for the minibuffer. In that case
4357 the window_deletion_count check below does not work. */
4358 if (XINT (CURSIZE (p->next)) - delta <= 0)
4360 Fset_window_configuration (old_config);
4361 error ("Cannot adjust window size as specified");
4364 XSETINT (CURBEG (p->next),
4365 XINT (CURBEG (p->next)) + delta);
4366 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4367 horiz_flag, 0, 1, 0);
4368 break;
4371 else
4372 /* Here we have a chain of parallel siblings, in the other dimension.
4373 Change the size of the other siblings. */
4374 for (child = first_parallel;
4375 ! NILP (child);
4376 child = XWINDOW (child)->next)
4377 if (! EQ (child, window))
4378 size_window (child, XINT (CURSIZE (child)) + delta,
4379 horiz_flag, 0, 0, 1);
4381 window = parent;
4384 /* If we made a window so small it got deleted,
4385 we failed. Report failure. */
4386 if (delcount != window_deletion_count)
4388 Fset_window_configuration (old_config);
4389 error ("Cannot adjust window size as specified");
4392 /* Adjust glyph matrices. */
4393 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4396 #undef CURBEG
4397 #undef CURSIZE
4399 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4400 Sadjust_window_trailing_edge, 3, 3, 0,
4401 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4402 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4403 Otherwise, adjust the height, moving the bottom edge.
4405 Following siblings of the selected window are resized to fulfill
4406 the size request. If they become too small in the process, they
4407 are not deleted; instead, we signal an error. */)
4408 (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal)
4410 CHECK_NUMBER (delta);
4411 if (NILP (window))
4412 window = selected_window;
4413 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4415 run_window_configuration_change_hook
4416 (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4418 return Qnil;
4423 /***********************************************************************
4424 Resizing Mini-Windows
4425 ***********************************************************************/
4427 static void shrink_window_lowest_first (struct window *, int);
4429 enum save_restore_action
4431 CHECK_ORIG_SIZES,
4432 SAVE_ORIG_SIZES,
4433 RESTORE_ORIG_SIZES
4436 static int save_restore_orig_size (struct window *,
4437 enum save_restore_action);
4439 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4440 from lowest windows first. */
4442 static void
4443 shrink_window_lowest_first (struct window *w, int height)
4445 struct window *c;
4446 Lisp_Object child;
4447 int old_height;
4449 xassert (!MINI_WINDOW_P (w));
4451 /* Set redisplay hints. */
4452 XSETFASTINT (w->last_modified, 0);
4453 XSETFASTINT (w->last_overlay_modified, 0);
4454 windows_or_buffers_changed++;
4455 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4457 old_height = XFASTINT (w->total_lines);
4458 XSETFASTINT (w->total_lines, height);
4460 if (!NILP (w->hchild))
4462 for (child = w->hchild; !NILP (child); child = c->next)
4464 c = XWINDOW (child);
4465 c->top_line = w->top_line;
4466 shrink_window_lowest_first (c, height);
4469 else if (!NILP (w->vchild))
4471 Lisp_Object last_child;
4472 int delta = old_height - height;
4473 int last_top;
4475 last_child = Qnil;
4477 /* Find the last child. We are taking space from lowest windows
4478 first, so we iterate over children from the last child
4479 backwards. */
4480 for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
4481 last_child = child;
4483 /* Size children down to their safe heights. */
4484 for (child = last_child; delta && !NILP (child); child = c->prev)
4486 int this_one;
4488 c = XWINDOW (child);
4489 this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
4491 if (this_one > delta)
4492 this_one = delta;
4494 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4495 delta -= this_one;
4498 /* Compute new positions. */
4499 last_top = XINT (w->top_line);
4500 for (child = w->vchild; !NILP (child); child = c->next)
4502 c = XWINDOW (child);
4503 c->top_line = make_number (last_top);
4504 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4505 last_top += XFASTINT (c->total_lines);
4511 /* Save, restore, or check positions and sizes in the window tree
4512 rooted at W. ACTION says what to do.
4514 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4515 orig_total_lines members are valid for all windows in the window
4516 tree. Value is non-zero if they are valid.
4518 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4519 orig_top_line and orig_total_lines for all windows in the tree.
4521 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4522 stored in orig_top_line and orig_total_lines for all windows. */
4524 static int
4525 save_restore_orig_size (struct window *w, enum save_restore_action action)
4527 int success_p = 1;
4529 while (w)
4531 if (!NILP (w->hchild))
4533 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4534 success_p = 0;
4536 else if (!NILP (w->vchild))
4538 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4539 success_p = 0;
4542 switch (action)
4544 case CHECK_ORIG_SIZES:
4545 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4546 return 0;
4547 break;
4549 case SAVE_ORIG_SIZES:
4550 w->orig_top_line = w->top_line;
4551 w->orig_total_lines = w->total_lines;
4552 XSETFASTINT (w->last_modified, 0);
4553 XSETFASTINT (w->last_overlay_modified, 0);
4554 break;
4556 case RESTORE_ORIG_SIZES:
4557 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4558 w->top_line = w->orig_top_line;
4559 w->total_lines = w->orig_total_lines;
4560 w->orig_total_lines = w->orig_top_line = Qnil;
4561 XSETFASTINT (w->last_modified, 0);
4562 XSETFASTINT (w->last_overlay_modified, 0);
4563 break;
4565 default:
4566 abort ();
4569 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4572 return success_p;
4576 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4577 without deleting other windows. */
4579 void
4580 grow_mini_window (struct window *w, int delta)
4582 struct frame *f = XFRAME (w->frame);
4583 struct window *root;
4585 xassert (MINI_WINDOW_P (w));
4586 /* Commenting out the following assertion goes against the stated interface
4587 of the function, but it currently does not seem to do anything useful.
4588 See discussion of this issue in the thread for bug#4534.
4589 xassert (delta >= 0); */
4591 /* Compute how much we can enlarge the mini-window without deleting
4592 other windows. */
4593 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4594 if (delta > 0)
4596 int min_height = window_min_size (root, 0, 0, 0, 0);
4597 if (XFASTINT (root->total_lines) - delta < min_height)
4598 /* Note that the root window may already be smaller than
4599 min_height. */
4600 delta = max (0, XFASTINT (root->total_lines) - min_height);
4603 if (delta)
4605 /* Save original window sizes and positions, if not already done. */
4606 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4607 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4609 /* Shrink other windows. */
4610 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4612 /* Grow the mini-window. */
4613 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4614 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4615 XSETFASTINT (w->last_modified, 0);
4616 XSETFASTINT (w->last_overlay_modified, 0);
4618 adjust_glyphs (f);
4623 /* Shrink mini-window W. If there is recorded info about window sizes
4624 before a call to grow_mini_window, restore recorded window sizes.
4625 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4626 line. */
4628 void
4629 shrink_mini_window (struct window *w)
4631 struct frame *f = XFRAME (w->frame);
4632 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4634 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4636 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4637 adjust_glyphs (f);
4638 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4639 windows_or_buffers_changed = 1;
4641 else if (XFASTINT (w->total_lines) > 1)
4643 /* Distribute the additional lines of the mini-window
4644 among the other windows. */
4645 Lisp_Object window;
4646 XSETWINDOW (window, w);
4647 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4653 /* Mark window cursors off for all windows in the window tree rooted
4654 at W by setting their phys_cursor_on_p flag to zero. Called from
4655 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4656 the frame are cleared. */
4658 void
4659 mark_window_cursors_off (struct window *w)
4661 while (w)
4663 if (!NILP (w->hchild))
4664 mark_window_cursors_off (XWINDOW (w->hchild));
4665 else if (!NILP (w->vchild))
4666 mark_window_cursors_off (XWINDOW (w->vchild));
4667 else
4668 w->phys_cursor_on_p = 0;
4670 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4675 /* Return number of lines of text (not counting mode lines) in W. */
4678 window_internal_height (struct window *w)
4680 int ht = XFASTINT (w->total_lines);
4682 if (!MINI_WINDOW_P (w))
4684 if (!NILP (w->parent)
4685 || !NILP (w->vchild)
4686 || !NILP (w->hchild)
4687 || !NILP (w->next)
4688 || !NILP (w->prev)
4689 || WINDOW_WANTS_MODELINE_P (w))
4690 --ht;
4692 if (WINDOW_WANTS_HEADER_LINE_P (w))
4693 --ht;
4696 return ht;
4700 /* Return the number of columns in W.
4701 Don't count columns occupied by scroll bars or the vertical bar
4702 separating W from the sibling to its right. */
4705 window_box_text_cols (struct window *w)
4707 struct frame *f = XFRAME (WINDOW_FRAME (w));
4708 int width = XINT (w->total_cols);
4710 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4711 /* Scroll bars occupy a few columns. */
4712 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4713 else if (!FRAME_WINDOW_P (f)
4714 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4715 /* The column of `|' characters separating side-by-side windows
4716 occupies one column only. */
4717 width -= 1;
4719 if (FRAME_WINDOW_P (f))
4720 /* On window-systems, fringes and display margins cannot be
4721 used for normal text. */
4722 width -= (WINDOW_FRINGE_COLS (w)
4723 + WINDOW_LEFT_MARGIN_COLS (w)
4724 + WINDOW_RIGHT_MARGIN_COLS (w));
4726 return width;
4730 /************************************************************************
4731 Window Scrolling
4732 ***********************************************************************/
4734 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4735 N screen-fulls, which is defined as the height of the window minus
4736 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4737 instead. Negative values of N mean scroll down. NOERROR non-zero
4738 means don't signal an error if we try to move over BEGV or ZV,
4739 respectively. */
4741 static void
4742 window_scroll (Lisp_Object window, int n, int whole, int noerror)
4744 immediate_quit = 1;
4746 /* If we must, use the pixel-based version which is much slower than
4747 the line-based one but can handle varying line heights. */
4748 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4749 window_scroll_pixel_based (window, n, whole, noerror);
4750 else
4751 window_scroll_line_based (window, n, whole, noerror);
4753 immediate_quit = 0;
4757 /* Implementation of window_scroll that works based on pixel line
4758 heights. See the comment of window_scroll for parameter
4759 descriptions. */
4761 static void
4762 window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4764 struct it it;
4765 struct window *w = XWINDOW (window);
4766 struct text_pos start;
4767 int this_scroll_margin;
4768 /* True if we fiddled the window vscroll field without really scrolling. */
4769 int vscrolled = 0;
4770 int x, y, rtop, rbot, rowh, vpos;
4772 SET_TEXT_POS_FROM_MARKER (start, w->start);
4774 /* If PT is not visible in WINDOW, move back one half of
4775 the screen. Allow PT to be partially visible, otherwise
4776 something like (scroll-down 1) with PT in the line before
4777 the partially visible one would recenter. */
4779 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4781 /* Move backward half the height of the window. Performance note:
4782 vmotion used here is about 10% faster, but would give wrong
4783 results for variable height lines. */
4784 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4785 it.current_y = it.last_visible_y;
4786 move_it_vertically_backward (&it, window_box_height (w) / 2);
4788 /* The function move_iterator_vertically may move over more than
4789 the specified y-distance. If it->w is small, e.g. a
4790 mini-buffer window, we may end up in front of the window's
4791 display area. This is the case when Start displaying at the
4792 start of the line containing PT in this case. */
4793 if (it.current_y <= 0)
4795 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4796 move_it_vertically_backward (&it, 0);
4797 it.current_y = 0;
4800 start = it.current.pos;
4802 else if (auto_window_vscroll_p)
4804 if (rtop || rbot) /* partially visible */
4806 int px;
4807 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4808 if (whole)
4809 dy = max ((window_box_height (w)
4810 - next_screen_context_lines * dy),
4811 dy);
4812 dy *= n;
4814 if (n < 0)
4816 /* Only vscroll backwards if already vscrolled forwards. */
4817 if (w->vscroll < 0 && rtop > 0)
4819 px = max (0, -w->vscroll - min (rtop, -dy));
4820 Fset_window_vscroll (window, make_number (px), Qt);
4821 return;
4824 if (n > 0)
4826 /* Do vscroll if already vscrolled or only display line. */
4827 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4829 px = max (0, -w->vscroll + min (rbot, dy));
4830 Fset_window_vscroll (window, make_number (px), Qt);
4831 return;
4834 /* Maybe modify window start instead of scrolling. */
4835 if (rbot > 0 || w->vscroll < 0)
4837 EMACS_INT spos;
4839 Fset_window_vscroll (window, make_number (0), Qt);
4840 /* If there are other text lines above the current row,
4841 move window start to current row. Else to next row. */
4842 if (rbot > 0)
4843 spos = XINT (Fline_beginning_position (Qnil));
4844 else
4845 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4846 set_marker_restricted (w->start, make_number (spos),
4847 w->buffer);
4848 w->start_at_line_beg = Qt;
4849 w->update_mode_line = Qt;
4850 XSETFASTINT (w->last_modified, 0);
4851 XSETFASTINT (w->last_overlay_modified, 0);
4852 /* Set force_start so that redisplay_window will run the
4853 window-scroll-functions. */
4854 w->force_start = Qt;
4855 return;
4859 /* Cancel previous vscroll. */
4860 Fset_window_vscroll (window, make_number (0), Qt);
4863 /* If scroll_preserve_screen_position is non-nil, we try to set
4864 point in the same window line as it is now, so get that line. */
4865 if (!NILP (Vscroll_preserve_screen_position))
4867 /* We preserve the goal pixel coordinate across consecutive
4868 calls to scroll-up, scroll-down and other commands that
4869 have the `scroll-command' property. This avoids the
4870 possibility of point becoming "stuck" on a tall line when
4871 scrolling by one line. */
4872 if (window_scroll_pixel_based_preserve_y < 0
4873 || !SYMBOLP (current_kboard->Vlast_command)
4874 || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
4876 start_display (&it, w, start);
4877 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4878 window_scroll_pixel_based_preserve_y = it.current_y;
4879 window_scroll_pixel_based_preserve_x = it.current_x;
4882 else
4883 window_scroll_pixel_based_preserve_y
4884 = window_scroll_pixel_based_preserve_x = -1;
4886 /* Move iterator it from start the specified distance forward or
4887 backward. The result is the new window start. */
4888 start_display (&it, w, start);
4889 if (whole)
4891 EMACS_INT start_pos = IT_CHARPOS (it);
4892 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4893 dy = max ((window_box_height (w)
4894 - next_screen_context_lines * dy),
4895 dy) * n;
4897 /* Note that move_it_vertically always moves the iterator to the
4898 start of a line. So, if the last line doesn't have a newline,
4899 we would end up at the start of the line ending at ZV. */
4900 if (dy <= 0)
4902 move_it_vertically_backward (&it, -dy);
4903 /* Ensure we actually do move, e.g. in case we are currently
4904 looking at an image that is taller that the window height. */
4905 while (start_pos == IT_CHARPOS (it)
4906 && start_pos > BEGV)
4907 move_it_by_lines (&it, -1, 1);
4909 else if (dy > 0)
4911 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4912 MOVE_TO_POS | MOVE_TO_Y);
4913 /* Ensure we actually do move, e.g. in case we are currently
4914 looking at an image that is taller that the window height. */
4915 while (start_pos == IT_CHARPOS (it)
4916 && start_pos < ZV)
4917 move_it_by_lines (&it, 1, 1);
4920 else
4921 move_it_by_lines (&it, n, 1);
4923 /* We failed if we find ZV is already on the screen (scrolling up,
4924 means there's nothing past the end), or if we can't start any
4925 earlier (scrolling down, means there's nothing past the top). */
4926 if ((n > 0 && IT_CHARPOS (it) == ZV)
4927 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4929 if (IT_CHARPOS (it) == ZV)
4931 if (it.current_y < it.last_visible_y
4932 && (it.current_y + it.max_ascent + it.max_descent
4933 > it.last_visible_y))
4935 /* The last line was only partially visible, make it fully
4936 visible. */
4937 w->vscroll = (it.last_visible_y
4938 - it.current_y + it.max_ascent + it.max_descent);
4939 adjust_glyphs (it.f);
4941 else if (noerror)
4942 return;
4943 else if (n < 0) /* could happen with empty buffers */
4944 xsignal0 (Qbeginning_of_buffer);
4945 else
4946 xsignal0 (Qend_of_buffer);
4948 else
4950 if (w->vscroll != 0)
4951 /* The first line was only partially visible, make it fully
4952 visible. */
4953 w->vscroll = 0;
4954 else if (noerror)
4955 return;
4956 else
4957 xsignal0 (Qbeginning_of_buffer);
4960 /* If control gets here, then we vscrolled. */
4962 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4964 /* Don't try to change the window start below. */
4965 vscrolled = 1;
4968 if (! vscrolled)
4970 EMACS_INT pos = IT_CHARPOS (it);
4971 EMACS_INT bytepos;
4973 /* If in the middle of a multi-glyph character move forward to
4974 the next character. */
4975 if (in_display_vector_p (&it))
4977 ++pos;
4978 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4981 /* Set the window start, and set up the window for redisplay. */
4982 set_marker_restricted (w->start, make_number (pos),
4983 w->buffer);
4984 bytepos = XMARKER (w->start)->bytepos;
4985 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4986 ? Qt : Qnil);
4987 w->update_mode_line = Qt;
4988 XSETFASTINT (w->last_modified, 0);
4989 XSETFASTINT (w->last_overlay_modified, 0);
4990 /* Set force_start so that redisplay_window will run the
4991 window-scroll-functions. */
4992 w->force_start = Qt;
4995 /* The rest of this function uses current_y in a nonstandard way,
4996 not including the height of the header line if any. */
4997 it.current_y = it.vpos = 0;
4999 /* Move PT out of scroll margins.
5000 This code wants current_y to be zero at the window start position
5001 even if there is a header line. */
5002 this_scroll_margin = max (0, scroll_margin);
5003 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5004 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5006 if (n > 0)
5008 /* We moved the window start towards ZV, so PT may be now
5009 in the scroll margin at the top. */
5010 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5011 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5012 && (NILP (Vscroll_preserve_screen_position)
5013 || EQ (Vscroll_preserve_screen_position, Qt)))
5014 /* We found PT at a legitimate height. Leave it alone. */
5016 else if (window_scroll_pixel_based_preserve_y >= 0)
5018 /* If we have a header line, take account of it.
5019 This is necessary because we set it.current_y to 0, above. */
5020 move_it_to (&it, -1,
5021 window_scroll_pixel_based_preserve_x,
5022 window_scroll_pixel_based_preserve_y
5023 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5024 -1, MOVE_TO_Y | MOVE_TO_X);
5025 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5027 else
5029 while (it.current_y < this_scroll_margin)
5031 int prev = it.current_y;
5032 move_it_by_lines (&it, 1, 1);
5033 if (prev == it.current_y)
5034 break;
5036 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5039 else if (n < 0)
5041 EMACS_INT charpos, bytepos;
5042 int partial_p;
5044 /* Save our position, for the
5045 window_scroll_pixel_based_preserve_y case. */
5046 charpos = IT_CHARPOS (it);
5047 bytepos = IT_BYTEPOS (it);
5049 /* We moved the window start towards BEGV, so PT may be now
5050 in the scroll margin at the bottom. */
5051 move_it_to (&it, PT, -1,
5052 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5053 - this_scroll_margin - 1),
5055 MOVE_TO_POS | MOVE_TO_Y);
5057 /* Save our position, in case it's correct. */
5058 charpos = IT_CHARPOS (it);
5059 bytepos = IT_BYTEPOS (it);
5061 /* See if point is on a partially visible line at the end. */
5062 if (it.what == IT_EOB)
5063 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5064 else
5066 move_it_by_lines (&it, 1, 1);
5067 partial_p = it.current_y > it.last_visible_y;
5070 if (charpos == PT && !partial_p
5071 && (NILP (Vscroll_preserve_screen_position)
5072 || EQ (Vscroll_preserve_screen_position, Qt)))
5073 /* We found PT before we found the display margin, so PT is ok. */
5075 else if (window_scroll_pixel_based_preserve_y >= 0)
5077 SET_TEXT_POS_FROM_MARKER (start, w->start);
5078 start_display (&it, w, start);
5079 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5080 here because we called start_display again and did not
5081 alter it.current_y this time. */
5082 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5083 window_scroll_pixel_based_preserve_y, -1,
5084 MOVE_TO_Y | MOVE_TO_X);
5085 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5087 else
5089 if (partial_p)
5090 /* The last line was only partially visible, so back up two
5091 lines to make sure we're on a fully visible line. */
5093 move_it_by_lines (&it, -2, 0);
5094 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5096 else
5097 /* No, the position we saved is OK, so use it. */
5098 SET_PT_BOTH (charpos, bytepos);
5104 /* Implementation of window_scroll that works based on screen lines.
5105 See the comment of window_scroll for parameter descriptions. */
5107 static void
5108 window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
5110 register struct window *w = XWINDOW (window);
5111 register EMACS_INT opoint = PT, opoint_byte = PT_BYTE;
5112 register EMACS_INT pos, pos_byte;
5113 register int ht = window_internal_height (w);
5114 register Lisp_Object tem;
5115 int lose;
5116 Lisp_Object bolp;
5117 EMACS_INT startpos;
5118 Lisp_Object original_pos = Qnil;
5120 /* If scrolling screen-fulls, compute the number of lines to
5121 scroll from the window's height. */
5122 if (whole)
5123 n *= max (1, ht - next_screen_context_lines);
5125 startpos = marker_position (w->start);
5127 if (!NILP (Vscroll_preserve_screen_position))
5129 if (window_scroll_preserve_vpos <= 0
5130 || !SYMBOLP (current_kboard->Vlast_command)
5131 || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
5133 struct position posit
5134 = *compute_motion (startpos, 0, 0, 0,
5135 PT, ht, 0,
5136 -1, XINT (w->hscroll),
5137 0, w);
5138 window_scroll_preserve_vpos = posit.vpos;
5139 window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
5142 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5143 make_number (window_scroll_preserve_vpos));
5146 XSETFASTINT (tem, PT);
5147 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5149 if (NILP (tem))
5151 Fvertical_motion (make_number (- (ht / 2)), window);
5152 startpos = PT;
5155 SET_PT (startpos);
5156 lose = n < 0 && PT == BEGV;
5157 Fvertical_motion (make_number (n), window);
5158 pos = PT;
5159 pos_byte = PT_BYTE;
5160 bolp = Fbolp ();
5161 SET_PT_BOTH (opoint, opoint_byte);
5163 if (lose)
5165 if (noerror)
5166 return;
5167 else
5168 xsignal0 (Qbeginning_of_buffer);
5171 if (pos < ZV)
5173 int this_scroll_margin = scroll_margin;
5175 /* Don't use a scroll margin that is negative or too large. */
5176 if (this_scroll_margin < 0)
5177 this_scroll_margin = 0;
5179 if (XINT (w->total_lines) < 4 * scroll_margin)
5180 this_scroll_margin = XINT (w->total_lines) / 4;
5182 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5183 w->start_at_line_beg = bolp;
5184 w->update_mode_line = Qt;
5185 XSETFASTINT (w->last_modified, 0);
5186 XSETFASTINT (w->last_overlay_modified, 0);
5187 /* Set force_start so that redisplay_window will run
5188 the window-scroll-functions. */
5189 w->force_start = Qt;
5191 if (!NILP (Vscroll_preserve_screen_position)
5192 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5194 SET_PT_BOTH (pos, pos_byte);
5195 Fvertical_motion (original_pos, window);
5197 /* If we scrolled forward, put point enough lines down
5198 that it is outside the scroll margin. */
5199 else if (n > 0)
5201 int top_margin;
5203 if (this_scroll_margin > 0)
5205 SET_PT_BOTH (pos, pos_byte);
5206 Fvertical_motion (make_number (this_scroll_margin), window);
5207 top_margin = PT;
5209 else
5210 top_margin = pos;
5212 if (top_margin <= opoint)
5213 SET_PT_BOTH (opoint, opoint_byte);
5214 else if (!NILP (Vscroll_preserve_screen_position))
5216 SET_PT_BOTH (pos, pos_byte);
5217 Fvertical_motion (original_pos, window);
5219 else
5220 SET_PT (top_margin);
5222 else if (n < 0)
5224 int bottom_margin;
5226 /* If we scrolled backward, put point near the end of the window
5227 but not within the scroll margin. */
5228 SET_PT_BOTH (pos, pos_byte);
5229 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5230 if (XFASTINT (tem) == ht - this_scroll_margin)
5231 bottom_margin = PT;
5232 else
5233 bottom_margin = PT + 1;
5235 if (bottom_margin > opoint)
5236 SET_PT_BOTH (opoint, opoint_byte);
5237 else
5239 if (!NILP (Vscroll_preserve_screen_position))
5241 SET_PT_BOTH (pos, pos_byte);
5242 Fvertical_motion (original_pos, window);
5244 else
5245 Fvertical_motion (make_number (-1), window);
5249 else
5251 if (noerror)
5252 return;
5253 else
5254 xsignal0 (Qend_of_buffer);
5259 /* Scroll selected_window up or down. If N is nil, scroll a
5260 screen-full which is defined as the height of the window minus
5261 next_screen_context_lines. If N is the symbol `-', scroll.
5262 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5263 up. This is the guts of Fscroll_up and Fscroll_down. */
5265 static void
5266 scroll_command (Lisp_Object n, int direction)
5268 int count = SPECPDL_INDEX ();
5270 xassert (eabs (direction) == 1);
5272 /* If selected window's buffer isn't current, make it current for
5273 the moment. But don't screw up if window_scroll gets an error. */
5274 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5276 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5277 Fset_buffer (XWINDOW (selected_window)->buffer);
5279 /* Make redisplay consider other windows than just selected_window. */
5280 ++windows_or_buffers_changed;
5283 if (NILP (n))
5284 window_scroll (selected_window, direction, 1, 0);
5285 else if (EQ (n, Qminus))
5286 window_scroll (selected_window, -direction, 1, 0);
5287 else
5289 n = Fprefix_numeric_value (n);
5290 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5293 unbind_to (count, Qnil);
5296 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5297 doc: /* Scroll text of selected window upward ARG lines.
5298 If ARG is omitted or nil, scroll upward by a near full screen.
5299 A near full screen is `next-screen-context-lines' less than a full screen.
5300 Negative ARG means scroll downward.
5301 If ARG is the atom `-', scroll downward by nearly full screen.
5302 When calling from a program, supply as argument a number, nil, or `-'. */)
5303 (Lisp_Object arg)
5305 scroll_command (arg, 1);
5306 return Qnil;
5309 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5310 doc: /* Scroll text of selected window down ARG lines.
5311 If ARG is omitted or nil, scroll down by a near full screen.
5312 A near full screen is `next-screen-context-lines' less than a full screen.
5313 Negative ARG means scroll upward.
5314 If ARG is the atom `-', scroll upward by nearly full screen.
5315 When calling from a program, supply as argument a number, nil, or `-'. */)
5316 (Lisp_Object arg)
5318 scroll_command (arg, -1);
5319 return Qnil;
5322 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5323 doc: /* Return the other window for \"other window scroll\" commands.
5324 If `other-window-scroll-buffer' is non-nil, a window
5325 showing that buffer is used.
5326 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5327 specifies the window. This takes precedence over
5328 `other-window-scroll-buffer'. */)
5329 (void)
5331 Lisp_Object window;
5333 if (MINI_WINDOW_P (XWINDOW (selected_window))
5334 && !NILP (Vminibuf_scroll_window))
5335 window = Vminibuf_scroll_window;
5336 /* If buffer is specified, scroll that buffer. */
5337 else if (!NILP (Vother_window_scroll_buffer))
5339 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5340 if (NILP (window))
5341 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5343 else
5345 /* Nothing specified; look for a neighboring window on the same
5346 frame. */
5347 window = Fnext_window (selected_window, Qnil, Qnil);
5349 if (EQ (window, selected_window))
5350 /* That didn't get us anywhere; look for a window on another
5351 visible frame. */
5353 window = Fnext_window (window, Qnil, Qt);
5354 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5355 && ! EQ (window, selected_window));
5358 CHECK_LIVE_WINDOW (window);
5360 if (EQ (window, selected_window))
5361 error ("There is no other window");
5363 return window;
5366 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5367 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5368 A near full screen is `next-screen-context-lines' less than a full screen.
5369 The next window is the one below the current one; or the one at the top
5370 if the current one is at the bottom. Negative ARG means scroll downward.
5371 If ARG is the atom `-', scroll downward by nearly full screen.
5372 When calling from a program, supply as argument a number, nil, or `-'.
5374 If `other-window-scroll-buffer' is non-nil, scroll the window
5375 showing that buffer, popping the buffer up if necessary.
5376 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5377 specifies the window to scroll. This takes precedence over
5378 `other-window-scroll-buffer'. */)
5379 (Lisp_Object arg)
5381 Lisp_Object window;
5382 struct window *w;
5383 int count = SPECPDL_INDEX ();
5385 window = Fother_window_for_scrolling ();
5386 w = XWINDOW (window);
5388 /* Don't screw up if window_scroll gets an error. */
5389 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5390 ++windows_or_buffers_changed;
5392 Fset_buffer (w->buffer);
5393 SET_PT (marker_position (w->pointm));
5395 if (NILP (arg))
5396 window_scroll (window, 1, 1, 1);
5397 else if (EQ (arg, Qminus))
5398 window_scroll (window, -1, 1, 1);
5399 else
5401 if (CONSP (arg))
5402 arg = Fcar (arg);
5403 CHECK_NUMBER (arg);
5404 window_scroll (window, XINT (arg), 0, 1);
5407 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5408 unbind_to (count, Qnil);
5410 return Qnil;
5413 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5414 doc: /* Scroll selected window display ARG columns left.
5415 Default for ARG is window width minus 2.
5416 Value is the total amount of leftward horizontal scrolling in
5417 effect after the change.
5418 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5419 lower bound for automatic scrolling, i.e. automatic scrolling
5420 will not scroll a window to a column less than the value returned
5421 by this function. This happens in an interactive call. */)
5422 (register Lisp_Object arg, Lisp_Object set_minimum)
5424 Lisp_Object result;
5425 int hscroll;
5426 struct window *w = XWINDOW (selected_window);
5428 if (NILP (arg))
5429 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5430 else
5431 arg = Fprefix_numeric_value (arg);
5433 hscroll = XINT (w->hscroll) + XINT (arg);
5434 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5436 if (!NILP (set_minimum))
5437 w->min_hscroll = w->hscroll;
5439 return result;
5442 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5443 doc: /* Scroll selected window display ARG columns right.
5444 Default for ARG is window width minus 2.
5445 Value is the total amount of leftward horizontal scrolling in
5446 effect after the change.
5447 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5448 lower bound for automatic scrolling, i.e. automatic scrolling
5449 will not scroll a window to a column less than the value returned
5450 by this function. This happens in an interactive call. */)
5451 (register Lisp_Object arg, Lisp_Object set_minimum)
5453 Lisp_Object result;
5454 int hscroll;
5455 struct window *w = XWINDOW (selected_window);
5457 if (NILP (arg))
5458 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5459 else
5460 arg = Fprefix_numeric_value (arg);
5462 hscroll = XINT (w->hscroll) - XINT (arg);
5463 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5465 if (!NILP (set_minimum))
5466 w->min_hscroll = w->hscroll;
5468 return result;
5471 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5472 doc: /* Return the window which was selected when entering the minibuffer.
5473 Returns nil, if selected window is not a minibuffer window. */)
5474 (void)
5476 if (minibuf_level > 0
5477 && MINI_WINDOW_P (XWINDOW (selected_window))
5478 && WINDOW_LIVE_P (minibuf_selected_window))
5479 return minibuf_selected_window;
5481 return Qnil;
5484 /* Value is the number of lines actually displayed in window W,
5485 as opposed to its height. */
5487 static int
5488 displayed_window_lines (struct window *w)
5490 struct it it;
5491 struct text_pos start;
5492 int height = window_box_height (w);
5493 struct buffer *old_buffer;
5494 int bottom_y;
5496 if (XBUFFER (w->buffer) != current_buffer)
5498 old_buffer = current_buffer;
5499 set_buffer_internal (XBUFFER (w->buffer));
5501 else
5502 old_buffer = NULL;
5504 /* In case W->start is out of the accessible range, do something
5505 reasonable. This happens in Info mode when Info-scroll-down
5506 calls (recenter -1) while W->start is 1. */
5507 if (XMARKER (w->start)->charpos < BEGV)
5508 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5509 else if (XMARKER (w->start)->charpos > ZV)
5510 SET_TEXT_POS (start, ZV, ZV_BYTE);
5511 else
5512 SET_TEXT_POS_FROM_MARKER (start, w->start);
5514 start_display (&it, w, start);
5515 move_it_vertically (&it, height);
5516 bottom_y = line_bottom_y (&it);
5518 /* rms: On a non-window display,
5519 the value of it.vpos at the bottom of the screen
5520 seems to be 1 larger than window_box_height (w).
5521 This kludge fixes a bug whereby (move-to-window-line -1)
5522 when ZV is on the last screen line
5523 moves to the previous screen line instead of the last one. */
5524 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5525 height++;
5527 /* Add in empty lines at the bottom of the window. */
5528 if (bottom_y < height)
5530 int uy = FRAME_LINE_HEIGHT (it.f);
5531 it.vpos += (height - bottom_y + uy - 1) / uy;
5534 if (old_buffer)
5535 set_buffer_internal (old_buffer);
5537 return it.vpos;
5541 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5542 doc: /* Center point in selected window and maybe redisplay frame.
5543 With prefix argument ARG, recenter putting point on screen line ARG
5544 relative to the selected window. If ARG is negative, it counts up from the
5545 bottom of the window. (ARG should be less than the height of the window.)
5547 If ARG is omitted or nil, then recenter with point on the middle line of
5548 the selected window; if the variable `recenter-redisplay' is non-nil,
5549 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5550 is set to `grow-only', this resets the tool-bar's height to the minimum
5551 height needed); if `recenter-redisplay' has the special value `tty',
5552 then only tty frame are redrawn.
5554 Just C-u as prefix means put point in the center of the window
5555 and redisplay normally--don't erase and redraw the frame. */)
5556 (register Lisp_Object arg)
5558 struct window *w = XWINDOW (selected_window);
5559 struct buffer *buf = XBUFFER (w->buffer);
5560 struct buffer *obuf = current_buffer;
5561 int center_p = 0;
5562 EMACS_INT charpos, bytepos;
5563 int iarg;
5564 int this_scroll_margin;
5566 /* If redisplay is suppressed due to an error, try again. */
5567 obuf->display_error_modiff = 0;
5569 if (NILP (arg))
5571 if (!NILP (Vrecenter_redisplay)
5572 && (!EQ (Vrecenter_redisplay, Qtty)
5573 || !NILP (Ftty_type (selected_frame))))
5575 int i;
5577 /* Invalidate pixel data calculated for all compositions. */
5578 for (i = 0; i < n_compositions; i++)
5579 composition_table[i]->font = NULL;
5581 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5583 Fredraw_frame (WINDOW_FRAME (w));
5584 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5587 center_p = 1;
5589 else if (CONSP (arg)) /* Just C-u. */
5590 center_p = 1;
5591 else
5593 arg = Fprefix_numeric_value (arg);
5594 CHECK_NUMBER (arg);
5595 iarg = XINT (arg);
5598 set_buffer_internal (buf);
5600 /* Do this after making BUF current
5601 in case scroll_margin is buffer-local. */
5602 this_scroll_margin = max (0, scroll_margin);
5603 this_scroll_margin = min (this_scroll_margin,
5604 XFASTINT (w->total_lines) / 4);
5606 /* Handle centering on a graphical frame specially. Such frames can
5607 have variable-height lines and centering point on the basis of
5608 line counts would lead to strange effects. */
5609 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5611 if (center_p)
5613 struct it it;
5614 struct text_pos pt;
5616 SET_TEXT_POS (pt, PT, PT_BYTE);
5617 start_display (&it, w, pt);
5618 move_it_vertically_backward (&it, window_box_height (w) / 2);
5619 charpos = IT_CHARPOS (it);
5620 bytepos = IT_BYTEPOS (it);
5622 else if (iarg < 0)
5624 struct it it;
5625 struct text_pos pt;
5626 int nlines = -iarg;
5627 int extra_line_spacing;
5628 int h = window_box_height (w);
5630 iarg = - max (-iarg, this_scroll_margin);
5632 SET_TEXT_POS (pt, PT, PT_BYTE);
5633 start_display (&it, w, pt);
5635 /* Be sure we have the exact height of the full line containing PT. */
5636 move_it_by_lines (&it, 0, 1);
5638 /* The amount of pixels we have to move back is the window
5639 height minus what's displayed in the line containing PT,
5640 and the lines below. */
5641 it.current_y = 0;
5642 it.vpos = 0;
5643 move_it_by_lines (&it, nlines, 1);
5645 if (it.vpos == nlines)
5646 h -= it.current_y;
5647 else
5649 /* Last line has no newline */
5650 h -= line_bottom_y (&it);
5651 it.vpos++;
5654 /* Don't reserve space for extra line spacing of last line. */
5655 extra_line_spacing = it.max_extra_line_spacing;
5657 /* If we can't move down NLINES lines because we hit
5658 the end of the buffer, count in some empty lines. */
5659 if (it.vpos < nlines)
5661 nlines -= it.vpos;
5662 extra_line_spacing = it.extra_line_spacing;
5663 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5665 if (h <= 0)
5666 return Qnil;
5668 /* Now find the new top line (starting position) of the window. */
5669 start_display (&it, w, pt);
5670 it.current_y = 0;
5671 move_it_vertically_backward (&it, h);
5673 /* If extra line spacing is present, we may move too far
5674 back. This causes the last line to be only partially
5675 visible (which triggers redisplay to recenter that line
5676 in the middle), so move forward.
5677 But ignore extra line spacing on last line, as it is not
5678 considered to be part of the visible height of the line.
5680 h += extra_line_spacing;
5681 while (-it.current_y > h)
5682 move_it_by_lines (&it, 1, 1);
5684 charpos = IT_CHARPOS (it);
5685 bytepos = IT_BYTEPOS (it);
5687 else
5689 struct position pos;
5691 iarg = max (iarg, this_scroll_margin);
5693 pos = *vmotion (PT, -iarg, w);
5694 charpos = pos.bufpos;
5695 bytepos = pos.bytepos;
5698 else
5700 struct position pos;
5701 int ht = window_internal_height (w);
5703 if (center_p)
5704 iarg = ht / 2;
5705 else if (iarg < 0)
5706 iarg += ht;
5708 /* Don't let it get into the margin at either top or bottom. */
5709 iarg = max (iarg, this_scroll_margin);
5710 iarg = min (iarg, ht - this_scroll_margin - 1);
5712 pos = *vmotion (PT, - iarg, w);
5713 charpos = pos.bufpos;
5714 bytepos = pos.bytepos;
5717 /* Set the new window start. */
5718 set_marker_both (w->start, w->buffer, charpos, bytepos);
5719 w->window_end_valid = Qnil;
5721 w->optional_new_start = Qt;
5723 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5724 w->start_at_line_beg = Qt;
5725 else
5726 w->start_at_line_beg = Qnil;
5728 set_buffer_internal (obuf);
5729 return Qnil;
5733 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5734 0, 1, 0,
5735 doc: /* Return the height in lines of the text display area of WINDOW.
5736 WINDOW defaults to the selected window.
5738 The return value does not include the mode line, any header line, nor
5739 any partial-height lines in the text display area. */)
5740 (Lisp_Object window)
5742 struct window *w = decode_window (window);
5743 int pixel_height = window_box_height (w);
5744 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5745 return make_number (line_height);
5750 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5751 1, 1, "P",
5752 doc: /* Position point relative to window.
5753 With no argument, position point at center of window.
5754 An argument specifies vertical position within the window;
5755 zero means top of window, negative means relative to bottom of window. */)
5756 (Lisp_Object arg)
5758 struct window *w = XWINDOW (selected_window);
5759 int lines, start;
5760 Lisp_Object window;
5761 #if 0
5762 int this_scroll_margin;
5763 #endif
5765 if (!(BUFFERP (w->buffer)
5766 && XBUFFER (w->buffer) == current_buffer))
5767 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5768 when passed below to set_marker_both. */
5769 error ("move-to-window-line called from unrelated buffer");
5771 window = selected_window;
5772 start = marker_position (w->start);
5773 if (start < BEGV || start > ZV)
5775 int height = window_internal_height (w);
5776 Fvertical_motion (make_number (- (height / 2)), window);
5777 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5778 w->start_at_line_beg = Fbolp ();
5779 w->force_start = Qt;
5781 else
5782 Fgoto_char (w->start);
5784 lines = displayed_window_lines (w);
5786 #if 0
5787 this_scroll_margin = max (0, scroll_margin);
5788 this_scroll_margin = min (this_scroll_margin, lines / 4);
5789 #endif
5791 if (NILP (arg))
5792 XSETFASTINT (arg, lines / 2);
5793 else
5795 int iarg = XINT (Fprefix_numeric_value (arg));
5797 if (iarg < 0)
5798 iarg = iarg + lines;
5800 #if 0 /* This code would prevent move-to-window-line from moving point
5801 to a place inside the scroll margins (which would cause the
5802 next redisplay to scroll). I wrote this code, but then concluded
5803 it is probably better not to install it. However, it is here
5804 inside #if 0 so as not to lose it. -- rms. */
5806 /* Don't let it get into the margin at either top or bottom. */
5807 iarg = max (iarg, this_scroll_margin);
5808 iarg = min (iarg, lines - this_scroll_margin - 1);
5809 #endif
5811 arg = make_number (iarg);
5814 /* Skip past a partially visible first line. */
5815 if (w->vscroll)
5816 XSETINT (arg, XINT (arg) + 1);
5818 return Fvertical_motion (arg, window);
5823 /***********************************************************************
5824 Window Configuration
5825 ***********************************************************************/
5827 struct save_window_data
5829 EMACS_UINT size;
5830 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5831 Lisp_Object selected_frame;
5832 Lisp_Object current_window;
5833 Lisp_Object current_buffer;
5834 Lisp_Object minibuf_scroll_window;
5835 Lisp_Object minibuf_selected_window;
5836 Lisp_Object root_window;
5837 Lisp_Object focus_frame;
5838 /* A vector, each of whose elements is a struct saved_window
5839 for one window. */
5840 Lisp_Object saved_windows;
5842 /* All fields above are traced by the GC.
5843 From `fame-cols' down, the fields are ignored by the GC. */
5845 int frame_cols, frame_lines, frame_menu_bar_lines;
5846 int frame_tool_bar_lines;
5849 /* This is saved as a Lisp_Vector */
5850 struct saved_window
5852 /* these first two must agree with struct Lisp_Vector in lisp.h */
5853 EMACS_UINT size;
5854 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5856 Lisp_Object window;
5857 Lisp_Object buffer, start, pointm, mark;
5858 Lisp_Object left_col, top_line, total_cols, total_lines;
5859 Lisp_Object hscroll, min_hscroll;
5860 Lisp_Object parent, prev;
5861 Lisp_Object start_at_line_beg;
5862 Lisp_Object display_table;
5863 Lisp_Object orig_top_line, orig_total_lines;
5864 Lisp_Object left_margin_cols, right_margin_cols;
5865 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5866 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5867 Lisp_Object dedicated, resize_proportionally;
5870 #define SAVED_WINDOW_N(swv,n) \
5871 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5873 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5874 doc: /* Return t if OBJECT is a window-configuration object. */)
5875 (Lisp_Object object)
5877 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5880 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5881 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5882 (Lisp_Object config)
5884 register struct save_window_data *data;
5885 struct Lisp_Vector *saved_windows;
5887 CHECK_WINDOW_CONFIGURATION (config);
5889 data = (struct save_window_data *) XVECTOR (config);
5890 saved_windows = XVECTOR (data->saved_windows);
5891 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5894 DEFUN ("set-window-configuration", Fset_window_configuration,
5895 Sset_window_configuration, 1, 1, 0,
5896 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5897 CONFIGURATION must be a value previously returned
5898 by `current-window-configuration' (which see).
5899 If CONFIGURATION was made from a frame that is now deleted,
5900 only frame-independent values can be restored. In this case,
5901 the return value is nil. Otherwise the value is t. */)
5902 (Lisp_Object configuration)
5904 register struct save_window_data *data;
5905 struct Lisp_Vector *saved_windows;
5906 Lisp_Object new_current_buffer;
5907 Lisp_Object frame;
5908 FRAME_PTR f;
5909 EMACS_INT old_point = -1;
5911 CHECK_WINDOW_CONFIGURATION (configuration);
5913 data = (struct save_window_data *) XVECTOR (configuration);
5914 saved_windows = XVECTOR (data->saved_windows);
5916 new_current_buffer = data->current_buffer;
5917 if (NILP (XBUFFER (new_current_buffer)->name))
5918 new_current_buffer = Qnil;
5919 else
5921 if (XBUFFER (new_current_buffer) == current_buffer)
5922 /* The code further down "preserves point" by saving here PT in
5923 old_point and then setting it later back into PT. When the
5924 current-selected-window and the final-selected-window both show
5925 the current buffer, this suffers from the problem that the
5926 current PT is the window-point of the current-selected-window,
5927 while the final PT is the point of the final-selected-window, so
5928 this copy from one PT to the other would end up moving the
5929 window-point of the final-selected-window to the window-point of
5930 the current-selected-window. So we have to be careful which
5931 point of the current-buffer we copy into old_point. */
5932 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5933 && WINDOWP (selected_window)
5934 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5935 && !EQ (selected_window, data->current_window))
5936 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5937 else
5938 old_point = PT;
5939 else
5940 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5941 point in new_current_buffer as of the last time this buffer was
5942 used. This can be non-deterministic since it can be changed by
5943 things like jit-lock by mere temporary selection of some random
5944 window that happens to show this buffer.
5945 So if possible we want this arbitrary choice of "which point" to
5946 be the one from the to-be-selected-window so as to prevent this
5947 window's cursor from being copied from another window. */
5948 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5949 /* If current_window = selected_window, its point is in BUF_PT. */
5950 && !EQ (selected_window, data->current_window))
5951 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5952 else
5953 old_point = BUF_PT (XBUFFER (new_current_buffer));
5956 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5957 f = XFRAME (frame);
5959 /* If f is a dead frame, don't bother rebuilding its window tree.
5960 However, there is other stuff we should still try to do below. */
5961 if (FRAME_LIVE_P (f))
5963 register struct window *w;
5964 register struct saved_window *p;
5965 struct window *root_window;
5966 struct window **leaf_windows;
5967 int n_leaf_windows;
5968 int k, i, n;
5970 /* If the frame has been resized since this window configuration was
5971 made, we change the frame to the size specified in the
5972 configuration, restore the configuration, and then resize it
5973 back. We keep track of the prevailing height in these variables. */
5974 int previous_frame_lines = FRAME_LINES (f);
5975 int previous_frame_cols = FRAME_COLS (f);
5976 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5977 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5979 /* The mouse highlighting code could get screwed up
5980 if it runs during this. */
5981 BLOCK_INPUT;
5983 if (data->frame_lines != previous_frame_lines
5984 || data->frame_cols != previous_frame_cols)
5985 change_frame_size (f, data->frame_lines,
5986 data->frame_cols, 0, 0, 0);
5987 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5988 if (data->frame_menu_bar_lines
5989 != previous_frame_menu_bar_lines)
5990 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5991 make_number (0));
5992 #ifdef HAVE_WINDOW_SYSTEM
5993 if (data->frame_tool_bar_lines
5994 != previous_frame_tool_bar_lines)
5995 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5996 make_number (0));
5997 #endif
5998 #endif
6000 /* "Swap out" point from the selected window's buffer
6001 into the window itself. (Normally the pointm of the selected
6002 window holds garbage.) We do this now, before
6003 restoring the window contents, and prevent it from
6004 being done later on when we select a new window. */
6005 if (! NILP (XWINDOW (selected_window)->buffer))
6007 w = XWINDOW (selected_window);
6008 set_marker_both (w->pointm,
6009 w->buffer,
6010 BUF_PT (XBUFFER (w->buffer)),
6011 BUF_PT_BYTE (XBUFFER (w->buffer)));
6014 windows_or_buffers_changed++;
6015 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6017 /* Problem: Freeing all matrices and later allocating them again
6018 is a serious redisplay flickering problem. What we would
6019 really like to do is to free only those matrices not reused
6020 below. */
6021 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6022 leaf_windows
6023 = (struct window **) alloca (count_windows (root_window)
6024 * sizeof (struct window *));
6025 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6027 /* Kludge Alert!
6028 Mark all windows now on frame as "deleted".
6029 Restoring the new configuration "undeletes" any that are in it.
6031 Save their current buffers in their height fields, since we may
6032 need it later, if a buffer saved in the configuration is now
6033 dead. */
6034 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6036 for (k = 0; k < saved_windows->size; k++)
6038 p = SAVED_WINDOW_N (saved_windows, k);
6039 w = XWINDOW (p->window);
6040 w->next = Qnil;
6042 if (!NILP (p->parent))
6043 w->parent = SAVED_WINDOW_N (saved_windows,
6044 XFASTINT (p->parent))->window;
6045 else
6046 w->parent = Qnil;
6048 if (!NILP (p->prev))
6050 w->prev = SAVED_WINDOW_N (saved_windows,
6051 XFASTINT (p->prev))->window;
6052 XWINDOW (w->prev)->next = p->window;
6054 else
6056 w->prev = Qnil;
6057 if (!NILP (w->parent))
6059 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6061 XWINDOW (w->parent)->vchild = p->window;
6062 XWINDOW (w->parent)->hchild = Qnil;
6064 else
6066 XWINDOW (w->parent)->hchild = p->window;
6067 XWINDOW (w->parent)->vchild = Qnil;
6072 /* If we squirreled away the buffer in the window's height,
6073 restore it now. */
6074 if (BUFFERP (w->total_lines))
6075 w->buffer = w->total_lines;
6076 w->left_col = p->left_col;
6077 w->top_line = p->top_line;
6078 w->total_cols = p->total_cols;
6079 w->total_lines = p->total_lines;
6080 w->hscroll = p->hscroll;
6081 w->min_hscroll = p->min_hscroll;
6082 w->display_table = p->display_table;
6083 w->orig_top_line = p->orig_top_line;
6084 w->orig_total_lines = p->orig_total_lines;
6085 w->left_margin_cols = p->left_margin_cols;
6086 w->right_margin_cols = p->right_margin_cols;
6087 w->left_fringe_width = p->left_fringe_width;
6088 w->right_fringe_width = p->right_fringe_width;
6089 w->fringes_outside_margins = p->fringes_outside_margins;
6090 w->scroll_bar_width = p->scroll_bar_width;
6091 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6092 w->dedicated = p->dedicated;
6093 w->resize_proportionally = p->resize_proportionally;
6094 XSETFASTINT (w->last_modified, 0);
6095 XSETFASTINT (w->last_overlay_modified, 0);
6097 /* Reinstall the saved buffer and pointers into it. */
6098 if (NILP (p->buffer))
6099 w->buffer = p->buffer;
6100 else
6102 if (!NILP (XBUFFER (p->buffer)->name))
6103 /* If saved buffer is alive, install it. */
6105 w->buffer = p->buffer;
6106 w->start_at_line_beg = p->start_at_line_beg;
6107 set_marker_restricted (w->start, p->start, w->buffer);
6108 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6109 Fset_marker (XBUFFER (w->buffer)->mark,
6110 p->mark, w->buffer);
6112 /* As documented in Fcurrent_window_configuration, don't
6113 restore the location of point in the buffer which was
6114 current when the window configuration was recorded. */
6115 if (!EQ (p->buffer, new_current_buffer)
6116 && XBUFFER (p->buffer) == current_buffer)
6117 Fgoto_char (w->pointm);
6119 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6120 /* Else unless window has a live buffer, get one. */
6122 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6123 /* This will set the markers to beginning of visible
6124 range. */
6125 set_marker_restricted (w->start, make_number (0), w->buffer);
6126 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6127 w->start_at_line_beg = Qt;
6129 else
6130 /* Keeping window's old buffer; make sure the markers
6131 are real. */
6133 /* Set window markers at start of visible range. */
6134 if (XMARKER (w->start)->buffer == 0)
6135 set_marker_restricted (w->start, make_number (0),
6136 w->buffer);
6137 if (XMARKER (w->pointm)->buffer == 0)
6138 set_marker_restricted_both (w->pointm, w->buffer,
6139 BUF_PT (XBUFFER (w->buffer)),
6140 BUF_PT_BYTE (XBUFFER (w->buffer)));
6141 w->start_at_line_beg = Qt;
6146 FRAME_ROOT_WINDOW (f) = data->root_window;
6147 /* Prevent "swapping out point" in the old selected window
6148 using the buffer that has been restored into it.
6149 We already swapped out point that from that window's old buffer. */
6150 selected_window = Qnil;
6152 /* Arrange *not* to restore point in the buffer that was
6153 current when the window configuration was saved. */
6154 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6155 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6156 make_number (old_point),
6157 XWINDOW (data->current_window)->buffer);
6159 Fselect_window (data->current_window, Qnil);
6160 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6161 = selected_window;
6163 if (NILP (data->focus_frame)
6164 || (FRAMEP (data->focus_frame)
6165 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6166 Fredirect_frame_focus (frame, data->focus_frame);
6168 #if 0 /* I don't understand why this is needed, and it causes problems
6169 when the frame's old selected window has been deleted. */
6170 if (f != selected_frame && FRAME_WINDOW_P (f))
6171 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6172 0, 0, Qnil);
6173 #endif
6175 /* Set the screen height to the value it had before this function. */
6176 if (previous_frame_lines != FRAME_LINES (f)
6177 || previous_frame_cols != FRAME_COLS (f))
6178 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6179 0, 0, 0);
6180 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6181 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6182 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6183 make_number (0));
6184 #ifdef HAVE_WINDOW_SYSTEM
6185 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6186 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6187 make_number (0));
6188 #endif
6189 #endif
6191 /* Now, free glyph matrices in windows that were not reused. */
6192 for (i = n = 0; i < n_leaf_windows; ++i)
6194 if (NILP (leaf_windows[i]->buffer))
6196 /* Assert it's not reused as a combination. */
6197 xassert (NILP (leaf_windows[i]->hchild)
6198 && NILP (leaf_windows[i]->vchild));
6199 free_window_matrices (leaf_windows[i]);
6201 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6202 ++n;
6205 adjust_glyphs (f);
6207 UNBLOCK_INPUT;
6209 /* Fselect_window will have made f the selected frame, so we
6210 reselect the proper frame here. Fhandle_switch_frame will change the
6211 selected window too, but that doesn't make the call to
6212 Fselect_window above totally superfluous; it still sets f's
6213 selected window. */
6214 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6215 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6217 run_window_configuration_change_hook (f);
6220 if (!NILP (new_current_buffer))
6221 Fset_buffer (new_current_buffer);
6223 Vminibuf_scroll_window = data->minibuf_scroll_window;
6224 minibuf_selected_window = data->minibuf_selected_window;
6226 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6229 /* Mark all windows now on frame as deleted
6230 by setting their buffers to nil. */
6232 void
6233 delete_all_subwindows (register struct window *w)
6235 if (!NILP (w->next))
6236 delete_all_subwindows (XWINDOW (w->next));
6237 if (!NILP (w->vchild))
6238 delete_all_subwindows (XWINDOW (w->vchild));
6239 if (!NILP (w->hchild))
6240 delete_all_subwindows (XWINDOW (w->hchild));
6242 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6244 if (!NILP (w->buffer))
6245 unshow_buffer (w);
6247 /* We set all three of these fields to nil, to make sure that we can
6248 distinguish this dead window from any live window. Live leaf
6249 windows will have buffer set, and combination windows will have
6250 vchild or hchild set. */
6251 w->buffer = Qnil;
6252 w->vchild = Qnil;
6253 w->hchild = Qnil;
6255 Vwindow_list = Qnil;
6258 static int
6259 count_windows (register struct window *window)
6261 register int count = 1;
6262 if (!NILP (window->next))
6263 count += count_windows (XWINDOW (window->next));
6264 if (!NILP (window->vchild))
6265 count += count_windows (XWINDOW (window->vchild));
6266 if (!NILP (window->hchild))
6267 count += count_windows (XWINDOW (window->hchild));
6268 return count;
6272 /* Fill vector FLAT with leaf windows under W, starting at index I.
6273 Value is last index + 1. */
6275 static int
6276 get_leaf_windows (struct window *w, struct window **flat, int i)
6278 while (w)
6280 if (!NILP (w->hchild))
6281 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6282 else if (!NILP (w->vchild))
6283 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6284 else
6285 flat[i++] = w;
6287 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6290 return i;
6294 /* Return a pointer to the glyph W's physical cursor is on. Value is
6295 null if W's current matrix is invalid, so that no meaningfull glyph
6296 can be returned. */
6298 struct glyph *
6299 get_phys_cursor_glyph (struct window *w)
6301 struct glyph_row *row;
6302 struct glyph *glyph;
6304 if (w->phys_cursor.vpos >= 0
6305 && w->phys_cursor.vpos < w->current_matrix->nrows
6306 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6307 row->enabled_p)
6308 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6309 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6310 else
6311 glyph = NULL;
6313 return glyph;
6317 static int
6318 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
6320 register struct saved_window *p;
6321 register struct window *w;
6322 register Lisp_Object tem;
6324 for (;!NILP (window); window = w->next)
6326 p = SAVED_WINDOW_N (vector, i);
6327 w = XWINDOW (window);
6329 XSETFASTINT (w->temslot, i); i++;
6330 p->window = window;
6331 p->buffer = w->buffer;
6332 p->left_col = w->left_col;
6333 p->top_line = w->top_line;
6334 p->total_cols = w->total_cols;
6335 p->total_lines = w->total_lines;
6336 p->hscroll = w->hscroll;
6337 p->min_hscroll = w->min_hscroll;
6338 p->display_table = w->display_table;
6339 p->orig_top_line = w->orig_top_line;
6340 p->orig_total_lines = w->orig_total_lines;
6341 p->left_margin_cols = w->left_margin_cols;
6342 p->right_margin_cols = w->right_margin_cols;
6343 p->left_fringe_width = w->left_fringe_width;
6344 p->right_fringe_width = w->right_fringe_width;
6345 p->fringes_outside_margins = w->fringes_outside_margins;
6346 p->scroll_bar_width = w->scroll_bar_width;
6347 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6348 p->dedicated = w->dedicated;
6349 p->resize_proportionally = w->resize_proportionally;
6350 if (!NILP (w->buffer))
6352 /* Save w's value of point in the window configuration.
6353 If w is the selected window, then get the value of point
6354 from the buffer; pointm is garbage in the selected window. */
6355 if (EQ (window, selected_window))
6357 p->pointm = Fmake_marker ();
6358 set_marker_both (p->pointm, w->buffer,
6359 BUF_PT (XBUFFER (w->buffer)),
6360 BUF_PT_BYTE (XBUFFER (w->buffer)));
6362 else
6363 p->pointm = Fcopy_marker (w->pointm, Qnil);
6365 p->start = Fcopy_marker (w->start, Qnil);
6366 p->start_at_line_beg = w->start_at_line_beg;
6368 tem = XBUFFER (w->buffer)->mark;
6369 p->mark = Fcopy_marker (tem, Qnil);
6371 else
6373 p->pointm = Qnil;
6374 p->start = Qnil;
6375 p->mark = Qnil;
6376 p->start_at_line_beg = Qnil;
6379 if (NILP (w->parent))
6380 p->parent = Qnil;
6381 else
6382 p->parent = XWINDOW (w->parent)->temslot;
6384 if (NILP (w->prev))
6385 p->prev = Qnil;
6386 else
6387 p->prev = XWINDOW (w->prev)->temslot;
6389 if (!NILP (w->vchild))
6390 i = save_window_save (w->vchild, vector, i);
6391 if (!NILP (w->hchild))
6392 i = save_window_save (w->hchild, vector, i);
6395 return i;
6398 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6399 Scurrent_window_configuration, 0, 1, 0,
6400 doc: /* Return an object representing the current window configuration of FRAME.
6401 If FRAME is nil or omitted, use the selected frame.
6402 This describes the number of windows, their sizes and current buffers,
6403 and for each displayed buffer, where display starts, and the positions of
6404 point and mark. An exception is made for point in the current buffer:
6405 its value is -not- saved.
6406 This also records the currently selected frame, and FRAME's focus
6407 redirection (see `redirect-frame-focus'). */)
6408 (Lisp_Object frame)
6410 register Lisp_Object tem;
6411 register int n_windows;
6412 register struct save_window_data *data;
6413 register int i;
6414 FRAME_PTR f;
6416 if (NILP (frame))
6417 frame = selected_frame;
6418 CHECK_LIVE_FRAME (frame);
6419 f = XFRAME (frame);
6421 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6422 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6423 PVEC_WINDOW_CONFIGURATION);
6425 data->frame_cols = FRAME_COLS (f);
6426 data->frame_lines = FRAME_LINES (f);
6427 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6428 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6429 data->selected_frame = selected_frame;
6430 data->current_window = FRAME_SELECTED_WINDOW (f);
6431 XSETBUFFER (data->current_buffer, current_buffer);
6432 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6433 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6434 data->root_window = FRAME_ROOT_WINDOW (f);
6435 data->focus_frame = FRAME_FOCUS_FRAME (f);
6436 tem = Fmake_vector (make_number (n_windows), Qnil);
6437 data->saved_windows = tem;
6438 for (i = 0; i < n_windows; i++)
6439 XVECTOR (tem)->contents[i]
6440 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6441 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6442 XSETWINDOW_CONFIGURATION (tem, data);
6443 return (tem);
6446 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6447 0, UNEVALLED, 0,
6448 doc: /* Execute BODY, preserving window sizes and contents.
6449 Return the value of the last form in BODY.
6450 Restore which buffer appears in which window, where display starts,
6451 and the value of point and mark for each window.
6452 Also restore the choice of selected window.
6453 Also restore which buffer is current.
6454 Does not restore the value of point in current buffer.
6455 usage: (save-window-excursion BODY...) */)
6456 (Lisp_Object args)
6458 register Lisp_Object val;
6459 register int count = SPECPDL_INDEX ();
6461 record_unwind_protect (Fset_window_configuration,
6462 Fcurrent_window_configuration (Qnil));
6463 val = Fprogn (args);
6464 return unbind_to (count, val);
6469 /***********************************************************************
6470 Window Split Tree
6471 ***********************************************************************/
6473 static Lisp_Object
6474 window_tree (struct window *w)
6476 Lisp_Object tail = Qnil;
6477 Lisp_Object result = Qnil;
6479 while (w)
6481 Lisp_Object wn;
6483 XSETWINDOW (wn, w);
6484 if (!NILP (w->hchild))
6485 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6486 window_tree (XWINDOW (w->hchild))));
6487 else if (!NILP (w->vchild))
6488 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6489 window_tree (XWINDOW (w->vchild))));
6491 if (NILP (result))
6493 result = tail = Fcons (wn, Qnil);
6495 else
6497 XSETCDR (tail, Fcons (wn, Qnil));
6498 tail = XCDR (tail);
6501 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6504 return result;
6509 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6510 0, 1, 0,
6511 doc: /* Return the window tree for frame FRAME.
6513 The return value is a list of the form (ROOT MINI), where ROOT
6514 represents the window tree of the frame's root window, and MINI
6515 is the frame's minibuffer window.
6517 If the root window is not split, ROOT is the root window itself.
6518 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6519 horizontal split, and t for a vertical split, EDGES gives the combined
6520 size and position of the subwindows in the split, and the rest of the
6521 elements are the subwindows in the split. Each of the subwindows may
6522 again be a window or a list representing a window split, and so on.
6523 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6525 If FRAME is nil or omitted, return information on the currently
6526 selected frame. */)
6527 (Lisp_Object frame)
6529 FRAME_PTR f;
6531 if (NILP (frame))
6532 frame = selected_frame;
6534 CHECK_FRAME (frame);
6535 f = XFRAME (frame);
6537 if (!FRAME_LIVE_P (f))
6538 return Qnil;
6540 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6544 /***********************************************************************
6545 Marginal Areas
6546 ***********************************************************************/
6548 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6549 2, 3, 0,
6550 doc: /* Set width of marginal areas of window WINDOW.
6551 If WINDOW is nil, set margins of the currently selected window.
6552 Second arg LEFT-WIDTH specifies the number of character cells to
6553 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6554 does the same for the right marginal area. A nil width parameter
6555 means no margin. */)
6556 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6558 struct window *w = decode_window (window);
6560 /* Translate negative or zero widths to nil.
6561 Margins that are too wide have to be checked elsewhere. */
6563 if (!NILP (left_width))
6565 CHECK_NUMBER (left_width);
6566 if (XINT (left_width) <= 0)
6567 left_width = Qnil;
6570 if (!NILP (right_width))
6572 CHECK_NUMBER (right_width);
6573 if (XINT (right_width) <= 0)
6574 right_width = Qnil;
6577 if (!EQ (w->left_margin_cols, left_width)
6578 || !EQ (w->right_margin_cols, right_width))
6580 w->left_margin_cols = left_width;
6581 w->right_margin_cols = right_width;
6583 adjust_window_margins (w);
6585 ++windows_or_buffers_changed;
6586 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6589 return Qnil;
6593 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6594 0, 1, 0,
6595 doc: /* Get width of marginal areas of window WINDOW.
6596 If WINDOW is omitted or nil, use the currently selected window.
6597 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6598 If a marginal area does not exist, its width will be returned
6599 as nil. */)
6600 (Lisp_Object window)
6602 struct window *w = decode_window (window);
6603 return Fcons (w->left_margin_cols, w->right_margin_cols);
6608 /***********************************************************************
6609 Fringes
6610 ***********************************************************************/
6612 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6613 2, 4, 0,
6614 doc: /* Set the fringe widths of window WINDOW.
6615 If WINDOW is nil, set the fringe widths of the currently selected
6616 window.
6617 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6618 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6619 fringe width. If a fringe width arg is nil, that means to use the
6620 frame's default fringe width. Default fringe widths can be set with
6621 the command `set-fringe-style'.
6622 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6623 outside of the display margins. By default, fringes are drawn between
6624 display marginal areas and the text area. */)
6625 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
6627 struct window *w = decode_window (window);
6629 if (!NILP (left_width))
6630 CHECK_NATNUM (left_width);
6631 if (!NILP (right_width))
6632 CHECK_NATNUM (right_width);
6634 /* Do nothing on a tty. */
6635 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6636 && (!EQ (w->left_fringe_width, left_width)
6637 || !EQ (w->right_fringe_width, right_width)
6638 || !EQ (w->fringes_outside_margins, outside_margins)))
6640 w->left_fringe_width = left_width;
6641 w->right_fringe_width = right_width;
6642 w->fringes_outside_margins = outside_margins;
6644 adjust_window_margins (w);
6646 clear_glyph_matrix (w->current_matrix);
6647 w->window_end_valid = Qnil;
6649 ++windows_or_buffers_changed;
6650 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6653 return Qnil;
6657 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6658 0, 1, 0,
6659 doc: /* Get width of fringes of window WINDOW.
6660 If WINDOW is omitted or nil, use the currently selected window.
6661 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6662 (Lisp_Object window)
6664 struct window *w = decode_window (window);
6666 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6667 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6668 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6669 ? Qt : Qnil), Qnil)));
6674 /***********************************************************************
6675 Scroll bars
6676 ***********************************************************************/
6678 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6679 2, 4, 0,
6680 doc: /* Set width and type of scroll bars of window WINDOW.
6681 If window is nil, set scroll bars of the currently selected window.
6682 Second parameter WIDTH specifies the pixel width for the scroll bar;
6683 this is automatically adjusted to a multiple of the frame column width.
6684 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6685 bar: left, right, or nil.
6686 If WIDTH is nil, use the frame's scroll-bar width.
6687 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6688 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6689 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6691 struct window *w = decode_window (window);
6693 if (!NILP (width))
6695 CHECK_NATNUM (width);
6697 if (XINT (width) == 0)
6698 vertical_type = Qnil;
6701 if (!(NILP (vertical_type)
6702 || EQ (vertical_type, Qleft)
6703 || EQ (vertical_type, Qright)
6704 || EQ (vertical_type, Qt)))
6705 error ("Invalid type of vertical scroll bar");
6707 if (!EQ (w->scroll_bar_width, width)
6708 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6710 w->scroll_bar_width = width;
6711 w->vertical_scroll_bar_type = vertical_type;
6713 adjust_window_margins (w);
6715 clear_glyph_matrix (w->current_matrix);
6716 w->window_end_valid = Qnil;
6718 ++windows_or_buffers_changed;
6719 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6722 return Qnil;
6726 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6727 0, 1, 0,
6728 doc: /* Get width and type of scroll bars of window WINDOW.
6729 If WINDOW is omitted or nil, use the currently selected window.
6730 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6731 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6732 value. */)
6733 (Lisp_Object window)
6735 struct window *w = decode_window (window);
6736 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6737 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6738 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6739 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6740 Fcons (w->vertical_scroll_bar_type,
6741 Fcons (Qnil, Qnil))));
6746 /***********************************************************************
6747 Smooth scrolling
6748 ***********************************************************************/
6750 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6751 doc: /* Return the amount by which WINDOW is scrolled vertically.
6752 Use the selected window if WINDOW is nil or omitted.
6753 Normally, value is a multiple of the canonical character height of WINDOW;
6754 optional second arg PIXELS-P means value is measured in pixels. */)
6755 (Lisp_Object window, Lisp_Object pixels_p)
6757 Lisp_Object result;
6758 struct frame *f;
6759 struct window *w;
6761 if (NILP (window))
6762 window = selected_window;
6763 else
6764 CHECK_WINDOW (window);
6765 w = XWINDOW (window);
6766 f = XFRAME (w->frame);
6768 if (FRAME_WINDOW_P (f))
6769 result = (NILP (pixels_p)
6770 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6771 : make_number (-w->vscroll));
6772 else
6773 result = make_number (0);
6774 return result;
6778 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6779 2, 3, 0,
6780 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6781 WINDOW nil means use the selected window. Normally, VSCROLL is a
6782 non-negative multiple of the canonical character height of WINDOW;
6783 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6784 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6785 corresponds to an integral number of pixels. The return value is the
6786 result of this rounding.
6787 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6788 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6790 struct window *w;
6791 struct frame *f;
6793 if (NILP (window))
6794 window = selected_window;
6795 else
6796 CHECK_WINDOW (window);
6797 CHECK_NUMBER_OR_FLOAT (vscroll);
6799 w = XWINDOW (window);
6800 f = XFRAME (w->frame);
6802 if (FRAME_WINDOW_P (f))
6804 int old_dy = w->vscroll;
6806 w->vscroll = - (NILP (pixels_p)
6807 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6808 : XFLOATINT (vscroll));
6809 w->vscroll = min (w->vscroll, 0);
6811 if (w->vscroll != old_dy)
6813 /* Adjust glyph matrix of the frame if the virtual display
6814 area becomes larger than before. */
6815 if (w->vscroll < 0 && w->vscroll < old_dy)
6816 adjust_glyphs (f);
6818 /* Prevent redisplay shortcuts. */
6819 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6823 return Fwindow_vscroll (window, pixels_p);
6827 /* Call FN for all leaf windows on frame F. FN is called with the
6828 first argument being a pointer to the leaf window, and with
6829 additional argument USER_DATA. Stops when FN returns 0. */
6831 static void
6832 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6833 void *user_data)
6835 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6836 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6837 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6841 /* Helper function for foreach_window. Call FN for all leaf windows
6842 reachable from W. FN is called with the first argument being a
6843 pointer to the leaf window, and with additional argument USER_DATA.
6844 Stop when FN returns 0. Value is 0 if stopped by FN. */
6846 static int
6847 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6849 int cont;
6851 for (cont = 1; w && cont;)
6853 if (!NILP (w->hchild))
6854 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6855 else if (!NILP (w->vchild))
6856 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6857 else
6858 cont = fn (w, user_data);
6860 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6863 return cont;
6867 /* Freeze or unfreeze the window start of W unless it is a
6868 mini-window or the selected window. FREEZE_P non-null means freeze
6869 the window start. */
6871 static int
6872 freeze_window_start (struct window *w, void *freeze_p)
6874 if (MINI_WINDOW_P (w)
6875 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
6876 && (w == XWINDOW (selected_window)
6877 || (MINI_WINDOW_P (XWINDOW (selected_window))
6878 && ! NILP (Vminibuf_scroll_window)
6879 && w == XWINDOW (Vminibuf_scroll_window)))))
6880 freeze_p = NULL;
6882 w->frozen_window_start_p = freeze_p != NULL;
6883 return 1;
6887 /* Freeze or unfreeze the window starts of all leaf windows on frame
6888 F, except the selected window and a mini-window. FREEZE_P non-zero
6889 means freeze the window start. */
6891 void
6892 freeze_window_starts (struct frame *f, int freeze_p)
6894 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6898 /***********************************************************************
6899 Initialization
6900 ***********************************************************************/
6902 /* Return 1 if window configurations C1 and C2
6903 describe the same state of affairs. This is used by Fequal. */
6906 compare_window_configurations (Lisp_Object c1, Lisp_Object c2, int ignore_positions)
6908 register struct save_window_data *d1, *d2;
6909 struct Lisp_Vector *sw1, *sw2;
6910 int i;
6912 CHECK_WINDOW_CONFIGURATION (c1);
6913 CHECK_WINDOW_CONFIGURATION (c2);
6915 d1 = (struct save_window_data *) XVECTOR (c1);
6916 d2 = (struct save_window_data *) XVECTOR (c2);
6917 sw1 = XVECTOR (d1->saved_windows);
6918 sw2 = XVECTOR (d2->saved_windows);
6920 if (d1->frame_cols != d2->frame_cols)
6921 return 0;
6922 if (d1->frame_lines != d2->frame_lines)
6923 return 0;
6924 if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines)
6925 return 0;
6926 if (! EQ (d1->selected_frame, d2->selected_frame))
6927 return 0;
6928 /* Don't compare the current_window field directly.
6929 Instead see w1_is_current and w2_is_current, below. */
6930 if (! EQ (d1->current_buffer, d2->current_buffer))
6931 return 0;
6932 if (! ignore_positions)
6934 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6935 return 0;
6936 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6937 return 0;
6939 /* Don't compare the root_window field.
6940 We don't require the two configurations
6941 to use the same window object,
6942 and the two root windows must be equivalent
6943 if everything else compares equal. */
6944 if (! EQ (d1->focus_frame, d2->focus_frame))
6945 return 0;
6947 /* Verify that the two confis have the same number of windows. */
6948 if (sw1->size != sw2->size)
6949 return 0;
6951 for (i = 0; i < sw1->size; i++)
6953 struct saved_window *p1, *p2;
6954 int w1_is_current, w2_is_current;
6956 p1 = SAVED_WINDOW_N (sw1, i);
6957 p2 = SAVED_WINDOW_N (sw2, i);
6959 /* Verify that the current windows in the two
6960 configurations correspond to each other. */
6961 w1_is_current = EQ (d1->current_window, p1->window);
6962 w2_is_current = EQ (d2->current_window, p2->window);
6964 if (w1_is_current != w2_is_current)
6965 return 0;
6967 /* Verify that the corresponding windows do match. */
6968 if (! EQ (p1->buffer, p2->buffer))
6969 return 0;
6970 if (! EQ (p1->left_col, p2->left_col))
6971 return 0;
6972 if (! EQ (p1->top_line, p2->top_line))
6973 return 0;
6974 if (! EQ (p1->total_cols, p2->total_cols))
6975 return 0;
6976 if (! EQ (p1->total_lines, p2->total_lines))
6977 return 0;
6978 if (! EQ (p1->display_table, p2->display_table))
6979 return 0;
6980 if (! EQ (p1->parent, p2->parent))
6981 return 0;
6982 if (! EQ (p1->prev, p2->prev))
6983 return 0;
6984 if (! ignore_positions)
6986 if (! EQ (p1->hscroll, p2->hscroll))
6987 return 0;
6988 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6989 return 0;
6990 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6991 return 0;
6992 if (NILP (Fequal (p1->start, p2->start)))
6993 return 0;
6994 if (NILP (Fequal (p1->pointm, p2->pointm)))
6995 return 0;
6996 if (NILP (Fequal (p1->mark, p2->mark)))
6997 return 0;
6999 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7000 return 0;
7001 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7002 return 0;
7003 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7004 return 0;
7005 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7006 return 0;
7007 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7008 return 0;
7009 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7010 return 0;
7011 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7012 return 0;
7015 return 1;
7018 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7019 Scompare_window_configurations, 2, 2, 0,
7020 doc: /* Compare two window configurations as regards the structure of windows.
7021 This function ignores details such as the values of point and mark
7022 and scrolling positions. */)
7023 (Lisp_Object x, Lisp_Object y)
7025 if (compare_window_configurations (x, y, 1))
7026 return Qt;
7027 return Qnil;
7030 void
7031 init_window_once (void)
7033 struct frame *f = make_initial_frame ();
7034 XSETFRAME (selected_frame, f);
7035 Vterminal_frame = selected_frame;
7036 minibuf_window = f->minibuffer_window;
7037 selected_window = f->selected_window;
7038 last_nonminibuf_frame = f;
7040 window_initialized = 1;
7043 void
7044 init_window (void)
7046 Vwindow_list = Qnil;
7049 void
7050 syms_of_window (void)
7052 Qscroll_up = intern_c_string ("scroll-up");
7053 staticpro (&Qscroll_up);
7055 Qscroll_down = intern_c_string ("scroll-down");
7056 staticpro (&Qscroll_down);
7058 Qscroll_command = intern_c_string ("scroll-command");
7059 staticpro (&Qscroll_command);
7061 Fput (Qscroll_up, Qscroll_command, Qt);
7062 Fput (Qscroll_down, Qscroll_command, Qt);
7064 Qwindow_size_fixed = intern_c_string ("window-size-fixed");
7065 staticpro (&Qwindow_size_fixed);
7066 Fset (Qwindow_size_fixed, Qnil);
7068 staticpro (&Qwindow_configuration_change_hook);
7069 Qwindow_configuration_change_hook
7070 = intern_c_string ("window-configuration-change-hook");
7072 Qwindowp = intern_c_string ("windowp");
7073 staticpro (&Qwindowp);
7075 Qwindow_configuration_p = intern_c_string ("window-configuration-p");
7076 staticpro (&Qwindow_configuration_p);
7078 Qwindow_live_p = intern_c_string ("window-live-p");
7079 staticpro (&Qwindow_live_p);
7081 Qdisplay_buffer = intern_c_string ("display-buffer");
7082 staticpro (&Qdisplay_buffer);
7084 Qtemp_buffer_show_hook = intern_c_string ("temp-buffer-show-hook");
7085 staticpro (&Qtemp_buffer_show_hook);
7087 staticpro (&Vwindow_list);
7089 minibuf_selected_window = Qnil;
7090 staticpro (&minibuf_selected_window);
7092 window_scroll_pixel_based_preserve_x = -1;
7093 window_scroll_pixel_based_preserve_y = -1;
7094 window_scroll_preserve_hpos = -1;
7095 window_scroll_preserve_vpos = -1;
7097 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7098 doc: /* Non-nil means call as function to display a help buffer.
7099 The function is called with one argument, the buffer to be displayed.
7100 Used by `with-output-to-temp-buffer'.
7101 If this function is used, then it must do the entire job of showing
7102 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7103 Vtemp_buffer_show_function = Qnil;
7105 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7106 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7107 Vminibuf_scroll_window = Qnil;
7109 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7110 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7111 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7112 is displayed in the `mode-line' face. */);
7113 mode_line_in_non_selected_windows = 1;
7115 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7116 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7117 Vother_window_scroll_buffer = Qnil;
7119 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7120 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7121 auto_window_vscroll_p = 1;
7123 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7124 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7125 next_screen_context_lines = 2;
7127 DEFVAR_INT ("window-min-height", &window_min_height,
7128 doc: /* Allow deleting windows less than this tall.
7129 The value is measured in line units. If a window wants a modeline it
7130 is counted as one line.
7132 Emacs honors settings of this variable when enlarging or shrinking
7133 windows vertically. A value less than 1 is invalid. */);
7134 window_min_height = 4;
7136 DEFVAR_INT ("window-min-width", &window_min_width,
7137 doc: /* Allow deleting windows less than this wide.
7138 The value is measured in characters and includes any fringes or
7139 the scrollbar.
7141 Emacs honors settings of this variable when enlarging or shrinking
7142 windows horizontally. A value less than 2 is invalid. */);
7143 window_min_width = 10;
7145 DEFVAR_LISP ("scroll-preserve-screen-position",
7146 &Vscroll_preserve_screen_position,
7147 doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
7148 A value of nil means point does not keep its screen position except
7149 at the scroll margin or window boundary respectively.
7150 A value of t means point keeps its screen position if the scroll
7151 command moved it vertically out of the window, e.g. when scrolling
7152 by full screens.
7153 Any other value means point always keeps its screen position.
7154 Scroll commands should have the `scroll-command' property
7155 on their symbols to be controlled by this variable. */);
7156 Vscroll_preserve_screen_position = Qnil;
7158 DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type,
7159 doc: /* Type of marker to use for `window-point'. */);
7160 Vwindow_point_insertion_type = Qnil;
7162 DEFVAR_LISP ("window-configuration-change-hook",
7163 &Vwindow_configuration_change_hook,
7164 doc: /* Functions to call when window configuration changes.
7165 The buffer-local part is run once per window, with the relevant window
7166 selected; while the global part is run only once for the modified frame,
7167 with the relevant frame selected. */);
7168 Vwindow_configuration_change_hook = Qnil;
7170 DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay,
7171 doc: /* If non-nil, then the `recenter' command with a nil argument
7172 will redraw the entire frame; the special value `tty' causes the
7173 frame to be redrawn only if it is a tty frame. */);
7174 Vrecenter_redisplay = Qtty;
7177 defsubr (&Sselected_window);
7178 defsubr (&Sminibuffer_window);
7179 defsubr (&Swindow_minibuffer_p);
7180 defsubr (&Swindowp);
7181 defsubr (&Swindow_live_p);
7182 defsubr (&Spos_visible_in_window_p);
7183 defsubr (&Swindow_line_height);
7184 defsubr (&Swindow_buffer);
7185 defsubr (&Swindow_height);
7186 defsubr (&Swindow_width);
7187 defsubr (&Swindow_full_width_p);
7188 defsubr (&Swindow_hscroll);
7189 defsubr (&Sset_window_hscroll);
7190 defsubr (&Swindow_redisplay_end_trigger);
7191 defsubr (&Sset_window_redisplay_end_trigger);
7192 defsubr (&Swindow_edges);
7193 defsubr (&Swindow_pixel_edges);
7194 defsubr (&Swindow_absolute_pixel_edges);
7195 defsubr (&Swindow_inside_edges);
7196 defsubr (&Swindow_inside_pixel_edges);
7197 defsubr (&Swindow_inside_absolute_pixel_edges);
7198 defsubr (&Scoordinates_in_window_p);
7199 defsubr (&Swindow_at);
7200 defsubr (&Swindow_point);
7201 defsubr (&Swindow_start);
7202 defsubr (&Swindow_end);
7203 defsubr (&Sset_window_point);
7204 defsubr (&Sset_window_start);
7205 defsubr (&Swindow_dedicated_p);
7206 defsubr (&Sset_window_dedicated_p);
7207 defsubr (&Swindow_display_table);
7208 defsubr (&Sset_window_display_table);
7209 defsubr (&Snext_window);
7210 defsubr (&Sprevious_window);
7211 defsubr (&Sother_window);
7212 defsubr (&Sget_lru_window);
7213 defsubr (&Swindow_use_time);
7214 defsubr (&Sget_largest_window);
7215 defsubr (&Sget_buffer_window);
7216 defsubr (&Sdelete_other_windows);
7217 defsubr (&Sdelete_windows_on);
7218 defsubr (&Sreplace_buffer_in_windows);
7219 defsubr (&Sdelete_window);
7220 defsubr (&Sset_window_buffer);
7221 defsubr (&Sselect_window);
7222 defsubr (&Sforce_window_update);
7223 defsubr (&Ssplit_window);
7224 defsubr (&Senlarge_window);
7225 defsubr (&Sshrink_window);
7226 defsubr (&Sadjust_window_trailing_edge);
7227 defsubr (&Sscroll_up);
7228 defsubr (&Sscroll_down);
7229 defsubr (&Sscroll_left);
7230 defsubr (&Sscroll_right);
7231 defsubr (&Sother_window_for_scrolling);
7232 defsubr (&Sscroll_other_window);
7233 defsubr (&Sminibuffer_selected_window);
7234 defsubr (&Srecenter);
7235 defsubr (&Swindow_text_height);
7236 defsubr (&Smove_to_window_line);
7237 defsubr (&Swindow_configuration_p);
7238 defsubr (&Swindow_configuration_frame);
7239 defsubr (&Sset_window_configuration);
7240 defsubr (&Scurrent_window_configuration);
7241 defsubr (&Ssave_window_excursion);
7242 defsubr (&Swindow_tree);
7243 defsubr (&Sset_window_margins);
7244 defsubr (&Swindow_margins);
7245 defsubr (&Sset_window_fringes);
7246 defsubr (&Swindow_fringes);
7247 defsubr (&Sset_window_scroll_bars);
7248 defsubr (&Swindow_scroll_bars);
7249 defsubr (&Swindow_vscroll);
7250 defsubr (&Sset_window_vscroll);
7251 defsubr (&Scompare_window_configurations);
7252 defsubr (&Swindow_list);
7253 defsubr (&Swindow_parameters);
7254 defsubr (&Swindow_parameter);
7255 defsubr (&Sset_window_parameter);
7259 void
7260 keys_of_window (void)
7262 initial_define_key (control_x_map, '1', "delete-other-windows");
7263 initial_define_key (control_x_map, '2', "split-window");
7264 initial_define_key (control_x_map, '0', "delete-window");
7265 initial_define_key (control_x_map, 'o', "other-window");
7266 initial_define_key (control_x_map, '^', "enlarge-window");
7267 initial_define_key (control_x_map, '<', "scroll-left");
7268 initial_define_key (control_x_map, '>', "scroll-right");
7270 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
7271 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7272 initial_define_key (meta_map, 'v', "scroll-down-command");
7275 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7276 (do not change this comment) */