Add ability to put Gtk+ tool bar on the left/right/bottom or top. Default top.
[emacs.git] / src / window.c
blob3c556fff69b813255207f321674515646d1a48e0
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
55 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
56 Lisp_Object Qdisplay_buffer;
57 Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
58 Lisp_Object Qwindow_size_fixed;
60 extern Lisp_Object Qleft_margin, Qright_margin;
62 static int displayed_window_lines (struct window *);
63 static struct window *decode_window (Lisp_Object);
64 static int count_windows (struct window *);
65 static int get_leaf_windows (struct window *, struct window **, int);
66 static void window_scroll (Lisp_Object, int, int, int);
67 static void window_scroll_pixel_based (Lisp_Object, int, int, int);
68 static void window_scroll_line_based (Lisp_Object, int, int, int);
69 static int window_min_size_1 (struct window *, int, int);
70 static int window_min_size_2 (struct window *, int, int);
71 static int window_min_size (struct window *, int, int, int, int *);
72 static void size_window (Lisp_Object, int, int, int, int, int);
73 static int freeze_window_start (struct window *, void *);
74 static int window_fixed_size_p (struct window *, int, int);
75 static void enlarge_window (Lisp_Object, int, int);
76 static Lisp_Object window_list (void);
77 static int add_window_to_list (struct window *, void *);
78 static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
79 Lisp_Object);
80 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
81 Lisp_Object, int);
82 static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
83 Lisp_Object *);
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 extern EMACS_INT scroll_margin;
196 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
198 /* If non-nil, then the `recenter' command with a nil argument
199 the entire frame to be redrawn; the special value `tty' causes the
200 frame to be redrawn only if it is a tty frame. */
202 static Lisp_Object Vrecenter_redisplay;
203 extern Lisp_Object Qtty;
206 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
207 doc: /* Return t if OBJECT is a window. */)
208 (Lisp_Object object)
210 return WINDOWP (object) ? Qt : Qnil;
213 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
214 doc: /* Return t if OBJECT is a window which is currently visible. */)
215 (Lisp_Object object)
217 return WINDOW_LIVE_P (object) ? Qt : Qnil;
220 Lisp_Object
221 make_window (void)
223 Lisp_Object val;
224 register struct window *p;
226 p = allocate_window ();
227 ++sequence_number;
228 XSETFASTINT (p->sequence_number, sequence_number);
229 XSETFASTINT (p->left_col, 0);
230 XSETFASTINT (p->top_line, 0);
231 XSETFASTINT (p->total_lines, 0);
232 XSETFASTINT (p->total_cols, 0);
233 XSETFASTINT (p->hscroll, 0);
234 XSETFASTINT (p->min_hscroll, 0);
235 p->orig_top_line = p->orig_total_lines = Qnil;
236 p->start = Fmake_marker ();
237 p->pointm = Fmake_marker ();
238 XSETFASTINT (p->use_time, 0);
239 p->frame = Qnil;
240 p->display_table = Qnil;
241 p->dedicated = Qnil;
242 p->window_parameters = Qnil;
243 p->pseudo_window_p = 0;
244 memset (&p->cursor, 0, sizeof (p->cursor));
245 memset (&p->last_cursor, 0, sizeof (p->last_cursor));
246 memset (&p->phys_cursor, 0, sizeof (p->phys_cursor));
247 p->desired_matrix = p->current_matrix = 0;
248 p->nrows_scale_factor = p->ncols_scale_factor = 1;
249 p->phys_cursor_type = -1;
250 p->phys_cursor_width = -1;
251 p->must_be_updated_p = 0;
252 XSETFASTINT (p->window_end_vpos, 0);
253 XSETFASTINT (p->window_end_pos, 0);
254 p->window_end_valid = Qnil;
255 p->vscroll = 0;
256 XSETWINDOW (val, p);
257 XSETFASTINT (p->last_point, 0);
258 p->frozen_window_start_p = 0;
259 p->last_cursor_off_p = p->cursor_off_p = 0;
260 p->left_margin_cols = Qnil;
261 p->right_margin_cols = Qnil;
262 p->left_fringe_width = Qnil;
263 p->right_fringe_width = Qnil;
264 p->fringes_outside_margins = Qnil;
265 p->scroll_bar_width = Qnil;
266 p->vertical_scroll_bar_type = Qt;
267 p->resize_proportionally = Qnil;
269 Vwindow_list = Qnil;
270 return val;
273 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
274 doc: /* Return the window that the cursor now appears in and commands apply to. */)
275 (void)
277 return selected_window;
280 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
281 doc: /* Return the window used now for minibuffers.
282 If the optional argument FRAME is specified, return the minibuffer window
283 used by that frame. */)
284 (Lisp_Object frame)
286 if (NILP (frame))
287 frame = selected_frame;
288 CHECK_LIVE_FRAME (frame);
289 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
292 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
293 doc: /* Return non-nil if WINDOW is a minibuffer window.
294 WINDOW defaults to the selected window. */)
295 (Lisp_Object window)
297 struct window *w = decode_window (window);
298 return MINI_WINDOW_P (w) ? Qt : Qnil;
302 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
303 Spos_visible_in_window_p, 0, 3, 0,
304 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
305 Return nil if that position is scrolled vertically out of view.
306 If a character is only partially visible, nil is returned, unless the
307 optional argument PARTIALLY is non-nil.
308 If POS is only out of view because of horizontal scrolling, return non-nil.
309 If POS is t, it specifies the position of the last visible glyph in WINDOW.
310 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
312 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
313 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
314 where X and Y are the pixel coordinates relative to the top left corner
315 of the window. The remaining elements are omitted if the character after
316 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
317 off-window at the top and bottom of the row, ROWH is the height of the
318 display row, and VPOS is the row number (0-based) containing POS. */)
319 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
321 register struct window *w;
322 register int posint;
323 register struct buffer *buf;
324 struct text_pos top;
325 Lisp_Object in_window = Qnil;
326 int rtop, rbot, rowh, vpos, fully_p = 1;
327 int x, y;
329 w = decode_window (window);
330 buf = XBUFFER (w->buffer);
331 SET_TEXT_POS_FROM_MARKER (top, w->start);
333 if (EQ (pos, Qt))
334 posint = -1;
335 else if (!NILP (pos))
337 CHECK_NUMBER_COERCE_MARKER (pos);
338 posint = XINT (pos);
340 else if (w == XWINDOW (selected_window))
341 posint = PT;
342 else
343 posint = XMARKER (w->pointm)->charpos;
345 /* If position is above window start or outside buffer boundaries,
346 or if window start is out of range, position is not visible. */
347 if ((EQ (pos, Qt)
348 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
349 && CHARPOS (top) >= BUF_BEGV (buf)
350 && CHARPOS (top) <= BUF_ZV (buf)
351 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
352 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
353 in_window = Qt;
355 if (!NILP (in_window) && !NILP (partially))
357 Lisp_Object part = Qnil;
358 if (!fully_p)
359 part = list4 (make_number (rtop), make_number (rbot),
360 make_number (rowh), make_number (vpos));
361 in_window = Fcons (make_number (x),
362 Fcons (make_number (y), part));
365 return in_window;
368 DEFUN ("window-line-height", Fwindow_line_height,
369 Swindow_line_height, 0, 2, 0,
370 doc: /* Return height in pixels of text line LINE in window WINDOW.
371 If WINDOW is nil or omitted, use selected window.
373 Return height of current line if LINE is omitted or nil. Return height of
374 header or mode line if LINE is `header-line' and `mode-line'.
375 Otherwise, LINE is a text line number starting from 0. A negative number
376 counts from the end of the window.
378 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
379 in pixels of the visible part of the line, VPOS and YPOS are the
380 vertical position in lines and pixels of the line, relative to the top
381 of the first text line, and OFFBOT is the number of off-window pixels at
382 the bottom of the text line. If there are off-window pixels at the top
383 of the (first) text line, YPOS is negative.
385 Return nil if window display is not up-to-date. In that case, use
386 `pos-visible-in-window-p' to obtain the information. */)
387 (Lisp_Object line, Lisp_Object window)
389 register struct window *w;
390 register struct buffer *b;
391 struct glyph_row *row, *end_row;
392 int max_y, crop, i, n;
394 w = decode_window (window);
396 if (noninteractive
397 || w->pseudo_window_p)
398 return Qnil;
400 CHECK_BUFFER (w->buffer);
401 b = XBUFFER (w->buffer);
403 /* Fail if current matrix is not up-to-date. */
404 if (NILP (w->window_end_valid)
405 || current_buffer->clip_changed
406 || current_buffer->prevent_redisplay_optimizations_p
407 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
408 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
409 return Qnil;
411 if (NILP (line))
413 i = w->cursor.vpos;
414 if (i < 0 || i >= w->current_matrix->nrows
415 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
416 return Qnil;
417 max_y = window_text_bottom_y (w);
418 goto found_row;
421 if (EQ (line, Qheader_line))
423 if (!WINDOW_WANTS_HEADER_LINE_P (w))
424 return Qnil;
425 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
426 if (!row->enabled_p)
427 return Qnil;
428 return list4 (make_number (row->height),
429 make_number (0), make_number (0),
430 make_number (0));
433 if (EQ (line, Qmode_line))
435 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
436 if (!row->enabled_p)
437 return Qnil;
438 return list4 (make_number (row->height),
439 make_number (0), /* not accurate */
440 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
441 + window_text_bottom_y (w)),
442 make_number (0));
445 CHECK_NUMBER (line);
446 n = XINT (line);
448 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
449 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
450 max_y = window_text_bottom_y (w);
451 i = 0;
453 while ((n < 0 || i < n)
454 && row <= end_row && row->enabled_p
455 && row->y + row->height < max_y)
456 row++, i++;
458 if (row > end_row || !row->enabled_p)
459 return Qnil;
461 if (++n < 0)
463 if (-n > i)
464 return Qnil;
465 row += n;
466 i += n;
469 found_row:
470 crop = max (0, (row->y + row->height) - max_y);
471 return list4 (make_number (row->height + min (0, row->y) - crop),
472 make_number (i),
473 make_number (row->y),
474 make_number (crop));
479 static struct window *
480 decode_window (register Lisp_Object window)
482 if (NILP (window))
483 return XWINDOW (selected_window);
485 CHECK_LIVE_WINDOW (window);
486 return XWINDOW (window);
489 static struct window *
490 decode_any_window (register Lisp_Object window)
492 if (NILP (window))
493 return XWINDOW (selected_window);
495 CHECK_WINDOW (window);
496 return XWINDOW (window);
499 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
500 doc: /* Return the buffer that WINDOW is displaying.
501 WINDOW defaults to the selected window. */)
502 (Lisp_Object window)
504 return decode_window (window)->buffer;
507 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
508 doc: /* Return the number of lines in WINDOW.
509 WINDOW defaults to the selected window.
511 The return value includes WINDOW's mode line and header line, if any.
513 Note: The function does not take into account the value of `line-spacing'
514 when calculating the number of lines in WINDOW. */)
515 (Lisp_Object window)
517 return decode_any_window (window)->total_lines;
520 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
521 doc: /* Return the number of display columns in WINDOW.
522 WINDOW defaults to the selected window.
524 Note: The return value is the number of columns available for text in
525 WINDOW. If you want to find out how many columns WINDOW takes up, use
526 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
527 (Lisp_Object window)
529 return make_number (window_box_text_cols (decode_any_window (window)));
532 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
533 doc: /* Return t if WINDOW is as wide as its frame.
534 WINDOW defaults to the selected window. */)
535 (Lisp_Object window)
537 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
540 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
541 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
542 WINDOW defaults to the selected window. */)
543 (Lisp_Object window)
545 return decode_window (window)->hscroll;
548 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
549 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
550 Return NCOL. NCOL should be zero or positive.
552 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
553 window so that the location of point moves off-window. */)
554 (Lisp_Object window, Lisp_Object ncol)
556 struct window *w = decode_window (window);
557 int hscroll;
559 CHECK_NUMBER (ncol);
560 hscroll = max (0, XINT (ncol));
562 /* Prevent redisplay shortcuts when changing the hscroll. */
563 if (XINT (w->hscroll) != hscroll)
564 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
566 w->hscroll = make_number (hscroll);
567 return ncol;
570 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
571 Swindow_redisplay_end_trigger, 0, 1, 0,
572 doc: /* Return WINDOW's redisplay end trigger value.
573 WINDOW defaults to the selected window.
574 See `set-window-redisplay-end-trigger' for more information. */)
575 (Lisp_Object window)
577 return decode_window (window)->redisplay_end_trigger;
580 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
581 Sset_window_redisplay_end_trigger, 2, 2, 0,
582 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
583 VALUE should be a buffer position (typically a marker) or nil.
584 If it is a buffer position, then if redisplay in WINDOW reaches a position
585 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
586 with two arguments: WINDOW, and the end trigger value.
587 Afterwards the end-trigger value is reset to nil. */)
588 (register Lisp_Object window, Lisp_Object value)
590 register struct window *w;
592 w = decode_window (window);
593 w->redisplay_end_trigger = value;
594 return value;
597 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
598 doc: /* Return a list of the edge coordinates of WINDOW.
599 The list has the form (LEFT TOP RIGHT BOTTOM).
600 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
601 all relative to 0, 0 at top left corner of frame.
603 RIGHT is one more than the rightmost column occupied by WINDOW.
604 BOTTOM is one more than the bottommost row occupied by WINDOW.
605 The edges include the space used by WINDOW's scroll bar, display
606 margins, fringes, header line, and/or mode line. For the edges of
607 just the text area, use `window-inside-edges'. */)
608 (Lisp_Object window)
610 register struct window *w = decode_any_window (window);
612 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
613 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
614 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
615 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
616 Qnil))));
619 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
620 doc: /* Return a list of the edge pixel coordinates of WINDOW.
621 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
622 the top left corner of the frame.
624 RIGHT is one more than the rightmost x position occupied by WINDOW.
625 BOTTOM is one more than the bottommost y position occupied by WINDOW.
626 The pixel edges include the space used by WINDOW's scroll bar, display
627 margins, fringes, header line, and/or mode line. For the pixel edges
628 of just the text area, use `window-inside-pixel-edges'. */)
629 (Lisp_Object window)
631 register struct window *w = decode_any_window (window);
633 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
634 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
635 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
636 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
637 Qnil))));
640 static void
641 calc_absolute_offset(struct window *w, int *add_x, int *add_y)
643 struct frame *f = XFRAME (w->frame);
644 *add_y = f->top_pos;
645 #ifdef FRAME_MENUBAR_HEIGHT
646 *add_y += FRAME_MENUBAR_HEIGHT (f);
647 #endif
648 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
649 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
650 #elif FRAME_TOOLBAR_HEIGHT
651 *add_y += FRAME_TOOLBAR_HEIGHT (f);
652 #endif
653 #ifdef FRAME_NS_TITLEBAR_HEIGHT
654 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
655 #endif
656 *add_x = f->left_pos;
657 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
658 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
659 #endif
662 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
663 Swindow_absolute_pixel_edges, 0, 1, 0,
664 doc: /* Return a list of the edge pixel coordinates of WINDOW.
665 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
666 the top left corner of the display.
668 RIGHT is one more than the rightmost x position occupied by WINDOW.
669 BOTTOM is one more than the bottommost y position occupied by WINDOW.
670 The pixel edges include the space used by WINDOW's scroll bar, display
671 margins, fringes, header line, and/or mode line. For the pixel edges
672 of just the text area, use `window-inside-absolute-pixel-edges'. */)
673 (Lisp_Object window)
675 register struct window *w = decode_any_window (window);
676 int add_x, add_y;
677 calc_absolute_offset (w, &add_x, &add_y);
679 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
680 Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
681 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
682 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
683 Qnil))));
686 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
687 doc: /* Return a list of the edge coordinates of WINDOW.
688 The list has the form (LEFT TOP RIGHT BOTTOM).
689 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
690 all relative to 0, 0 at top left corner of frame.
692 RIGHT is one more than the rightmost column of WINDOW's text area.
693 BOTTOM is one more than the bottommost row of WINDOW's text area.
694 The inside edges do not include the space used by the WINDOW's scroll
695 bar, display margins, fringes, header line, and/or mode line. */)
696 (Lisp_Object window)
698 register struct window *w = decode_any_window (window);
700 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
701 + WINDOW_LEFT_MARGIN_COLS (w)
702 + WINDOW_LEFT_FRINGE_COLS (w)),
703 make_number (WINDOW_TOP_EDGE_LINE (w)
704 + WINDOW_HEADER_LINE_LINES (w)),
705 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
706 - WINDOW_RIGHT_MARGIN_COLS (w)
707 - WINDOW_RIGHT_FRINGE_COLS (w)),
708 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
709 - WINDOW_MODE_LINE_LINES (w)));
712 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
713 doc: /* Return a list of the edge pixel coordinates of WINDOW.
714 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
715 the top left corner of the frame.
717 RIGHT is one more than the rightmost x position of WINDOW's text area.
718 BOTTOM is one more than the bottommost y position of WINDOW's text area.
719 The inside edges do not include the space used by WINDOW's scroll bar,
720 display margins, fringes, header line, and/or mode line. */)
721 (Lisp_Object window)
723 register struct window *w = decode_any_window (window);
725 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
726 + WINDOW_LEFT_MARGIN_WIDTH (w)
727 + WINDOW_LEFT_FRINGE_WIDTH (w)),
728 make_number (WINDOW_TOP_EDGE_Y (w)
729 + WINDOW_HEADER_LINE_HEIGHT (w)),
730 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
731 - WINDOW_RIGHT_MARGIN_WIDTH (w)
732 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
733 make_number (WINDOW_BOTTOM_EDGE_Y (w)
734 - WINDOW_MODE_LINE_HEIGHT (w)));
737 DEFUN ("window-inside-absolute-pixel-edges",
738 Fwindow_inside_absolute_pixel_edges,
739 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
740 doc: /* Return a list of the edge pixel coordinates of WINDOW.
741 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
742 the top left corner of the display.
744 RIGHT is one more than the rightmost x position of WINDOW's text area.
745 BOTTOM is one more than the bottommost y position of WINDOW's text area.
746 The inside edges do not include the space used by WINDOW's scroll bar,
747 display margins, fringes, header line, and/or mode line. */)
748 (Lisp_Object window)
750 register struct window *w = decode_any_window (window);
751 int add_x, add_y;
752 calc_absolute_offset (w, &add_x, &add_y);
754 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
755 + WINDOW_LEFT_MARGIN_WIDTH (w)
756 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
757 make_number (WINDOW_TOP_EDGE_Y (w)
758 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
759 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
760 - WINDOW_RIGHT_MARGIN_WIDTH (w)
761 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
762 make_number (WINDOW_BOTTOM_EDGE_Y (w)
763 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
766 /* Test if the character at column *X, row *Y is within window W.
767 If it is not, return ON_NOTHING;
768 if it is in the window's text area,
769 set *x and *y to its location relative to the upper left corner
770 of the window, and
771 return ON_TEXT;
772 if it is on the window's modeline, return ON_MODE_LINE;
773 if it is on the border between the window and its right sibling,
774 return ON_VERTICAL_BORDER.
775 if it is on a scroll bar,
776 return ON_SCROLL_BAR.
777 if it is on the window's top line, return ON_HEADER_LINE;
778 if it is in left or right fringe of the window,
779 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
780 to window-relative coordinates;
781 if it is in the marginal area to the left/right of the window,
782 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
783 to window-relative coordinates.
785 X and Y are frame relative pixel coordinates. */
787 static enum window_part
788 coordinates_in_window (register struct window *w, register int *x, register int *y)
790 struct frame *f = XFRAME (WINDOW_FRAME (w));
791 int left_x, right_x, top_y, bottom_y;
792 enum window_part part;
793 int ux = FRAME_COLUMN_WIDTH (f);
794 int x0 = WINDOW_LEFT_EDGE_X (w);
795 int x1 = WINDOW_RIGHT_EDGE_X (w);
796 /* The width of the area where the vertical line can be dragged.
797 (Between mode lines for instance. */
798 int grabbable_width = ux;
799 int lmargin_width, rmargin_width, text_left, text_right;
801 /* In what's below, we subtract 1 when computing right_x because we
802 want the rightmost pixel, which is given by left_pixel+width-1. */
803 if (w->pseudo_window_p)
805 left_x = 0;
806 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
807 top_y = WINDOW_TOP_EDGE_Y (w);
808 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
810 else
812 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
813 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
814 top_y = WINDOW_TOP_EDGE_Y (w);
815 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
818 /* Outside any interesting row? */
819 if (*y < top_y || *y >= bottom_y)
820 return ON_NOTHING;
822 /* On the mode line or header line? If it's near the start of
823 the mode or header line of window that's has a horizontal
824 sibling, say it's on the vertical line. That's to be able
825 to resize windows horizontally in case we're using toolkit
826 scroll bars. */
828 if (WINDOW_WANTS_MODELINE_P (w)
829 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
831 part = ON_MODE_LINE;
833 header_vertical_border_check:
834 /* We're somewhere on the mode line. We consider the place
835 between mode lines of horizontally adjacent mode lines
836 as the vertical border. If scroll bars on the left,
837 return the right window. */
838 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
839 || WINDOW_RIGHTMOST_P (w))
841 if (!WINDOW_LEFTMOST_P (w) && eabs (*x - x0) < grabbable_width)
843 /* Convert X and Y to window relative coordinates.
844 Vertical border is at the left edge of window. */
845 *x = max (0, *x - x0);
846 *y -= top_y;
847 return ON_VERTICAL_BORDER;
850 else
852 /* Make sure we're not at the rightmost position of a
853 mode-/header-line and there's yet another window on
854 the right. (Bug#1372) */
855 if ((WINDOW_RIGHTMOST_P (w) || *x < x1)
856 && eabs (*x - x1) < grabbable_width)
858 /* Convert X and Y to window relative coordinates.
859 Vertical border is at the right edge of window. */
860 *x = min (x1, *x) - x0;
861 *y -= top_y;
862 return ON_VERTICAL_BORDER;
866 if (*x < x0 || *x >= x1)
867 return ON_NOTHING;
869 /* Convert X and Y to window relative coordinates.
870 Mode line starts at left edge of window. */
871 *x -= x0;
872 *y -= top_y;
873 return part;
876 if (WINDOW_WANTS_HEADER_LINE_P (w)
877 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
879 part = ON_HEADER_LINE;
880 goto header_vertical_border_check;
883 if (*x < x0 || *x >= x1)
884 return ON_NOTHING;
886 /* Outside any interesting column? */
887 if (*x < left_x || *x > right_x)
889 *y -= top_y;
890 return ON_SCROLL_BAR;
893 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
894 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
896 text_left = window_box_left (w, TEXT_AREA);
897 text_right = text_left + window_box_width (w, TEXT_AREA);
899 if (FRAME_WINDOW_P (f))
901 if (!w->pseudo_window_p
902 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
903 && !WINDOW_RIGHTMOST_P (w)
904 && (eabs (*x - right_x) < grabbable_width))
906 /* Convert X and Y to window relative coordinates.
907 Vertical border is at the right edge of window. */
908 *x = min (right_x, *x) - left_x;
909 *y -= top_y;
910 return ON_VERTICAL_BORDER;
913 else
915 /* Need to say "*x > right_x" rather than >=, since on character
916 terminals, the vertical line's x coordinate is right_x. */
917 if (!w->pseudo_window_p
918 && !WINDOW_RIGHTMOST_P (w)
919 && *x > right_x - ux)
921 /* On the border on the right side of the window? Assume that
922 this area begins at RIGHT_X minus a canonical char width. */
923 *x = min (right_x, *x) - left_x;
924 *y -= top_y;
925 return ON_VERTICAL_BORDER;
929 if (*x < text_left)
931 if (lmargin_width > 0
932 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
933 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
934 : (*x < left_x + lmargin_width)))
936 *x -= left_x;
937 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
938 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
939 *y -= top_y;
940 return ON_LEFT_MARGIN;
943 /* Convert X and Y to window-relative pixel coordinates. */
944 *x -= left_x;
945 *y -= top_y;
946 return ON_LEFT_FRINGE;
949 if (*x >= text_right)
951 if (rmargin_width > 0
952 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
953 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
954 : (*x >= right_x - rmargin_width)))
956 *x -= right_x - rmargin_width;
957 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
958 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
959 *y -= top_y;
960 return ON_RIGHT_MARGIN;
963 /* Convert X and Y to window-relative pixel coordinates. */
964 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
965 *y -= top_y;
966 return ON_RIGHT_FRINGE;
969 /* Everything special ruled out - must be on text area */
970 *x -= text_left;
971 *y -= top_y;
972 return ON_TEXT;
976 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
977 Scoordinates_in_window_p, 2, 2, 0,
978 doc: /* Return non-nil if COORDINATES are in WINDOW.
979 COORDINATES is a cons of the form (X . Y), X and Y being distances
980 measured in characters from the upper-left corner of the frame.
981 \(0 . 0) denotes the character in the upper left corner of the
982 frame.
983 If COORDINATES are in the text portion of WINDOW,
984 the coordinates relative to the window are returned.
985 If they are in the mode line of WINDOW, `mode-line' is returned.
986 If they are in the top mode line of WINDOW, `header-line' is returned.
987 If they are in the left fringe of WINDOW, `left-fringe' is returned.
988 If they are in the right fringe of WINDOW, `right-fringe' is returned.
989 If they are on the border between WINDOW and its right sibling,
990 `vertical-line' is returned.
991 If they are in the windows's left or right marginal areas, `left-margin'\n\
992 or `right-margin' is returned. */)
993 (register Lisp_Object coordinates, Lisp_Object window)
995 struct window *w;
996 struct frame *f;
997 int x, y;
998 Lisp_Object lx, ly;
1000 CHECK_WINDOW (window);
1001 w = XWINDOW (window);
1002 f = XFRAME (w->frame);
1003 CHECK_CONS (coordinates);
1004 lx = Fcar (coordinates);
1005 ly = Fcdr (coordinates);
1006 CHECK_NUMBER_OR_FLOAT (lx);
1007 CHECK_NUMBER_OR_FLOAT (ly);
1008 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1009 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1011 switch (coordinates_in_window (w, &x, &y))
1013 case ON_NOTHING:
1014 return Qnil;
1016 case ON_TEXT:
1017 /* X and Y are now window relative pixel coordinates. Convert
1018 them to canonical char units before returning them. */
1019 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1020 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1022 case ON_MODE_LINE:
1023 return Qmode_line;
1025 case ON_VERTICAL_BORDER:
1026 return Qvertical_line;
1028 case ON_HEADER_LINE:
1029 return Qheader_line;
1031 case ON_LEFT_FRINGE:
1032 return Qleft_fringe;
1034 case ON_RIGHT_FRINGE:
1035 return Qright_fringe;
1037 case ON_LEFT_MARGIN:
1038 return Qleft_margin;
1040 case ON_RIGHT_MARGIN:
1041 return Qright_margin;
1043 case ON_SCROLL_BAR:
1044 /* Historically we are supposed to return nil in this case. */
1045 return Qnil;
1047 default:
1048 abort ();
1053 /* Callback for foreach_window, used in window_from_coordinates.
1054 Check if window W contains coordinates specified by USER_DATA which
1055 is actually a pointer to a struct check_window_data CW.
1057 Check if window W contains coordinates *CW->x and *CW->y. If it
1058 does, return W in *CW->window, as Lisp_Object, and return in
1059 *CW->part the part of the window under coordinates *X,*Y. Return
1060 zero from this function to stop iterating over windows. */
1062 struct check_window_data
1064 Lisp_Object *window;
1065 int *x, *y;
1066 enum window_part *part;
1069 static int
1070 check_window_containing (struct window *w, void *user_data)
1072 struct check_window_data *cw = (struct check_window_data *) user_data;
1073 enum window_part found;
1074 int continue_p = 1;
1076 found = coordinates_in_window (w, cw->x, cw->y);
1077 if (found != ON_NOTHING)
1079 *cw->part = found;
1080 XSETWINDOW (*cw->window, w);
1081 continue_p = 0;
1084 return continue_p;
1088 /* Find the window containing frame-relative pixel position X/Y and
1089 return it as a Lisp_Object.
1091 If X, Y is on one of the window's special `window_part' elements,
1092 set *PART to the id of that element, and return X and Y converted
1093 to window relative coordinates in WX and WY.
1095 If there is no window under X, Y return nil and leave *PART
1096 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1098 This function was previously implemented with a loop cycling over
1099 windows with Fnext_window, and starting with the frame's selected
1100 window. It turned out that this doesn't work with an
1101 implementation of next_window using Vwindow_list, because
1102 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1103 tree of F when this function is called asynchronously from
1104 note_mouse_highlight. The original loop didn't terminate in this
1105 case. */
1107 Lisp_Object
1108 window_from_coordinates (struct frame *f, int x, int y, enum window_part *part, int *wx, int *wy, int tool_bar_p)
1110 Lisp_Object window;
1111 struct check_window_data cw;
1112 enum window_part dummy;
1114 if (part == 0)
1115 part = &dummy;
1117 window = Qnil;
1118 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1119 foreach_window (f, check_window_containing, &cw);
1121 /* If not found above, see if it's in the tool bar window, if a tool
1122 bar exists. */
1123 if (NILP (window)
1124 && tool_bar_p
1125 && WINDOWP (f->tool_bar_window)
1126 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1127 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1128 != ON_NOTHING))
1130 *part = ON_TEXT;
1131 window = f->tool_bar_window;
1134 if (wx) *wx = x;
1135 if (wy) *wy = y;
1137 return window;
1140 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1141 doc: /* Return window containing coordinates X and Y on FRAME.
1142 If omitted, FRAME defaults to the currently selected frame.
1143 The top left corner of the frame is considered to be row 0,
1144 column 0. */)
1145 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1147 struct frame *f;
1149 if (NILP (frame))
1150 frame = selected_frame;
1151 CHECK_LIVE_FRAME (frame);
1152 f = XFRAME (frame);
1154 /* Check that arguments are integers or floats. */
1155 CHECK_NUMBER_OR_FLOAT (x);
1156 CHECK_NUMBER_OR_FLOAT (y);
1158 return window_from_coordinates (f,
1159 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1160 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1161 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1162 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1163 0, 0, 0, 0);
1166 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1167 doc: /* Return current value of point in WINDOW.
1168 WINDOW defaults to the selected window.
1170 For a nonselected window, this is the value point would have
1171 if that window were selected.
1173 Note that, when WINDOW is the selected window and its buffer
1174 is also currently selected, the value returned is the same as (point).
1175 It would be more strictly correct to return the `top-level' value
1176 of point, outside of any save-excursion forms.
1177 But that is hard to define. */)
1178 (Lisp_Object window)
1180 register struct window *w = decode_window (window);
1182 if (w == XWINDOW (selected_window)
1183 && current_buffer == XBUFFER (w->buffer))
1184 return Fpoint ();
1185 return Fmarker_position (w->pointm);
1188 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1189 doc: /* Return position at which display currently starts in WINDOW.
1190 WINDOW defaults to the selected window.
1191 This is updated by redisplay or by calling `set-window-start'. */)
1192 (Lisp_Object window)
1194 return Fmarker_position (decode_window (window)->start);
1197 /* This is text temporarily removed from the doc string below.
1199 This function returns nil if the position is not currently known.
1200 That happens when redisplay is preempted and doesn't finish.
1201 If in that case you want to compute where the end of the window would
1202 have been if redisplay had finished, do this:
1203 (save-excursion
1204 (goto-char (window-start window))
1205 (vertical-motion (1- (window-height window)) window)
1206 (point))") */
1208 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1209 doc: /* Return position at which display currently ends in WINDOW.
1210 WINDOW defaults to the selected window.
1211 This is updated by redisplay, when it runs to completion.
1212 Simply changing the buffer text or setting `window-start'
1213 does not update this value.
1214 Return nil if there is no recorded value. \(This can happen if the
1215 last redisplay of WINDOW was preempted, and did not finish.)
1216 If UPDATE is non-nil, compute the up-to-date position
1217 if it isn't already recorded. */)
1218 (Lisp_Object window, Lisp_Object update)
1220 Lisp_Object value;
1221 struct window *w = decode_window (window);
1222 Lisp_Object buf;
1223 struct buffer *b;
1225 buf = w->buffer;
1226 CHECK_BUFFER (buf);
1227 b = XBUFFER (buf);
1229 #if 0 /* This change broke some things. We should make it later. */
1230 /* If we don't know the end position, return nil.
1231 The user can compute it with vertical-motion if he wants to.
1232 It would be nicer to do it automatically,
1233 but that's so slow that it would probably bother people. */
1234 if (NILP (w->window_end_valid))
1235 return Qnil;
1236 #endif
1238 if (! NILP (update)
1239 && ! (! NILP (w->window_end_valid)
1240 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1241 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1242 && !noninteractive)
1244 struct text_pos startp;
1245 struct it it;
1246 struct buffer *old_buffer = NULL;
1248 /* Cannot use Fvertical_motion because that function doesn't
1249 cope with variable-height lines. */
1250 if (b != current_buffer)
1252 old_buffer = current_buffer;
1253 set_buffer_internal (b);
1256 /* In case W->start is out of the range, use something
1257 reasonable. This situation occurred when loading a file with
1258 `-l' containing a call to `rmail' with subsequent other
1259 commands. At the end, W->start happened to be BEG, while
1260 rmail had already narrowed the buffer. */
1261 if (XMARKER (w->start)->charpos < BEGV)
1262 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1263 else if (XMARKER (w->start)->charpos > ZV)
1264 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1265 else
1266 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1268 start_display (&it, w, startp);
1269 move_it_vertically (&it, window_box_height (w));
1270 if (it.current_y < it.last_visible_y)
1271 move_it_past_eol (&it);
1272 value = make_number (IT_CHARPOS (it));
1274 if (old_buffer)
1275 set_buffer_internal (old_buffer);
1277 else
1278 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1280 return value;
1283 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1284 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1285 Return POS. */)
1286 (Lisp_Object window, Lisp_Object pos)
1288 register struct window *w = decode_window (window);
1290 CHECK_NUMBER_COERCE_MARKER (pos);
1291 if (w == XWINDOW (selected_window)
1292 && XBUFFER (w->buffer) == current_buffer)
1293 Fgoto_char (pos);
1294 else
1295 set_marker_restricted (w->pointm, pos, w->buffer);
1297 /* We have to make sure that redisplay updates the window to show
1298 the new value of point. */
1299 if (!EQ (window, selected_window))
1300 ++windows_or_buffers_changed;
1302 return pos;
1305 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1306 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1307 WINDOW defaults to the selected window. Return POS.
1308 Optional third arg NOFORCE non-nil inhibits next redisplay from
1309 overriding motion of point in order to display at this exact start. */)
1310 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1312 register struct window *w = decode_window (window);
1314 CHECK_NUMBER_COERCE_MARKER (pos);
1315 set_marker_restricted (w->start, pos, w->buffer);
1316 /* this is not right, but much easier than doing what is right. */
1317 w->start_at_line_beg = Qnil;
1318 if (NILP (noforce))
1319 w->force_start = Qt;
1320 w->update_mode_line = Qt;
1321 XSETFASTINT (w->last_modified, 0);
1322 XSETFASTINT (w->last_overlay_modified, 0);
1323 if (!EQ (window, selected_window))
1324 windows_or_buffers_changed++;
1326 return pos;
1330 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1331 0, 1, 0,
1332 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1333 More precisely, return the value assigned by the last call of
1334 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1335 never called with WINDOW as its argument, or the value set by that
1336 function was internally reset since its last call. WINDOW defaults to
1337 the selected window.
1339 When a window is dedicated to its buffer, `display-buffer' will refrain
1340 from displaying another buffer in it. `get-lru-window' and
1341 `get-largest-window' treat dedicated windows specially.
1342 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1343 `kill-buffer' can delete a dedicated window and the containing frame.
1345 Functions like `set-window-buffer' may change the buffer displayed by a
1346 window, unless that window is "strongly" dedicated to its buffer, that
1347 is the value returned by `window-dedicated-p' is t. */)
1348 (Lisp_Object window)
1350 return decode_window (window)->dedicated;
1353 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1354 Sset_window_dedicated_p, 2, 2, 0,
1355 doc: /* Mark WINDOW as dedicated according to FLAG.
1356 WINDOW defaults to the selected window. FLAG non-nil means mark WINDOW
1357 as dedicated to its buffer. FLAG nil means mark WINDOW as non-dedicated.
1358 Return FLAG.
1360 When a window is dedicated to its buffer, `display-buffer' will refrain
1361 from displaying another buffer in it. `get-lru-window' and
1362 `get-largest-window' treat dedicated windows specially.
1363 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1364 `kill-buffer' can delete a dedicated window and the containing
1365 frame.
1367 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1368 its buffer. Functions like `set-window-buffer' may change the buffer
1369 displayed by a window, unless that window is strongly dedicated to its
1370 buffer. If and when `set-window-buffer' displays another buffer in a
1371 window, it also makes sure that the window is not marked as dedicated. */)
1372 (Lisp_Object window, Lisp_Object flag)
1374 register struct window *w = decode_window (window);
1376 w->dedicated = flag;
1377 return w->dedicated;
1381 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1382 0, 1, 0,
1383 doc: /* Return the parameters of WINDOW and their values.
1384 WINDOW defaults to the selected window. The return value is a list of
1385 elements of the form (PARAMETER . VALUE). */)
1386 (Lisp_Object window)
1388 return Fcopy_alist (decode_window (window)->window_parameters);
1391 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1392 2, 2, 0,
1393 doc: /* Return WINDOW's value for PARAMETER.
1394 WINDOW defaults to the selected window. */)
1395 (Lisp_Object window, Lisp_Object parameter)
1397 Lisp_Object result;
1399 result = Fassq (parameter, decode_window (window)->window_parameters);
1400 return CDR_SAFE (result);
1403 DEFUN ("set-window-parameter", Fset_window_parameter,
1404 Sset_window_parameter, 3, 3, 0,
1405 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1406 WINDOW defaults to the selected window. Return VALUE. */)
1407 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1409 register struct window *w = decode_window (window);
1410 Lisp_Object old_alist_elt;
1412 old_alist_elt = Fassq (parameter, w->window_parameters);
1413 if (NILP (old_alist_elt))
1414 w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
1415 else
1416 Fsetcdr (old_alist_elt, value);
1417 return value;
1421 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1422 0, 1, 0,
1423 doc: /* Return the display-table that WINDOW is using.
1424 WINDOW defaults to the selected window. */)
1425 (Lisp_Object window)
1427 return decode_window (window)->display_table;
1430 /* Get the display table for use on window W. This is either W's
1431 display table or W's buffer's display table. Ignore the specified
1432 tables if they are not valid; if no valid table is specified,
1433 return 0. */
1435 struct Lisp_Char_Table *
1436 window_display_table (struct window *w)
1438 struct Lisp_Char_Table *dp = NULL;
1440 if (DISP_TABLE_P (w->display_table))
1441 dp = XCHAR_TABLE (w->display_table);
1442 else if (BUFFERP (w->buffer))
1444 struct buffer *b = XBUFFER (w->buffer);
1446 if (DISP_TABLE_P (b->display_table))
1447 dp = XCHAR_TABLE (b->display_table);
1448 else if (DISP_TABLE_P (Vstandard_display_table))
1449 dp = XCHAR_TABLE (Vstandard_display_table);
1452 return dp;
1455 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1456 doc: /* Set WINDOW's display-table to TABLE. */)
1457 (register Lisp_Object window, Lisp_Object table)
1459 register struct window *w;
1461 w = decode_window (window);
1462 w->display_table = table;
1463 return table;
1466 /* Record info on buffer window w is displaying
1467 when it is about to cease to display that buffer. */
1468 static void
1469 unshow_buffer (register struct window *w)
1471 Lisp_Object buf;
1472 struct buffer *b;
1474 buf = w->buffer;
1475 b = XBUFFER (buf);
1476 if (b != XMARKER (w->pointm)->buffer)
1477 abort ();
1479 #if 0
1480 if (w == XWINDOW (selected_window)
1481 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1482 /* Do this except when the selected window's buffer
1483 is being removed from some other window. */
1484 #endif
1485 /* last_window_start records the start position that this buffer
1486 had in the last window to be disconnected from it.
1487 Now that this statement is unconditional,
1488 it is possible for the buffer to be displayed in the
1489 selected window, while last_window_start reflects another
1490 window which was recently showing the same buffer.
1491 Some people might say that might be a good thing. Let's see. */
1492 b->last_window_start = marker_position (w->start);
1494 /* Point in the selected window's buffer
1495 is actually stored in that buffer, and the window's pointm isn't used.
1496 So don't clobber point in that buffer. */
1497 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1498 /* This line helps to fix Horsley's testbug.el bug. */
1499 && !(WINDOWP (b->last_selected_window)
1500 && w != XWINDOW (b->last_selected_window)
1501 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1502 temp_set_point_both (b,
1503 clip_to_bounds (BUF_BEGV (b),
1504 XMARKER (w->pointm)->charpos,
1505 BUF_ZV (b)),
1506 clip_to_bounds (BUF_BEGV_BYTE (b),
1507 marker_byte_position (w->pointm),
1508 BUF_ZV_BYTE (b)));
1510 if (WINDOWP (b->last_selected_window)
1511 && w == XWINDOW (b->last_selected_window))
1512 b->last_selected_window = Qnil;
1515 /* Put replacement into the window structure in place of old. */
1516 static void
1517 replace_window (Lisp_Object old, Lisp_Object replacement)
1519 register Lisp_Object tem;
1520 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1522 /* If OLD is its frame's root_window, then replacement is the new
1523 root_window for that frame. */
1525 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1526 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1528 p->left_col = o->left_col;
1529 p->top_line = o->top_line;
1530 p->total_cols = o->total_cols;
1531 p->total_lines = o->total_lines;
1532 p->desired_matrix = p->current_matrix = 0;
1533 p->vscroll = 0;
1534 memset (&p->cursor, 0, sizeof (p->cursor));
1535 memset (&p->last_cursor, 0, sizeof (p->last_cursor));
1536 memset (&p->phys_cursor, 0, sizeof (p->phys_cursor));
1537 p->phys_cursor_type = -1;
1538 p->phys_cursor_width = -1;
1539 p->must_be_updated_p = 0;
1540 p->pseudo_window_p = 0;
1541 XSETFASTINT (p->window_end_vpos, 0);
1542 XSETFASTINT (p->window_end_pos, 0);
1543 p->window_end_valid = Qnil;
1544 p->frozen_window_start_p = 0;
1545 p->orig_top_line = p->orig_total_lines = Qnil;
1547 p->next = tem = o->next;
1548 if (!NILP (tem))
1549 XWINDOW (tem)->prev = replacement;
1551 p->prev = tem = o->prev;
1552 if (!NILP (tem))
1553 XWINDOW (tem)->next = replacement;
1555 p->parent = tem = o->parent;
1556 if (!NILP (tem))
1558 if (EQ (XWINDOW (tem)->vchild, old))
1559 XWINDOW (tem)->vchild = replacement;
1560 if (EQ (XWINDOW (tem)->hchild, old))
1561 XWINDOW (tem)->hchild = replacement;
1564 /*** Here, if replacement is a vertical combination
1565 and so is its new parent, we should make replacement's
1566 children be children of that parent instead. ***/
1569 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1570 doc: /* Remove WINDOW from its frame.
1571 WINDOW defaults to the selected window. Return nil.
1572 Signal an error when WINDOW is the only window on its frame. */)
1573 (register Lisp_Object window)
1575 struct frame *f;
1576 if (NILP (window))
1577 window = selected_window;
1578 else
1579 CHECK_LIVE_WINDOW (window);
1581 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1582 delete_window (window);
1584 run_window_configuration_change_hook (f);
1586 return Qnil;
1589 void
1590 delete_window (register Lisp_Object window)
1592 register Lisp_Object tem, parent, sib;
1593 register struct window *p;
1594 register struct window *par;
1595 struct frame *f;
1597 /* Because this function is called by other C code on non-leaf
1598 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1599 so we can't decode_window here. */
1600 CHECK_WINDOW (window);
1601 p = XWINDOW (window);
1603 /* It's a no-op to delete an already-deleted window. */
1604 if (NILP (p->buffer)
1605 && NILP (p->hchild)
1606 && NILP (p->vchild))
1607 return;
1609 parent = p->parent;
1610 if (NILP (parent))
1611 error ("Attempt to delete minibuffer or sole ordinary window");
1612 par = XWINDOW (parent);
1614 windows_or_buffers_changed++;
1615 Vwindow_list = Qnil;
1616 f = XFRAME (WINDOW_FRAME (p));
1617 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1619 /* Are we trying to delete any frame's selected window? */
1621 Lisp_Object swindow, pwindow;
1623 /* See if the frame's selected window is either WINDOW
1624 or any subwindow of it, by finding all that window's parents
1625 and comparing each one with WINDOW. */
1626 swindow = FRAME_SELECTED_WINDOW (f);
1628 while (1)
1630 pwindow = swindow;
1631 while (!NILP (pwindow))
1633 if (EQ (window, pwindow))
1634 break;
1635 pwindow = XWINDOW (pwindow)->parent;
1638 /* If the window being deleted is not a parent of SWINDOW,
1639 then SWINDOW is ok as the new selected window. */
1640 if (!EQ (window, pwindow))
1641 break;
1642 /* Otherwise, try another window for SWINDOW. */
1643 swindow = Fnext_window (swindow, Qlambda, Qnil);
1645 /* If we get back to the frame's selected window,
1646 it means there was no acceptable alternative,
1647 so we cannot delete. */
1648 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1649 error ("Cannot delete window");
1652 /* If we need to change SWINDOW, do it. */
1653 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1655 /* If we're about to delete the selected window on the
1656 selected frame, then we should use Fselect_window to select
1657 the new window. On the other hand, if we're about to
1658 delete the selected window on any other frame, we shouldn't do
1659 anything but set the frame's selected_window slot. */
1660 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1661 Fselect_window (swindow, Qnil);
1662 else
1663 FRAME_SELECTED_WINDOW (f) = swindow;
1667 /* Now we know we can delete this one. */
1668 window_deletion_count++;
1670 tem = p->buffer;
1671 /* tem is null for dummy parent windows
1672 (which have inferiors but not any contents themselves) */
1673 if (!NILP (tem))
1675 unshow_buffer (p);
1676 unchain_marker (XMARKER (p->pointm));
1677 unchain_marker (XMARKER (p->start));
1680 /* Free window glyph matrices. It is sure that they are allocated
1681 again when ADJUST_GLYPHS is called. Block input so that expose
1682 events and other events that access glyph matrices are not
1683 processed while we are changing them. */
1684 BLOCK_INPUT;
1685 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1687 tem = p->next;
1688 if (!NILP (tem))
1689 XWINDOW (tem)->prev = p->prev;
1691 tem = p->prev;
1692 if (!NILP (tem))
1693 XWINDOW (tem)->next = p->next;
1695 if (EQ (window, par->hchild))
1696 par->hchild = p->next;
1697 if (EQ (window, par->vchild))
1698 par->vchild = p->next;
1700 /* Find one of our siblings to give our space to. */
1701 sib = p->prev;
1702 if (NILP (sib))
1704 /* If p gives its space to its next sibling, that sibling needs
1705 to have its top/left side pulled back to where p's is.
1706 set_window_{height,width} will re-position the sibling's
1707 children. */
1708 sib = p->next;
1709 XWINDOW (sib)->top_line = p->top_line;
1710 XWINDOW (sib)->left_col = p->left_col;
1713 /* Stretch that sibling. */
1714 if (!NILP (par->vchild))
1715 set_window_height (sib,
1716 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1718 if (!NILP (par->hchild))
1719 set_window_width (sib,
1720 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1723 /* If parent now has only one child,
1724 put the child into the parent's place. */
1725 tem = par->hchild;
1726 if (NILP (tem))
1727 tem = par->vchild;
1728 if (NILP (XWINDOW (tem)->next)) {
1729 replace_window (parent, tem);
1730 par = XWINDOW (tem);
1733 /* Since we may be deleting combination windows, we must make sure that
1734 not only p but all its children have been marked as deleted. */
1735 if (! NILP (p->hchild))
1736 delete_all_subwindows (XWINDOW (p->hchild));
1737 else if (! NILP (p->vchild))
1738 delete_all_subwindows (XWINDOW (p->vchild));
1740 /* Mark this window as deleted. */
1741 p->buffer = p->hchild = p->vchild = Qnil;
1743 if (! NILP (par->parent))
1744 par = XWINDOW (par->parent);
1746 /* Check if we have a v/hchild with a v/hchild. In that case remove
1747 one of them. */
1749 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1751 p = XWINDOW (par->vchild);
1752 par->vchild = p->vchild;
1753 tem = p->vchild;
1755 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1757 p = XWINDOW (par->hchild);
1758 par->hchild = p->hchild;
1759 tem = p->hchild;
1761 else
1762 p = 0;
1764 if (p)
1766 while (! NILP (tem)) {
1767 XWINDOW (tem)->parent = p->parent;
1768 if (NILP (XWINDOW (tem)->next))
1769 break;
1770 tem = XWINDOW (tem)->next;
1772 if (! NILP (tem)) {
1773 /* The next of the v/hchild we are removing is now the next of the
1774 last child for the v/hchild:
1775 Before v/hchild -> v/hchild -> next1 -> next2
1777 -> next3
1778 After: v/hchild -> next1 -> next2 -> next3
1780 XWINDOW (tem)->next = p->next;
1781 if (! NILP (p->next))
1782 XWINDOW (p->next)->prev = tem;
1784 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1788 /* Adjust glyph matrices. */
1789 adjust_glyphs (f);
1790 UNBLOCK_INPUT;
1795 /***********************************************************************
1796 Window List
1797 ***********************************************************************/
1799 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1800 pointer. This is a callback function for foreach_window, used in
1801 function window_list. */
1803 static int
1804 add_window_to_list (struct window *w, void *user_data)
1806 Lisp_Object *list = (Lisp_Object *) user_data;
1807 Lisp_Object window;
1808 XSETWINDOW (window, w);
1809 *list = Fcons (window, *list);
1810 return 1;
1814 /* Return a list of all windows, for use by next_window. If
1815 Vwindow_list is a list, return that list. Otherwise, build a new
1816 list, cache it in Vwindow_list, and return that. */
1818 static Lisp_Object
1819 window_list (void)
1821 if (!CONSP (Vwindow_list))
1823 Lisp_Object tail;
1825 Vwindow_list = Qnil;
1826 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1828 Lisp_Object args[2];
1830 /* We are visiting windows in canonical order, and add
1831 new windows at the front of args[1], which means we
1832 have to reverse this list at the end. */
1833 args[1] = Qnil;
1834 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1835 args[0] = Vwindow_list;
1836 args[1] = Fnreverse (args[1]);
1837 Vwindow_list = Fnconc (2, args);
1841 return Vwindow_list;
1845 /* Value is non-zero if WINDOW satisfies the constraints given by
1846 OWINDOW, MINIBUF and ALL_FRAMES.
1848 MINIBUF t means WINDOW may be minibuffer windows.
1849 `lambda' means WINDOW may not be a minibuffer window.
1850 a window means a specific minibuffer window
1852 ALL_FRAMES t means search all frames,
1853 nil means search just current frame,
1854 `visible' means search just visible frames,
1855 0 means search visible and iconified frames,
1856 a window means search the frame that window belongs to,
1857 a frame means consider windows on that frame, only. */
1859 static int
1860 candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
1862 struct window *w = XWINDOW (window);
1863 struct frame *f = XFRAME (w->frame);
1864 int candidate_p = 1;
1866 if (!BUFFERP (w->buffer))
1867 candidate_p = 0;
1868 else if (MINI_WINDOW_P (w)
1869 && (EQ (minibuf, Qlambda)
1870 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1872 /* If MINIBUF is `lambda' don't consider any mini-windows.
1873 If it is a window, consider only that one. */
1874 candidate_p = 0;
1876 else if (EQ (all_frames, Qt))
1877 candidate_p = 1;
1878 else if (NILP (all_frames))
1880 xassert (WINDOWP (owindow));
1881 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1883 else if (EQ (all_frames, Qvisible))
1885 FRAME_SAMPLE_VISIBILITY (f);
1886 candidate_p = FRAME_VISIBLE_P (f)
1887 && (FRAME_TERMINAL (XFRAME (w->frame))
1888 == FRAME_TERMINAL (XFRAME (selected_frame)));
1891 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1893 FRAME_SAMPLE_VISIBILITY (f);
1894 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
1895 #ifdef HAVE_X_WINDOWS
1896 /* Yuck!! If we've just created the frame and the
1897 window-manager requested the user to place it
1898 manually, the window may still not be considered
1899 `visible'. I'd argue it should be at least
1900 something like `iconified', but don't know how to do
1901 that yet. --Stef */
1902 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
1903 && !f->output_data.x->has_been_visible)
1904 #endif
1906 && (FRAME_TERMINAL (XFRAME (w->frame))
1907 == FRAME_TERMINAL (XFRAME (selected_frame)));
1909 else if (WINDOWP (all_frames))
1910 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1911 || EQ (XWINDOW (all_frames)->frame, w->frame)
1912 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1913 else if (FRAMEP (all_frames))
1914 candidate_p = EQ (all_frames, w->frame);
1916 return candidate_p;
1920 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1921 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1922 ALL_FRAMES. */
1924 static void
1925 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
1927 if (NILP (*window))
1928 *window = selected_window;
1929 else
1930 CHECK_LIVE_WINDOW (*window);
1932 /* MINIBUF nil may or may not include minibuffers. Decide if it
1933 does. */
1934 if (NILP (*minibuf))
1935 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1936 else if (!EQ (*minibuf, Qt))
1937 *minibuf = Qlambda;
1939 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1940 => count none of them, or a specific minibuffer window (the
1941 active one) to count. */
1943 /* ALL_FRAMES nil doesn't specify which frames to include. */
1944 if (NILP (*all_frames))
1945 *all_frames = (!EQ (*minibuf, Qlambda)
1946 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1947 : Qnil);
1948 else if (EQ (*all_frames, Qvisible))
1950 else if (EQ (*all_frames, make_number (0)))
1952 else if (FRAMEP (*all_frames))
1954 else if (!EQ (*all_frames, Qt))
1955 *all_frames = Qnil;
1957 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1958 search just current frame, `visible' meaning search just visible
1959 frames, 0 meaning search visible and iconified frames, or a
1960 window, meaning search the frame that window belongs to, or a
1961 frame, meaning consider windows on that frame, only. */
1965 /* Return the next or previous window of WINDOW in cyclic ordering
1966 of windows. NEXT_P non-zero means return the next window. See the
1967 documentation string of next-window for the meaning of MINIBUF and
1968 ALL_FRAMES. */
1970 static Lisp_Object
1971 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
1973 decode_next_window_args (&window, &minibuf, &all_frames);
1975 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1976 return the first window on the frame. */
1977 if (FRAMEP (all_frames)
1978 && !EQ (all_frames, XWINDOW (window)->frame))
1979 return Fframe_first_window (all_frames);
1981 if (next_p)
1983 Lisp_Object list;
1985 /* Find WINDOW in the list of all windows. */
1986 list = Fmemq (window, window_list ());
1988 /* Scan forward from WINDOW to the end of the window list. */
1989 if (CONSP (list))
1990 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1991 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1992 break;
1994 /* Scan from the start of the window list up to WINDOW. */
1995 if (!CONSP (list))
1996 for (list = Vwindow_list;
1997 CONSP (list) && !EQ (XCAR (list), window);
1998 list = XCDR (list))
1999 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2000 break;
2002 if (CONSP (list))
2003 window = XCAR (list);
2005 else
2007 Lisp_Object candidate, list;
2009 /* Scan through the list of windows for candidates. If there are
2010 candidate windows in front of WINDOW, the last one of these
2011 is the one we want. If there are candidates following WINDOW
2012 in the list, again the last one of these is the one we want. */
2013 candidate = Qnil;
2014 for (list = window_list (); CONSP (list); list = XCDR (list))
2016 if (EQ (XCAR (list), window))
2018 if (WINDOWP (candidate))
2019 break;
2021 else if (candidate_window_p (XCAR (list), window, minibuf,
2022 all_frames))
2023 candidate = XCAR (list);
2026 if (WINDOWP (candidate))
2027 window = candidate;
2030 return window;
2034 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2035 doc: /* Return window following WINDOW in cyclic ordering of windows.
2036 WINDOW defaults to the selected window. The optional arguments
2037 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2039 MINIBUF t means consider the minibuffer window even if the
2040 minibuffer is not active. MINIBUF nil or omitted means consider
2041 the minibuffer window only if the minibuffer is active. Any
2042 other value means do not consider the minibuffer window even if
2043 the minibuffer is active.
2045 Several frames may share a single minibuffer; if the minibuffer
2046 is active, all windows on all frames that share that minibuffer
2047 are considered too. Therefore, if you are using a separate
2048 minibuffer frame and the minibuffer is active and MINIBUF says it
2049 counts, `next-window' considers the windows in the frame from
2050 which you entered the minibuffer, as well as the minibuffer
2051 window.
2053 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
2054 frame, plus the minibuffer window if specified by the MINIBUF
2055 argument, see above. If the minibuffer counts, consider all
2056 windows on all frames that share that minibuffer too.
2057 ALL-FRAMES t means consider all windows on all existing frames.
2058 ALL-FRAMES `visible' means consider all windows on all visible
2059 frames.
2060 ALL-FRAMES 0 means consider all windows on all visible and
2061 iconified frames.
2062 ALL-FRAMES a frame means consider all windows on that frame only.
2063 Anything else means consider all windows on WINDOW's frame and no
2064 others.
2066 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2067 `next-window' to iterate through the entire cycle of acceptable
2068 windows, eventually ending up back at the window you started with.
2069 `previous-window' traverses the same cycle, in the reverse order. */)
2070 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2072 return next_window (window, minibuf, all_frames, 1);
2076 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2077 doc: /* Return window preceding WINDOW in cyclic ordering of windows.
2078 WINDOW defaults to the selected window. The optional arguments
2079 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2080 For the precise meaning of these arguments see `next-window'.
2082 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2083 use `previous-window' to iterate through the entire cycle of
2084 acceptable windows, eventually ending up back at the window you
2085 started with. `next-window' traverses the same cycle, in the
2086 reverse order. */)
2087 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2089 return next_window (window, minibuf, all_frames, 0);
2093 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2094 doc: /* Select another window in cyclic ordering of windows.
2095 COUNT specifies the number of windows to skip, starting with the
2096 selected window, before making the selection. If COUNT is
2097 positive, skip COUNT windows forwards. If COUNT is negative,
2098 skip -COUNT windows backwards. COUNT zero means do not skip any
2099 window, so select the selected window. In an interactive call,
2100 COUNT is the numeric prefix argument. Return nil.
2102 This function uses `next-window' for finding the window to select.
2103 The argument ALL-FRAMES has the same meaning as in `next-window',
2104 but the MINIBUF argument of `next-window' is always effectively
2105 nil. */)
2106 (Lisp_Object count, Lisp_Object all_frames)
2108 Lisp_Object window;
2109 int i;
2111 CHECK_NUMBER (count);
2112 window = selected_window;
2114 for (i = XINT (count); i > 0; --i)
2115 window = Fnext_window (window, Qnil, all_frames);
2116 for (; i < 0; ++i)
2117 window = Fprevious_window (window, Qnil, all_frames);
2119 Fselect_window (window, Qnil);
2120 return Qnil;
2124 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2125 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2126 FRAME nil or omitted means use the selected frame.
2127 WINDOW nil or omitted means use the selected window.
2128 MINIBUF t means include the minibuffer window, even if it isn't active.
2129 MINIBUF nil or omitted means include the minibuffer window only
2130 if it's active.
2131 MINIBUF neither nil nor t means never include the minibuffer window. */)
2132 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2134 if (NILP (window))
2135 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2136 CHECK_WINDOW (window);
2137 if (NILP (frame))
2138 frame = selected_frame;
2140 if (!EQ (frame, XWINDOW (window)->frame))
2141 error ("Window is on a different frame");
2143 return window_list_1 (window, minibuf, frame);
2147 /* Return a list of windows in cyclic ordering. Arguments are like
2148 for `next-window'. */
2150 static Lisp_Object
2151 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2153 Lisp_Object tail, list, rest;
2155 decode_next_window_args (&window, &minibuf, &all_frames);
2156 list = Qnil;
2158 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2159 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2160 list = Fcons (XCAR (tail), list);
2162 /* Rotate the list to start with WINDOW. */
2163 list = Fnreverse (list);
2164 rest = Fmemq (window, list);
2165 if (!NILP (rest) && !EQ (rest, list))
2167 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2169 XSETCDR (tail, Qnil);
2170 list = nconc2 (rest, list);
2172 return list;
2177 /* Look at all windows, performing an operation specified by TYPE
2178 with argument OBJ.
2179 If FRAMES is Qt, look at all frames;
2180 Qnil, look at just the selected frame;
2181 Qvisible, look at visible frames;
2182 a frame, just look at windows on that frame.
2183 If MINI is non-zero, perform the operation on minibuffer windows too. */
2185 enum window_loop
2187 WINDOW_LOOP_UNUSED,
2188 GET_BUFFER_WINDOW, /* Arg is buffer */
2189 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2190 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2191 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2192 GET_LARGEST_WINDOW,
2193 UNSHOW_BUFFER, /* Arg is buffer */
2194 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2195 CHECK_ALL_WINDOWS
2198 static Lisp_Object
2199 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2201 Lisp_Object window, windows, best_window, frame_arg;
2202 struct frame *f;
2203 struct gcpro gcpro1;
2205 /* If we're only looping through windows on a particular frame,
2206 frame points to that frame. If we're looping through windows
2207 on all frames, frame is 0. */
2208 if (FRAMEP (frames))
2209 f = XFRAME (frames);
2210 else if (NILP (frames))
2211 f = SELECTED_FRAME ();
2212 else
2213 f = NULL;
2215 if (f)
2216 frame_arg = Qlambda;
2217 else if (EQ (frames, make_number (0)))
2218 frame_arg = frames;
2219 else if (EQ (frames, Qvisible))
2220 frame_arg = frames;
2221 else
2222 frame_arg = Qt;
2224 /* frame_arg is Qlambda to stick to one frame,
2225 Qvisible to consider all visible frames,
2226 or Qt otherwise. */
2228 /* Pick a window to start with. */
2229 if (WINDOWP (obj))
2230 window = obj;
2231 else if (f)
2232 window = FRAME_SELECTED_WINDOW (f);
2233 else
2234 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2236 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2237 GCPRO1 (windows);
2238 best_window = Qnil;
2240 for (; CONSP (windows); windows = XCDR (windows))
2242 struct window *w;
2244 window = XCAR (windows);
2245 w = XWINDOW (window);
2247 /* Note that we do not pay attention here to whether the frame
2248 is visible, since Fwindow_list skips non-visible frames if
2249 that is desired, under the control of frame_arg. */
2250 if (!MINI_WINDOW_P (w)
2251 /* For UNSHOW_BUFFER, we must always consider all windows. */
2252 || type == UNSHOW_BUFFER
2253 || (mini && minibuf_level > 0))
2254 switch (type)
2256 case GET_BUFFER_WINDOW:
2257 if (EQ (w->buffer, obj)
2258 /* Don't find any minibuffer window
2259 except the one that is currently in use. */
2260 && (MINI_WINDOW_P (w)
2261 ? EQ (window, minibuf_window)
2262 : 1))
2264 if (NILP (best_window))
2265 best_window = window;
2266 else if (EQ (window, selected_window))
2267 /* Prefer to return selected-window. */
2268 RETURN_UNGCPRO (window);
2269 else if (EQ (Fwindow_frame (window), selected_frame))
2270 /* Prefer windows on the current frame. */
2271 best_window = window;
2273 break;
2275 case GET_LRU_WINDOW:
2276 /* `obj' is an integer encoding a bitvector.
2277 `obj & 1' means consider only full-width windows.
2278 `obj & 2' means consider also dedicated windows. */
2279 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2280 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2281 /* Minibuffer windows are always ignored. */
2282 || MINI_WINDOW_P (w))
2283 break;
2284 if (NILP (best_window)
2285 || (XFASTINT (XWINDOW (best_window)->use_time)
2286 > XFASTINT (w->use_time)))
2287 best_window = window;
2288 break;
2290 case DELETE_OTHER_WINDOWS:
2291 if (!EQ (window, obj))
2292 Fdelete_window (window);
2293 break;
2295 case DELETE_BUFFER_WINDOWS:
2296 if (EQ (w->buffer, obj))
2298 struct frame *f = XFRAME (WINDOW_FRAME (w));
2300 /* If this window is dedicated, and in a frame of its own,
2301 kill the frame. */
2302 if (EQ (window, FRAME_ROOT_WINDOW (f))
2303 && !NILP (w->dedicated)
2304 && other_visible_frames (f))
2306 /* Skip the other windows on this frame.
2307 There might be one, the minibuffer! */
2308 while (CONSP (XCDR (windows))
2309 && EQ (XWINDOW (XCAR (windows))->frame,
2310 XWINDOW (XCAR (XCDR (windows)))->frame))
2311 windows = XCDR (windows);
2313 /* Now we can safely delete the frame. */
2314 delete_frame (w->frame, Qnil);
2316 else if (NILP (w->parent))
2318 /* If we're deleting the buffer displayed in the
2319 only window on the frame, find a new buffer to
2320 display there. */
2321 Lisp_Object buffer;
2322 buffer = Fother_buffer (obj, Qnil, w->frame);
2323 /* Reset dedicated state of window. */
2324 w->dedicated = Qnil;
2325 Fset_window_buffer (window, buffer, Qnil);
2326 if (EQ (window, selected_window))
2327 Fset_buffer (w->buffer);
2329 else
2330 Fdelete_window (window);
2332 break;
2334 case GET_LARGEST_WINDOW:
2335 { /* nil `obj' means to ignore dedicated windows. */
2336 /* Ignore dedicated windows and minibuffers. */
2337 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2338 break;
2340 if (NILP (best_window))
2341 best_window = window;
2342 else
2344 struct window *b = XWINDOW (best_window);
2345 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2346 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2347 best_window = window;
2350 break;
2352 case UNSHOW_BUFFER:
2353 if (EQ (w->buffer, obj))
2355 Lisp_Object buffer;
2356 struct frame *f = XFRAME (w->frame);
2358 /* Find another buffer to show in this window. */
2359 buffer = Fother_buffer (obj, Qnil, w->frame);
2361 /* If this window is dedicated, and in a frame of its own,
2362 kill the frame. */
2363 if (EQ (window, FRAME_ROOT_WINDOW (f))
2364 && !NILP (w->dedicated)
2365 && other_visible_frames (f))
2367 /* Skip the other windows on this frame.
2368 There might be one, the minibuffer! */
2369 while (CONSP (XCDR (windows))
2370 && EQ (XWINDOW (XCAR (windows))->frame,
2371 XWINDOW (XCAR (XCDR (windows)))->frame))
2372 windows = XCDR (windows);
2374 /* Now we can safely delete the frame. */
2375 delete_frame (w->frame, Qnil);
2377 else if (!NILP (w->dedicated) && !NILP (w->parent))
2379 Lisp_Object window;
2380 XSETWINDOW (window, w);
2381 /* If this window is dedicated and not the only window
2382 in its frame, then kill it. */
2383 Fdelete_window (window);
2385 else
2387 /* Otherwise show a different buffer in the window. */
2388 w->dedicated = Qnil;
2389 Fset_window_buffer (window, buffer, Qnil);
2390 if (EQ (window, selected_window))
2391 Fset_buffer (w->buffer);
2394 break;
2396 case REDISPLAY_BUFFER_WINDOWS:
2397 if (EQ (w->buffer, obj))
2399 mark_window_display_accurate (window, 0);
2400 w->update_mode_line = Qt;
2401 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2402 ++update_mode_lines;
2403 best_window = window;
2405 break;
2407 /* Check for a window that has a killed buffer. */
2408 case CHECK_ALL_WINDOWS:
2409 if (! NILP (w->buffer)
2410 && NILP (XBUFFER (w->buffer)->name))
2411 abort ();
2412 break;
2414 case WINDOW_LOOP_UNUSED:
2415 break;
2419 UNGCPRO;
2420 return best_window;
2423 /* Used for debugging. Abort if any window has a dead buffer. */
2425 void
2426 check_all_windows (void)
2428 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2431 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2432 doc: /* Return the window least recently selected or used for display.
2433 \(LRU means Least Recently Used.)
2435 Return a full-width window if possible.
2436 A minibuffer window is never a candidate.
2437 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2438 so if all windows are dedicated, the value is nil.
2439 If optional argument FRAME is `visible', search all visible frames.
2440 If FRAME is 0, search all visible and iconified frames.
2441 If FRAME is t, search all frames.
2442 If FRAME is nil, search only the selected frame.
2443 If FRAME is a frame, search only that frame. */)
2444 (Lisp_Object frame, Lisp_Object dedicated)
2446 register Lisp_Object w;
2447 /* First try for a window that is full-width */
2448 w = window_loop (GET_LRU_WINDOW,
2449 NILP (dedicated) ? make_number (1) : make_number (3),
2450 0, frame);
2451 if (!NILP (w) && !EQ (w, selected_window))
2452 return w;
2453 /* If none of them, try the rest */
2454 return window_loop (GET_LRU_WINDOW,
2455 NILP (dedicated) ? make_number (0) : make_number (2),
2456 0, frame);
2459 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2460 doc: /* Return the largest window in area.
2461 A minibuffer window is never a candidate.
2462 A dedicated window is never a candidate unless DEDICATED is non-nil,
2463 so if all windows are dedicated, the value is nil.
2464 If optional argument FRAME is `visible', search all visible frames.
2465 If FRAME is 0, search all visible and iconified frames.
2466 If FRAME is t, search all frames.
2467 If FRAME is nil, search only the selected frame.
2468 If FRAME is a frame, search only that frame. */)
2469 (Lisp_Object frame, Lisp_Object dedicated)
2471 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2472 frame);
2475 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2476 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2477 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
2478 current buffer.
2479 If optional argument FRAME is `visible', search all visible frames.
2480 If optional argument FRAME is 0, search all visible and iconified frames.
2481 If FRAME is t, search all frames.
2482 If FRAME is nil, search only the selected frame.
2483 If FRAME is a frame, search only that frame. */)
2484 (Lisp_Object buffer_or_name, Lisp_Object frame)
2486 Lisp_Object buffer;
2488 if (NILP (buffer_or_name))
2489 buffer = Fcurrent_buffer ();
2490 else
2491 buffer = Fget_buffer (buffer_or_name);
2493 if (BUFFERP (buffer))
2494 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2495 else
2496 return Qnil;
2499 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2500 0, 1, "",
2501 doc: /* Make WINDOW (or the selected window) fill its frame.
2502 Only the frame WINDOW is on is affected.
2503 This function tries to reduce display jumps by keeping the text
2504 previously visible in WINDOW in the same place on the frame. Doing this
2505 depends on the value of (window-start WINDOW), so if calling this
2506 function in a program gives strange scrolling, make sure the
2507 window-start value is reasonable when this function is called. */)
2508 (Lisp_Object window)
2510 struct window *w;
2511 int startpos;
2512 int top, new_top;
2514 if (NILP (window))
2515 window = selected_window;
2516 else
2517 CHECK_LIVE_WINDOW (window);
2518 w = XWINDOW (window);
2520 startpos = marker_position (w->start);
2521 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2523 if (MINI_WINDOW_P (w) && top > 0)
2524 error ("Can't expand minibuffer to full frame");
2526 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2528 /* Try to minimize scrolling, by setting the window start to the point
2529 will cause the text at the old window start to be at the same place
2530 on the frame. But don't try to do this if the window start is
2531 outside the visible portion (as might happen when the display is
2532 not current, due to typeahead). */
2533 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2534 if (new_top != top
2535 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2536 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2538 struct position pos;
2539 struct buffer *obuf = current_buffer;
2541 Fset_buffer (w->buffer);
2542 /* This computation used to temporarily move point, but that can
2543 have unwanted side effects due to text properties. */
2544 pos = *vmotion (startpos, -top, w);
2546 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2547 w->window_end_valid = Qnil;
2548 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2549 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2550 : Qnil);
2551 /* We need to do this, so that the window-scroll-functions
2552 get called. */
2553 w->optional_new_start = Qt;
2555 set_buffer_internal (obuf);
2558 return Qnil;
2561 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2562 0, 2, "bDelete windows on (buffer): ",
2563 doc: /* Delete all windows showing BUFFER-OR-NAME.
2564 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2565 defaults to the current buffer.
2567 Optional second argument FRAME controls which frames are affected.
2568 If optional argument FRAME is `visible', search all visible frames.
2569 If FRAME is 0, search all visible and iconified frames.
2570 If FRAME is nil, search all frames.
2571 If FRAME is t, search only the selected frame.
2572 If FRAME is a frame, search only that frame.
2573 When a window showing BUFFER-OR-NAME is dedicated and the only window of
2574 its frame, that frame is deleted when there are other frames left. */)
2575 (Lisp_Object buffer_or_name, Lisp_Object frame)
2577 Lisp_Object buffer;
2579 /* FRAME uses t and nil to mean the opposite of what window_loop
2580 expects. */
2581 if (NILP (frame))
2582 frame = Qt;
2583 else if (EQ (frame, Qt))
2584 frame = Qnil;
2586 if (NILP (buffer_or_name))
2587 buffer = Fcurrent_buffer ();
2588 else
2590 buffer = Fget_buffer (buffer_or_name);
2591 CHECK_BUFFER (buffer);
2594 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2596 return Qnil;
2599 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2600 Sreplace_buffer_in_windows,
2601 0, 1, "bReplace buffer in windows: ",
2602 doc: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2603 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2604 defaults to the current buffer.
2606 When a window showing BUFFER-OR-NAME is dedicated that window is
2607 deleted. If that window is the only window on its frame, that frame is
2608 deleted too when there are other frames left. If there are no other
2609 frames left, some other buffer is displayed in that window. */)
2610 (Lisp_Object buffer_or_name)
2612 Lisp_Object buffer;
2614 if (NILP (buffer_or_name))
2615 buffer = Fcurrent_buffer ();
2616 else
2618 buffer = Fget_buffer (buffer_or_name);
2619 CHECK_BUFFER (buffer);
2622 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2624 return Qnil;
2627 /* Replace BUFFER with some other buffer in all windows
2628 of all frames, even those on other keyboards. */
2630 void
2631 replace_buffer_in_all_windows (Lisp_Object buffer)
2633 Lisp_Object tail, frame;
2635 /* A single call to window_loop won't do the job
2636 because it only considers frames on the current keyboard.
2637 So loop manually over frames, and handle each one. */
2638 FOR_EACH_FRAME (tail, frame)
2639 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2642 /* Set the height of WINDOW and all its inferiors. */
2644 /* The smallest acceptable dimensions for a window. Anything smaller
2645 might crash Emacs. */
2647 #define MIN_SAFE_WINDOW_WIDTH (2)
2648 #define MIN_SAFE_WINDOW_HEIGHT (1)
2650 /* For wp non-zero the total number of columns of window w. Otherwise
2651 the total number of lines of w. */
2653 #define WINDOW_TOTAL_SIZE(w, wp) \
2654 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2656 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2657 minimum allowable size. */
2659 void
2660 check_frame_size (FRAME_PTR frame, int *rows, int *cols)
2662 /* For height, we have to see:
2663 how many windows the frame has at minimum (one or two),
2664 and whether it has a menu bar or other special stuff at the top. */
2665 int min_height
2666 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2667 ? MIN_SAFE_WINDOW_HEIGHT
2668 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2670 if (FRAME_TOP_MARGIN (frame) > 0)
2671 min_height += FRAME_TOP_MARGIN (frame);
2673 if (*rows < min_height)
2674 *rows = min_height;
2675 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2676 *cols = MIN_SAFE_WINDOW_WIDTH;
2679 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2680 check if W's width can be changed, otherwise check W's height.
2681 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2682 siblings, too. If none of the siblings is resizable, WINDOW isn't
2683 either. */
2685 static int
2686 window_fixed_size_p (struct window *w, int width_p, int check_siblings_p)
2688 int fixed_p;
2689 struct window *c;
2691 if (!NILP (w->hchild))
2693 c = XWINDOW (w->hchild);
2695 if (width_p)
2697 /* A horizontal combination is fixed-width if all of if its
2698 children are. */
2699 while (c && window_fixed_size_p (c, width_p, 0))
2700 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2701 fixed_p = c == NULL;
2703 else
2705 /* A horizontal combination is fixed-height if one of if its
2706 children is. */
2707 while (c && !window_fixed_size_p (c, width_p, 0))
2708 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2709 fixed_p = c != NULL;
2712 else if (!NILP (w->vchild))
2714 c = XWINDOW (w->vchild);
2716 if (width_p)
2718 /* A vertical combination is fixed-width if one of if its
2719 children is. */
2720 while (c && !window_fixed_size_p (c, width_p, 0))
2721 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2722 fixed_p = c != NULL;
2724 else
2726 /* A vertical combination is fixed-height if all of if its
2727 children are. */
2728 while (c && window_fixed_size_p (c, width_p, 0))
2729 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2730 fixed_p = c == NULL;
2733 else if (BUFFERP (w->buffer))
2735 struct buffer *old = current_buffer;
2736 Lisp_Object val;
2738 current_buffer = XBUFFER (w->buffer);
2739 val = find_symbol_value (Qwindow_size_fixed);
2740 current_buffer = old;
2742 fixed_p = 0;
2743 if (!EQ (val, Qunbound))
2745 fixed_p = !NILP (val);
2747 if (fixed_p
2748 && ((EQ (val, Qheight) && width_p)
2749 || (EQ (val, Qwidth) && !width_p)))
2750 fixed_p = 0;
2753 /* Can't tell if this one is resizable without looking at
2754 siblings. If all siblings are fixed-size this one is too. */
2755 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2757 Lisp_Object child;
2759 for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev)
2760 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2761 break;
2763 if (NILP (child))
2764 for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next)
2765 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2766 break;
2768 if (NILP (child))
2769 fixed_p = 1;
2772 else
2773 fixed_p = 1;
2775 return fixed_p;
2778 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2779 the minimum width of W, WIDTH_P zero means return the minimum height
2780 of W. SAFE_P non-zero means ignore window-min-height|width but just
2781 return values that won't crash Emacs and don't hide components like
2782 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2783 minibuffer window, always return 1. */
2785 static int
2786 window_min_size_2 (struct window *w, int width_p, int safe_p)
2788 /* We should consider buffer-local values of window_min_height and
2789 window_min_width here. */
2790 if (width_p)
2792 int safe_size = (MIN_SAFE_WINDOW_WIDTH
2793 + WINDOW_FRINGE_COLS (w)
2794 + WINDOW_SCROLL_BAR_COLS (w));
2796 return safe_p ? safe_size : max (window_min_width, safe_size);
2798 else if (MINI_WINDOW_P (w))
2799 return 1;
2800 else
2802 int safe_size = (MIN_SAFE_WINDOW_HEIGHT
2803 + ((BUFFERP (w->buffer)
2804 && !NILP (XBUFFER (w->buffer)->mode_line_format))
2805 ? 1 : 0));
2807 return safe_p ? safe_size : max (window_min_height, safe_size);
2811 /* Return minimum size of window W, not taking fixed-width windows into
2812 account. WIDTH_P non-zero means return the minimum width, otherwise
2813 return the minimum height. SAFE_P non-zero means ignore
2814 window-min-height|width but just return values that won't crash Emacs
2815 and don't hide components like fringes, scrollbars, or modelines. If
2816 W is a combination window, compute the minimum size from the minimum
2817 sizes of W's children. */
2819 static int
2820 window_min_size_1 (struct window *w, int width_p, int safe_p)
2822 struct window *c;
2823 int size;
2825 if (!NILP (w->hchild))
2827 /* W is a horizontal combination. */
2828 c = XWINDOW (w->hchild);
2829 size = 0;
2831 if (width_p)
2833 /* The minimum width of a horizontal combination is the sum of
2834 the minimum widths of its children. */
2835 while (c)
2837 size += window_min_size_1 (c, 1, safe_p);
2838 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2841 else
2843 /* The minimum height of a horizontal combination is the
2844 maximum of the minimum heights of its children. */
2845 while (c)
2847 size = max (window_min_size_1 (c, 0, safe_p), size);
2848 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2852 else if (!NILP (w->vchild))
2854 /* W is a vertical combination. */
2855 c = XWINDOW (w->vchild);
2856 size = 0;
2858 if (width_p)
2860 /* The minimum width of a vertical combination is the maximum
2861 of the minimum widths of its children. */
2862 while (c)
2864 size = max (window_min_size_1 (c, 1, safe_p), size);
2865 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2868 else
2870 /* The minimum height of a vertical combination is the sum of
2871 the minimum height of its children. */
2872 while (c)
2874 size += window_min_size_1 (c, 0, safe_p);
2875 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2879 else
2880 /* W is a leaf window. */
2881 size = window_min_size_2 (w, width_p, safe_p);
2883 return size;
2886 /* Return the minimum size of window W, taking fixed-size windows into
2887 account. WIDTH_P non-zero means return the minimum width, otherwise
2888 return the minimum height. SAFE_P non-zero means ignore
2889 window-min-height|width but just return values that won't crash Emacs
2890 and don't hide components like fringes, scrollbars, or modelines.
2891 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2892 to 1 if W is fixed-size unless FIXED is null. */
2894 static int
2895 window_min_size (struct window *w, int width_p, int safe_p, int ignore_fixed_p, int *fixed)
2897 int size, fixed_p;
2899 if (ignore_fixed_p)
2900 fixed_p = 0;
2901 else
2902 fixed_p = window_fixed_size_p (w, width_p, 1);
2904 if (fixed)
2905 *fixed = fixed_p;
2907 if (fixed_p)
2908 size = WINDOW_TOTAL_SIZE (w, width_p);
2909 else
2910 size = window_min_size_1 (w, width_p, safe_p);
2912 return size;
2916 /* Adjust the margins of window W if text area is too small.
2917 Return 1 if window width is ok after adjustment; 0 if window
2918 is still too narrow. */
2920 static int
2921 adjust_window_margins (struct window *w)
2923 int box_cols = (WINDOW_TOTAL_COLS (w)
2924 - WINDOW_FRINGE_COLS (w)
2925 - WINDOW_SCROLL_BAR_COLS (w));
2926 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2927 + WINDOW_RIGHT_MARGIN_COLS (w));
2929 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2930 return 1;
2932 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2933 return 0;
2935 /* Window's text area is too narrow, but reducing the window
2936 margins will fix that. */
2937 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2938 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2940 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2941 w->left_margin_cols = w->right_margin_cols
2942 = make_number (margin_cols/2);
2943 else
2944 w->right_margin_cols = make_number (margin_cols);
2946 else
2947 w->left_margin_cols = make_number (margin_cols);
2948 return 1;
2951 /* Calculate new sizes for windows in the list FORWARD when their
2952 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2953 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2954 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2955 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2956 shrink columns, otherwise shrink lines.
2958 SAFE_P zero means windows may be sized down to window-min-height
2959 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2960 non-zero means windows may be sized down to their minimum safe sizes
2961 taking into account the space needed to display modelines, fringes,
2962 and scrollbars.
2964 This function returns an allocated array of new sizes that the caller
2965 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2966 zero. A size zero means the window shall be deleted. Array index 0
2967 refers to the first window in FORWARD, 1 to the second, and so on.
2969 This function resizes windows proportionally to their size. It also
2970 tries to preserve smaller windows by resizing larger windows before
2971 resizing any window to zero. If resize_proportionally is non-nil for
2972 a specific window, it will attempt to strictly resize that window
2973 proportionally, even at the expense of deleting smaller windows. */
2974 static int *
2975 shrink_windows (int total, int size, int nchildren, int shrinkable,
2976 int resize_fixed_p, Lisp_Object forward, int width_p, int safe_p)
2978 int available_resize = 0;
2979 int *new_sizes, *min_sizes;
2980 struct window *c;
2981 Lisp_Object child;
2982 int smallest = total;
2983 int total_removed = 0;
2984 int total_shrink = total - size;
2985 int i;
2987 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2988 min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
2990 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2992 int child_size;
2994 c = XWINDOW (child);
2995 child_size = WINDOW_TOTAL_SIZE (c, width_p);
2997 if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2998 new_sizes[i] = -1;
2999 else
3001 new_sizes[i] = child_size;
3002 min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
3003 if (child_size > min_sizes[i]
3004 && NILP (c->resize_proportionally))
3005 available_resize += child_size - min_sizes[i];
3008 /* We might need to shrink some windows to zero. Find the smallest
3009 windows and set them to 0 until we can fulfil the new size. */
3011 while (shrinkable > 1 && size + available_resize < total)
3013 for (i = 0; i < nchildren; ++i)
3014 if (new_sizes[i] > 0 && smallest > new_sizes[i])
3015 smallest = new_sizes[i];
3017 for (i = 0; i < nchildren; ++i)
3018 if (new_sizes[i] == smallest)
3020 /* Resize this window down to zero. */
3021 new_sizes[i] = 0;
3022 if (smallest > min_sizes[i])
3023 available_resize -= smallest - min_sizes[i];
3024 available_resize += smallest;
3025 --shrinkable;
3026 total_removed += smallest;
3028 /* We don't know what the smallest is now. */
3029 smallest = total;
3031 /* Out of for, just remove one window at the time and
3032 check again if we have enough space. */
3033 break;
3037 /* Now, calculate the new sizes. Try to shrink each window
3038 proportional to its size. */
3039 for (i = 0; i < nchildren; ++i)
3041 if (new_sizes[i] > min_sizes[i])
3043 int to_shrink = total_shrink * new_sizes[i] / total;
3045 if (new_sizes[i] - to_shrink < min_sizes[i])
3046 to_shrink = new_sizes[i] - min_sizes[i];
3047 new_sizes[i] -= to_shrink;
3048 total_removed += to_shrink;
3052 /* Any reminder due to rounding, we just subtract from windows
3053 that are left and still can be shrunk. */
3054 while (total_shrink > total_removed)
3056 int nonzero_sizes = 0;
3057 int nonzero_idx = -1;
3059 for (i = 0; i < nchildren; ++i)
3060 if (new_sizes[i] > 0)
3062 ++nonzero_sizes;
3063 nonzero_idx = i;
3066 for (i = 0; i < nchildren; ++i)
3067 if (new_sizes[i] > min_sizes[i])
3069 --new_sizes[i];
3070 ++total_removed;
3072 /* Out of for, just shrink one window at the time and
3073 check again if we have enough space. */
3074 break;
3077 /* Special case, only one window left. */
3078 if (nonzero_sizes == 1)
3079 break;
3082 /* Any surplus due to rounding, we add to windows that are left. */
3083 while (total_shrink < total_removed)
3085 for (i = 0; i < nchildren; ++i)
3087 if (new_sizes[i] != 0 && total_shrink < total_removed)
3089 ++new_sizes[i];
3090 --total_removed;
3091 break;
3096 xfree (min_sizes);
3098 return new_sizes;
3101 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3102 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3103 their proportionate size relative to WINDOW.
3105 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3106 they are in series. If LAST_ONLY is 1, change only the last of
3107 WINDOW's children when they are in series.
3109 Propagate WINDOW's top or left edge position to children. Delete
3110 windows that become too small unless NODELETE_P is 1. When
3111 NODELETE_P equals 2 do not honor settings for window-min-height and
3112 window-min-width when resizing windows but use safe defaults instead.
3113 This should give better behavior when resizing frames. */
3115 static void
3116 size_window (Lisp_Object window, int size, int width_p, int nodelete_p, int first_only, int last_only)
3118 struct window *w = XWINDOW (window);
3119 struct window *c;
3120 Lisp_Object child, *forward, *sideward;
3121 int old_size = WINDOW_TOTAL_SIZE (w, width_p);
3123 size = max (0, size);
3125 /* Delete WINDOW if it's too small. */
3126 if (nodelete_p != 1 && !NILP (w->parent)
3127 && size < window_min_size_1 (w, width_p, nodelete_p == 2))
3129 delete_window (window);
3130 return;
3133 /* Set redisplay hints. */
3134 w->last_modified = make_number (0);
3135 w->last_overlay_modified = make_number (0);
3136 windows_or_buffers_changed++;
3137 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3139 if (width_p)
3141 sideward = &w->vchild;
3142 forward = &w->hchild;
3143 w->total_cols = make_number (size);
3144 adjust_window_margins (w);
3146 else
3148 sideward = &w->hchild;
3149 forward = &w->vchild;
3150 w->total_lines = make_number (size);
3151 w->orig_total_lines = Qnil;
3154 if (!NILP (*sideward))
3156 /* We have a chain of parallel siblings whose size should all change. */
3157 for (child = *sideward; !NILP (child); child = c->next)
3159 c = XWINDOW (child);
3160 if (width_p)
3161 c->left_col = w->left_col;
3162 else
3163 c->top_line = w->top_line;
3164 size_window (child, size, width_p, nodelete_p,
3165 first_only, last_only);
3168 else if (!NILP (*forward) && last_only)
3170 /* Change the last in a series of siblings. */
3171 Lisp_Object last_child;
3172 int child_size;
3174 for (child = *forward; !NILP (child); child = c->next)
3176 c = XWINDOW (child);
3177 last_child = child;
3180 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3181 size_window (last_child, size - old_size + child_size,
3182 width_p, nodelete_p, first_only, last_only);
3184 else if (!NILP (*forward) && first_only)
3186 /* Change the first in a series of siblings. */
3187 int child_size;
3189 child = *forward;
3190 c = XWINDOW (child);
3192 if (width_p)
3193 c->left_col = w->left_col;
3194 else
3195 c->top_line = w->top_line;
3197 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3198 size_window (child, size - old_size + child_size,
3199 width_p, nodelete_p, first_only, last_only);
3201 else if (!NILP (*forward))
3203 int fixed_size, each, extra, n;
3204 int resize_fixed_p, nfixed;
3205 int last_pos, first_pos, nchildren, total;
3206 int *new_sizes = NULL;
3208 /* Determine the fixed-size portion of this window, and the
3209 number of child windows. */
3210 fixed_size = nchildren = nfixed = total = 0;
3211 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3213 int child_size;
3215 c = XWINDOW (child);
3216 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3217 total += child_size;
3219 if (window_fixed_size_p (c, width_p, 0))
3221 fixed_size += child_size;
3222 ++nfixed;
3226 /* If the new size is smaller than fixed_size, or if there
3227 aren't any resizable windows, allow resizing fixed-size
3228 windows. */
3229 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3231 /* Compute how many lines/columns to add/remove to each child. The
3232 value of extra takes care of rounding errors. */
3233 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3234 if (size < total && n > 1)
3235 new_sizes = shrink_windows (total, size, nchildren, n,
3236 resize_fixed_p, *forward, width_p,
3237 nodelete_p == 2);
3238 else
3240 each = (size - total) / n;
3241 extra = (size - total) - n * each;
3244 /* Compute new children heights and edge positions. */
3245 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3246 last_pos = first_pos;
3247 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3249 int new_size, old_size;
3251 c = XWINDOW (child);
3252 old_size = WINDOW_TOTAL_SIZE (c, width_p);
3253 new_size = old_size;
3255 /* The top or left edge position of this child equals the
3256 bottom or right edge of its predecessor. */
3257 if (width_p)
3258 c->left_col = make_number (last_pos);
3259 else
3260 c->top_line = make_number (last_pos);
3262 /* If this child can be resized, do it. */
3263 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3265 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3266 extra = 0;
3269 /* Set new size. Note that size_window also propagates
3270 edge positions to children, so it's not a no-op if we
3271 didn't change the child's size. */
3272 size_window (child, new_size, width_p, 1, first_only, last_only);
3274 /* Remember the bottom/right edge position of this child; it
3275 will be used to set the top/left edge of the next child. */
3276 last_pos += new_size;
3279 xfree (new_sizes);
3281 /* We should have covered the parent exactly with child windows. */
3282 xassert (size == last_pos - first_pos);
3284 /* Now delete any children that became too small. */
3285 if (nodelete_p != 1)
3286 for (child = *forward; !NILP (child); child = c->next)
3288 int child_size;
3290 c = XWINDOW (child);
3291 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3292 size_window (child, child_size, width_p, nodelete_p,
3293 first_only, last_only);
3298 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3299 WINDOW's children. NODELETE zero means windows that have become
3300 smaller than window-min-height in the process may be deleted.
3301 NODELETE 1 means never delete windows that become too small in the
3302 process. (The caller should check later and do so if appropriate.)
3303 NODELETE 2 means delete only windows that have become too small to be
3304 displayed correctly. */
3306 void
3307 set_window_height (Lisp_Object window, int height, int nodelete)
3309 size_window (window, height, 0, nodelete, 0, 0);
3312 /* Set WINDOW's width to WIDTH, and recursively change the width of
3313 WINDOW's children. NODELETE zero means windows that have become
3314 smaller than window-min-width in the process may be deleted.
3315 NODELETE 1 means never delete windows that become too small in the
3316 process. (The caller should check later and do so if appropriate.)
3317 NODELETE 2 means delete only windows that have become too small to be
3318 displayed correctly. */
3320 void
3321 set_window_width (Lisp_Object window, int width, int nodelete)
3323 size_window (window, width, 1, nodelete, 0, 0);
3326 /* Change window heights in windows rooted in WINDOW by N lines. */
3328 void
3329 change_window_heights (Lisp_Object window, int n)
3331 struct window *w = XWINDOW (window);
3333 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3334 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3336 if (INTEGERP (w->orig_top_line))
3337 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3338 if (INTEGERP (w->orig_total_lines))
3339 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3341 /* Handle just the top child in a vertical split. */
3342 if (!NILP (w->vchild))
3343 change_window_heights (w->vchild, n);
3345 /* Adjust all children in a horizontal split. */
3346 for (window = w->hchild; !NILP (window); window = w->next)
3348 w = XWINDOW (window);
3349 change_window_heights (window, n);
3354 int window_select_count;
3356 EXFUN (Fset_window_fringes, 4);
3357 EXFUN (Fset_window_scroll_bars, 4);
3359 static void
3360 run_funs (Lisp_Object funs)
3362 for (; CONSP (funs); funs = XCDR (funs))
3363 if (!EQ (XCAR (funs), Qt))
3364 call0 (XCAR (funs));
3367 static Lisp_Object select_window_norecord (Lisp_Object window);
3368 static Lisp_Object select_frame_norecord (Lisp_Object frame);
3370 void
3371 run_window_configuration_change_hook (struct frame *f)
3373 int count = SPECPDL_INDEX ();
3374 Lisp_Object frame, global_wcch
3375 = Fdefault_value (Qwindow_configuration_change_hook);
3376 XSETFRAME (frame, f);
3378 if (NILP (Vrun_hooks))
3379 return;
3381 if (SELECTED_FRAME () != f)
3383 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3384 Fselect_frame (frame, Qt);
3387 /* Use the right buffer. Matters when running the local hooks. */
3388 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3390 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3391 Fset_buffer (Fwindow_buffer (Qnil));
3394 /* Look for buffer-local values. */
3396 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3397 for (; CONSP (windows); windows = XCDR (windows))
3399 Lisp_Object window = XCAR (windows);
3400 Lisp_Object buffer = Fwindow_buffer (window);
3401 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3402 buffer)))
3404 int count = SPECPDL_INDEX ();
3405 record_unwind_protect (select_window_norecord, Fselected_window ());
3406 select_window_norecord (window);
3407 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3408 buffer));
3409 unbind_to (count, Qnil);
3414 run_funs (global_wcch);
3415 unbind_to (count, Qnil);
3418 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3419 means it's allowed to run hooks. See make_frame for a case where
3420 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3421 margins, fringes, and scroll-bar settings of the window are not
3422 reset from the buffer's local settings. */
3424 void
3425 set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
3427 struct window *w = XWINDOW (window);
3428 struct buffer *b = XBUFFER (buffer);
3429 int count = SPECPDL_INDEX ();
3430 int samebuf = EQ (buffer, w->buffer);
3432 w->buffer = buffer;
3434 if (EQ (window, selected_window))
3435 b->last_selected_window = window;
3437 /* Let redisplay errors through. */
3438 b->display_error_modiff = 0;
3440 /* Update time stamps of buffer display. */
3441 if (INTEGERP (b->display_count))
3442 XSETINT (b->display_count, XINT (b->display_count) + 1);
3443 b->display_time = Fcurrent_time ();
3445 XSETFASTINT (w->window_end_pos, 0);
3446 XSETFASTINT (w->window_end_vpos, 0);
3447 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3448 w->window_end_valid = Qnil;
3449 if (!(keep_margins_p && samebuf))
3450 { /* If we're not actually changing the buffer, don't reset hscroll and
3451 vscroll. This case happens for example when called from
3452 change_frame_size_1, where we use a dummy call to
3453 Fset_window_buffer on the frame's selected window (and no other)
3454 just in order to run window-configuration-change-hook.
3455 Resetting hscroll and vscroll here is problematic for things like
3456 image-mode and doc-view-mode since it resets the image's position
3457 whenever we resize the frame. */
3458 w->hscroll = w->min_hscroll = make_number (0);
3459 w->vscroll = 0;
3460 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3461 set_marker_restricted (w->start,
3462 make_number (b->last_window_start),
3463 buffer);
3464 w->start_at_line_beg = Qnil;
3465 w->force_start = Qnil;
3466 XSETFASTINT (w->last_modified, 0);
3467 XSETFASTINT (w->last_overlay_modified, 0);
3469 /* Maybe we could move this into the `if' but it's not obviously safe and
3470 I doubt it's worth the trouble. */
3471 windows_or_buffers_changed++;
3473 /* We must select BUFFER for running the window-scroll-functions. */
3474 /* We can't check ! NILP (Vwindow_scroll_functions) here
3475 because that might itself be a local variable. */
3476 if (window_initialized)
3478 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3479 Fset_buffer (buffer);
3482 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3484 if (!keep_margins_p)
3486 /* Set left and right marginal area width etc. from buffer. */
3488 /* This may call adjust_window_margins three times, so
3489 temporarily disable window margins. */
3490 Lisp_Object save_left = w->left_margin_cols;
3491 Lisp_Object save_right = w->right_margin_cols;
3493 w->left_margin_cols = w->right_margin_cols = Qnil;
3495 Fset_window_fringes (window,
3496 b->left_fringe_width, b->right_fringe_width,
3497 b->fringes_outside_margins);
3499 Fset_window_scroll_bars (window,
3500 b->scroll_bar_width,
3501 b->vertical_scroll_bar_type, Qnil);
3503 w->left_margin_cols = save_left;
3504 w->right_margin_cols = save_right;
3506 Fset_window_margins (window,
3507 b->left_margin_cols, b->right_margin_cols);
3510 if (run_hooks_p)
3512 if (! NILP (Vwindow_scroll_functions))
3513 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3514 Fmarker_position (w->start));
3515 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3518 unbind_to (count, Qnil);
3522 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3523 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3524 WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
3525 or the name of an existing buffer. Optional third argument KEEP-MARGINS
3526 non-nil means that WINDOW's current display margins, fringe widths, and
3527 scroll bar settings are preserved; the default is to reset these from
3528 the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
3530 This function throws an error when WINDOW is strongly dedicated to its
3531 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3532 already display BUFFER-OR-NAME.
3534 This function runs `window-scroll-functions' before running
3535 `window-configuration-change-hook'. */)
3536 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3538 register Lisp_Object tem, buffer;
3539 register struct window *w = decode_window (window);
3541 XSETWINDOW (window, w);
3542 buffer = Fget_buffer (buffer_or_name);
3543 CHECK_BUFFER (buffer);
3544 if (NILP (XBUFFER (buffer)->name))
3545 error ("Attempt to display deleted buffer");
3547 tem = w->buffer;
3548 if (NILP (tem))
3549 error ("Window is deleted");
3550 else if (!EQ (tem, Qt))
3551 /* w->buffer is t when the window is first being set up. */
3553 if (!EQ (tem, buffer))
3554 if (EQ (w->dedicated, Qt))
3555 error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem)->name));
3556 else
3557 w->dedicated = Qnil;
3559 unshow_buffer (w);
3562 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3563 return Qnil;
3566 /* Note that selected_window can be nil when this is called from
3567 Fset_window_configuration. */
3569 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3570 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3571 If WINDOW is not already selected, make WINDOW's buffer current
3572 and make WINDOW the frame's selected window. Return WINDOW.
3573 Optional second arg NORECORD non-nil means do not put this buffer
3574 at the front of the list of recently selected ones and do not
3575 make this window the most recently selected one.
3577 Note that the main editor command loop selects the buffer of the
3578 selected window before each command. */)
3579 (register Lisp_Object window, Lisp_Object norecord)
3581 register struct window *w;
3582 register struct window *ow;
3583 struct frame *sf;
3585 CHECK_LIVE_WINDOW (window);
3587 w = XWINDOW (window);
3588 w->frozen_window_start_p = 0;
3590 if (NILP (norecord))
3592 ++window_select_count;
3593 XSETFASTINT (w->use_time, window_select_count);
3594 record_buffer (w->buffer);
3597 if (EQ (window, selected_window))
3598 return window;
3600 sf = SELECTED_FRAME ();
3601 if (XFRAME (WINDOW_FRAME (w)) != sf)
3603 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3604 /* Use this rather than Fhandle_switch_frame
3605 so that FRAME_FOCUS_FRAME is moved appropriately as we
3606 move around in the state where a minibuffer in a separate
3607 frame is active. */
3608 Fselect_frame (WINDOW_FRAME (w), norecord);
3609 /* Fselect_frame called us back so we've done all the work already. */
3610 eassert (EQ (window, selected_window));
3611 return window;
3613 else
3614 sf->selected_window = window;
3616 /* Store the current buffer's actual point into the
3617 old selected window. It belongs to that window,
3618 and when the window is not selected, must be in the window. */
3619 if (!NILP (selected_window))
3621 ow = XWINDOW (selected_window);
3622 if (! NILP (ow->buffer))
3623 set_marker_both (ow->pointm, ow->buffer,
3624 BUF_PT (XBUFFER (ow->buffer)),
3625 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3628 selected_window = window;
3630 Fset_buffer (w->buffer);
3632 XBUFFER (w->buffer)->last_selected_window = window;
3634 /* Go to the point recorded in the window.
3635 This is important when the buffer is in more
3636 than one window. It also matters when
3637 redisplay_window has altered point after scrolling,
3638 because it makes the change only in the window. */
3640 register int new_point = marker_position (w->pointm);
3641 if (new_point < BEGV)
3642 SET_PT (BEGV);
3643 else if (new_point > ZV)
3644 SET_PT (ZV);
3645 else
3646 SET_PT (new_point);
3649 windows_or_buffers_changed++;
3650 return window;
3653 static Lisp_Object
3654 select_window_norecord (Lisp_Object window)
3656 return WINDOW_LIVE_P (window)
3657 ? Fselect_window (window, Qt) : selected_window;
3660 static Lisp_Object
3661 select_frame_norecord (Lisp_Object frame)
3663 return FRAME_LIVE_P (XFRAME (frame))
3664 ? Fselect_frame (frame, Qt) : selected_frame;
3667 Lisp_Object
3668 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3670 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3673 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3674 0, 1, 0,
3675 doc: /* Force all windows to be updated on next redisplay.
3676 If optional arg OBJECT is a window, force redisplay of that window only.
3677 If OBJECT is a buffer or buffer name, force redisplay of all windows
3678 displaying that buffer. */)
3679 (Lisp_Object object)
3681 if (NILP (object))
3683 windows_or_buffers_changed++;
3684 update_mode_lines++;
3685 return Qt;
3688 if (WINDOWP (object))
3690 struct window *w = XWINDOW (object);
3691 mark_window_display_accurate (object, 0);
3692 w->update_mode_line = Qt;
3693 if (BUFFERP (w->buffer))
3694 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3695 ++update_mode_lines;
3696 return Qt;
3699 if (STRINGP (object))
3700 object = Fget_buffer (object);
3701 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3703 /* Walk all windows looking for buffer, and force update
3704 of each of those windows. */
3706 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3707 return NILP (object) ? Qnil : Qt;
3710 /* If nothing suitable was found, just return.
3711 We could signal an error, but this feature will typically be used
3712 asynchronously in timers or process sentinels, so we don't. */
3713 return Qnil;
3717 void
3718 temp_output_buffer_show (register Lisp_Object buf)
3720 register struct buffer *old = current_buffer;
3721 register Lisp_Object window;
3722 register struct window *w;
3724 XBUFFER (buf)->directory = current_buffer->directory;
3726 Fset_buffer (buf);
3727 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3728 BEGV = BEG;
3729 ZV = Z;
3730 SET_PT (BEG);
3731 #if 0 /* rms: there should be no reason for this. */
3732 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3733 #endif
3734 set_buffer_internal (old);
3736 if (!NILP (Vtemp_buffer_show_function))
3737 call1 (Vtemp_buffer_show_function, buf);
3738 else
3740 window = display_buffer (buf, Qnil, Qnil);
3742 if (!EQ (XWINDOW (window)->frame, selected_frame))
3743 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3744 Vminibuf_scroll_window = window;
3745 w = XWINDOW (window);
3746 XSETFASTINT (w->hscroll, 0);
3747 XSETFASTINT (w->min_hscroll, 0);
3748 set_marker_restricted_both (w->start, buf, BEG, BEG);
3749 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3751 /* Run temp-buffer-show-hook, with the chosen window selected
3752 and its buffer current. */
3754 if (!NILP (Vrun_hooks)
3755 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3756 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3758 int count = SPECPDL_INDEX ();
3759 Lisp_Object prev_window, prev_buffer;
3760 prev_window = selected_window;
3761 XSETBUFFER (prev_buffer, old);
3763 /* Select the window that was chosen, for running the hook.
3764 Note: Both Fselect_window and select_window_norecord may
3765 set-buffer to the buffer displayed in the window,
3766 so we need to save the current buffer. --stef */
3767 record_unwind_protect (Fset_buffer, prev_buffer);
3768 record_unwind_protect (select_window_norecord, prev_window);
3769 Fselect_window (window, Qt);
3770 Fset_buffer (w->buffer);
3771 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3772 unbind_to (count, Qnil);
3777 static void
3778 make_dummy_parent (Lisp_Object window)
3780 Lisp_Object new;
3781 register struct window *o, *p;
3782 int i;
3784 o = XWINDOW (window);
3785 p = allocate_window ();
3786 for (i = 0; i < VECSIZE (struct window); ++i)
3787 ((struct Lisp_Vector *) p)->contents[i]
3788 = ((struct Lisp_Vector *)o)->contents[i];
3789 XSETWINDOW (new, p);
3791 ++sequence_number;
3792 XSETFASTINT (p->sequence_number, sequence_number);
3794 /* Put new into window structure in place of window */
3795 replace_window (window, new);
3797 o->next = Qnil;
3798 o->prev = Qnil;
3799 o->vchild = Qnil;
3800 o->hchild = Qnil;
3801 o->parent = new;
3803 p->start = Qnil;
3804 p->pointm = Qnil;
3805 p->buffer = Qnil;
3808 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3809 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3810 WINDOW defaults to selected one and SIZE to half its size.
3811 If optional third arg HORIZONTAL is non-nil, split side by side and put
3812 SIZE columns in the first of the pair. In that case, SIZE includes that
3813 window's scroll bar, or the divider column to its right.
3814 Interactively, all arguments are nil.
3815 Returns the newly created window (which is the lower or rightmost one).
3816 The upper or leftmost window is the original one, and remains selected
3817 if it was selected before.
3819 See Info node `(elisp)Splitting Windows' for more details and examples. */)
3820 (Lisp_Object window, Lisp_Object size, Lisp_Object horizontal)
3822 register Lisp_Object new;
3823 register struct window *o, *p;
3824 FRAME_PTR fo;
3825 register int size_int;
3827 if (NILP (window))
3828 window = selected_window;
3829 else
3830 CHECK_LIVE_WINDOW (window);
3832 o = XWINDOW (window);
3833 fo = XFRAME (WINDOW_FRAME (o));
3835 if (NILP (size))
3837 if (!NILP (horizontal))
3838 /* Calculate the size of the left-hand window, by dividing
3839 the usable space in columns by two.
3840 We round up, since the left-hand window may include
3841 a dividing line, while the right-hand may not. */
3842 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3843 else
3844 size_int = XFASTINT (o->total_lines) >> 1;
3846 else
3848 CHECK_NUMBER (size);
3849 size_int = XINT (size);
3852 if (MINI_WINDOW_P (o))
3853 error ("Attempt to split minibuffer window");
3854 else if (window_fixed_size_p (o, !NILP (horizontal), 0))
3855 error ("Attempt to split fixed-size window");
3857 if (NILP (horizontal))
3859 int window_safe_height = window_min_size_2 (o, 0, 0);
3861 if (size_int < window_safe_height)
3862 error ("Window height %d too small (after splitting)", size_int);
3863 if (size_int + window_safe_height > XFASTINT (o->total_lines))
3864 error ("Window height %d too small (after splitting)",
3865 XFASTINT (o->total_lines) - size_int);
3866 if (NILP (o->parent)
3867 || NILP (XWINDOW (o->parent)->vchild))
3869 make_dummy_parent (window);
3870 new = o->parent;
3871 XWINDOW (new)->vchild = window;
3874 else
3876 int window_safe_width = window_min_size_2 (o, 1, 0);
3878 if (size_int < window_safe_width)
3879 error ("Window width %d too small (after splitting)", size_int);
3880 if (size_int + window_safe_width > XFASTINT (o->total_cols))
3881 error ("Window width %d too small (after splitting)",
3882 XFASTINT (o->total_cols) - size_int);
3883 if (NILP (o->parent)
3884 || NILP (XWINDOW (o->parent)->hchild))
3886 make_dummy_parent (window);
3887 new = o->parent;
3888 XWINDOW (new)->hchild = window;
3892 /* Now we know that window's parent is a vertical combination
3893 if we are dividing vertically, or a horizontal combination
3894 if we are making side-by-side windows */
3896 windows_or_buffers_changed++;
3897 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3898 new = make_window ();
3899 p = XWINDOW (new);
3901 p->frame = o->frame;
3902 p->next = o->next;
3903 if (!NILP (p->next))
3904 XWINDOW (p->next)->prev = new;
3905 p->prev = window;
3906 o->next = new;
3907 p->parent = o->parent;
3908 p->buffer = Qt;
3909 p->window_end_valid = Qnil;
3910 memset (&p->last_cursor, 0, sizeof p->last_cursor);
3912 /* Duplicate special geometry settings. */
3914 p->left_margin_cols = o->left_margin_cols;
3915 p->right_margin_cols = o->right_margin_cols;
3916 p->left_fringe_width = o->left_fringe_width;
3917 p->right_fringe_width = o->right_fringe_width;
3918 p->fringes_outside_margins = o->fringes_outside_margins;
3919 p->scroll_bar_width = o->scroll_bar_width;
3920 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3922 /* Apportion the available frame space among the two new windows */
3924 if (!NILP (horizontal))
3926 p->total_lines = o->total_lines;
3927 p->top_line = o->top_line;
3928 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3929 XSETFASTINT (o->total_cols, size_int);
3930 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3931 adjust_window_margins (p);
3932 adjust_window_margins (o);
3934 else
3936 p->left_col = o->left_col;
3937 p->total_cols = o->total_cols;
3938 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3939 XSETFASTINT (o->total_lines, size_int);
3940 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3943 /* Adjust glyph matrices. */
3944 adjust_glyphs (fo);
3946 Fset_window_buffer (new, o->buffer, Qt);
3947 return new;
3950 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3951 doc: /* Make selected window SIZE lines taller.
3952 Interactively, if no argument is given, make the selected window one
3953 line taller. If optional argument HORIZONTAL is non-nil, make selected
3954 window wider by SIZE columns. If SIZE is negative, shrink the window by
3955 -SIZE lines or columns. Return nil.
3957 This function can delete windows if they get too small. The size of
3958 fixed size windows is not altered by this function. */)
3959 (Lisp_Object size, Lisp_Object horizontal)
3961 CHECK_NUMBER (size);
3962 enlarge_window (selected_window, XINT (size), !NILP (horizontal));
3964 run_window_configuration_change_hook (SELECTED_FRAME ());
3966 return Qnil;
3969 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3970 doc: /* Make selected window SIZE lines smaller.
3971 Interactively, if no argument is given, make the selected window one
3972 line smaller. If optional argument HORIZONTAL is non-nil, make the
3973 window narrower by SIZE columns. If SIZE is negative, enlarge selected
3974 window by -SIZE lines or columns. Return nil.
3976 This function can delete windows if they get too small. The size of
3977 fixed size windows is not altered by this function. */)
3978 (Lisp_Object size, Lisp_Object horizontal)
3980 CHECK_NUMBER (size);
3981 enlarge_window (selected_window, -XINT (size), !NILP (horizontal));
3983 run_window_configuration_change_hook (SELECTED_FRAME ());
3985 return Qnil;
3989 window_height (Lisp_Object window)
3991 register struct window *p = XWINDOW (window);
3992 return WINDOW_TOTAL_LINES (p);
3996 window_width (Lisp_Object window)
3998 register struct window *p = XWINDOW (window);
3999 return WINDOW_TOTAL_COLS (p);
4003 #define CURBEG(w) \
4004 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4006 #define CURSIZE(w) \
4007 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4010 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4011 horizontally; zero means do it vertically.
4013 Siblings of the selected window are resized to fulfill the size
4014 request. If they become too small in the process, they may be
4015 deleted. */
4017 static void
4018 enlarge_window (Lisp_Object window, int delta, int horiz_flag)
4020 Lisp_Object parent, next, prev;
4021 struct window *p;
4022 Lisp_Object *sizep;
4023 int maximum;
4024 int (*sizefun) (Lisp_Object)
4025 = horiz_flag ? window_width : window_height;
4026 void (*setsizefun) (Lisp_Object, int, int)
4027 = (horiz_flag ? set_window_width : set_window_height);
4029 /* Give up if this window cannot be resized. */
4030 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4031 error ("Window is not resizable");
4033 /* Find the parent of the selected window. */
4034 while (1)
4036 p = XWINDOW (window);
4037 parent = p->parent;
4039 if (NILP (parent))
4041 if (horiz_flag)
4042 error ("No other window to side of this one");
4043 break;
4046 if (horiz_flag
4047 ? !NILP (XWINDOW (parent)->hchild)
4048 : !NILP (XWINDOW (parent)->vchild))
4049 break;
4051 window = parent;
4054 sizep = &CURSIZE (window);
4057 register int maxdelta;
4059 /* Compute the maximum size increment this window can have. */
4061 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4062 /* This is a main window followed by a minibuffer. */
4063 : !NILP (p->next) ? ((*sizefun) (p->next)
4064 - window_min_size (XWINDOW (p->next),
4065 horiz_flag, 0, 0, 0))
4066 /* This is a minibuffer following a main window. */
4067 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4068 - window_min_size (XWINDOW (p->prev),
4069 horiz_flag, 0, 0, 0))
4070 /* This is a frame with only one window, a minibuffer-only
4071 or a minibufferless frame. */
4072 : (delta = 0));
4074 if (delta > maxdelta)
4075 /* This case traps trying to make the minibuffer
4076 the full frame, or make the only window aside from the
4077 minibuffer the full frame. */
4078 delta = maxdelta;
4081 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
4082 horiz_flag, 0, 0, 0))
4084 delete_window (window);
4085 return;
4088 if (delta == 0)
4089 return;
4091 /* Find the total we can get from other siblings without deleting them. */
4092 maximum = 0;
4093 for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
4094 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4095 horiz_flag, 0, 0, 0);
4096 for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
4097 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4098 horiz_flag, 0, 0, 0);
4100 /* If we can get it all from them without deleting them, do so. */
4101 if (delta <= maximum)
4103 Lisp_Object first_unaffected;
4104 Lisp_Object first_affected;
4105 int fixed_p;
4107 next = p->next;
4108 prev = p->prev;
4109 first_affected = window;
4110 /* Look at one sibling at a time,
4111 moving away from this window in both directions alternately,
4112 and take as much as we can get without deleting that sibling. */
4113 while (delta != 0
4114 && (!NILP (next) || !NILP (prev)))
4116 if (! NILP (next))
4118 int this_one = ((*sizefun) (next)
4119 - window_min_size (XWINDOW (next), horiz_flag,
4120 0, 0, &fixed_p));
4121 if (!fixed_p)
4123 if (this_one > delta)
4124 this_one = delta;
4126 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4127 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4129 delta -= this_one;
4132 next = XWINDOW (next)->next;
4135 if (delta == 0)
4136 break;
4138 if (! NILP (prev))
4140 int this_one = ((*sizefun) (prev)
4141 - window_min_size (XWINDOW (prev), horiz_flag,
4142 0, 0, &fixed_p));
4143 if (!fixed_p)
4145 if (this_one > delta)
4146 this_one = delta;
4148 first_affected = prev;
4150 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4151 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4153 delta -= this_one;
4156 prev = XWINDOW (prev)->prev;
4160 xassert (delta == 0);
4162 /* Now recalculate the edge positions of all the windows affected,
4163 based on the new sizes. */
4164 first_unaffected = next;
4165 prev = first_affected;
4166 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4167 prev = next, next = XWINDOW (next)->next)
4169 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4170 /* This does not change size of NEXT,
4171 but it propagates the new top edge to its children */
4172 (*setsizefun) (next, (*sizefun) (next), 0);
4175 else
4177 register int delta1;
4178 register int opht = (*sizefun) (parent);
4180 if (opht <= XINT (*sizep) + delta)
4182 /* If trying to grow this window to or beyond size of the parent,
4183 just delete all the sibling windows. */
4184 Lisp_Object start, tem, next;
4186 start = XWINDOW (parent)->vchild;
4187 if (NILP (start))
4188 start = XWINDOW (parent)->hchild;
4190 /* Delete any siblings that come after WINDOW. */
4191 tem = XWINDOW (window)->next;
4192 while (! NILP (tem))
4194 next = XWINDOW (tem)->next;
4195 delete_window (tem);
4196 tem = next;
4199 /* Delete any siblings that come after WINDOW.
4200 Note that if START is not WINDOW, then WINDOW still
4201 has siblings, so WINDOW has not yet replaced its parent. */
4202 tem = start;
4203 while (! EQ (tem, window))
4205 next = XWINDOW (tem)->next;
4206 delete_window (tem);
4207 tem = next;
4210 else
4212 /* Otherwise, make delta1 just right so that if we add
4213 delta1 lines to this window and to the parent, and then
4214 shrink the parent back to its original size, the new
4215 proportional size of this window will increase by delta.
4217 The function size_window will compute the new height h'
4218 of the window from delta1 as:
4220 e = delta1/n
4221 x = delta1 - delta1/n * n for the 1st resizable child
4222 h' = h + e + x
4224 where n is the number of children that can be resized.
4225 We can ignore x by choosing a delta1 that is a multiple of
4226 n. We want the height of this window to come out as
4228 h' = h + delta
4230 So, delta1 must be
4232 h + e = h + delta
4233 delta1/n = delta
4234 delta1 = n * delta.
4236 The number of children n equals the number of resizable
4237 children of this window + 1 because we know window itself
4238 is resizable (otherwise we would have signaled an error).
4240 This reasoning is not correct when other windows become too
4241 small and shrink_windows refuses to delete them. Below we
4242 use resize_proportionally to work around this problem. */
4244 struct window *w = XWINDOW (window);
4245 Lisp_Object s;
4246 int n = 1;
4248 for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next)
4249 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4250 ++n;
4251 for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev)
4252 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4253 ++n;
4255 delta1 = n * delta;
4257 /* Add delta1 lines or columns to this window, and to the parent,
4258 keeping things consistent while not affecting siblings. */
4259 XSETINT (CURSIZE (parent), opht + delta1);
4260 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4262 /* Squeeze out delta1 lines or columns from our parent,
4263 shrinking this window and siblings proportionately. This
4264 brings parent back to correct size. Delta1 was calculated
4265 so this makes this window the desired size, taking it all
4266 out of the siblings.
4268 Temporarily set resize_proportionally to Qt to assure that,
4269 if necessary, shrink_windows deletes smaller windows rather
4270 than shrink this window. */
4271 w->resize_proportionally = Qt;
4272 (*setsizefun) (parent, opht, 0);
4273 w->resize_proportionally = Qnil;
4277 XSETFASTINT (p->last_modified, 0);
4278 XSETFASTINT (p->last_overlay_modified, 0);
4280 /* Adjust glyph matrices. */
4281 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4285 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4286 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4287 zero means adjust the height, moving the bottom edge.
4289 Following siblings of the selected window are resized to fulfill
4290 the size request. If they become too small in the process, they
4291 are not deleted; instead, we signal an error. */
4293 static void
4294 adjust_window_trailing_edge (Lisp_Object window, int delta, int horiz_flag)
4296 Lisp_Object parent, child;
4297 struct window *p;
4298 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4299 int delcount = window_deletion_count;
4301 CHECK_WINDOW (window);
4303 /* Give up if this window cannot be resized. */
4304 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4305 error ("Window is not resizable");
4307 while (1)
4309 Lisp_Object first_parallel = Qnil;
4311 if (NILP (window))
4313 /* This happens if WINDOW on the previous iteration was
4314 at top level of the window tree. */
4315 Fset_window_configuration (old_config);
4316 error ("Specified window edge is fixed");
4319 p = XWINDOW (window);
4320 parent = p->parent;
4322 /* See if this level has windows in parallel in the specified
4323 direction. If so, set FIRST_PARALLEL to the first one. */
4324 if (horiz_flag)
4326 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4327 first_parallel = XWINDOW (parent)->vchild;
4328 else if (NILP (parent) && !NILP (p->next))
4330 /* Handle the vertical chain of main window and minibuffer
4331 which has no parent. */
4332 first_parallel = window;
4333 while (! NILP (XWINDOW (first_parallel)->prev))
4334 first_parallel = XWINDOW (first_parallel)->prev;
4337 else
4339 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4340 first_parallel = XWINDOW (parent)->hchild;
4343 /* If this level's succession is in the desired dimension,
4344 and this window is the last one, and there is no higher level,
4345 its trailing edge is fixed. */
4346 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4347 && NILP (parent))
4349 Fset_window_configuration (old_config);
4350 error ("Specified window edge is fixed");
4353 /* Don't make this window too small. */
4354 if (XINT (CURSIZE (window)) + delta
4355 < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
4357 Fset_window_configuration (old_config);
4358 error ("Cannot adjust window size as specified");
4361 /* Clear out some redisplay caches. */
4362 XSETFASTINT (p->last_modified, 0);
4363 XSETFASTINT (p->last_overlay_modified, 0);
4365 /* Adjust this window's edge. */
4366 XSETINT (CURSIZE (window),
4367 XINT (CURSIZE (window)) + delta);
4369 /* If this window has following siblings in the desired dimension,
4370 make them smaller, and exit the loop.
4372 (If we reach the top of the tree and can never do this,
4373 we will fail and report an error, above.) */
4374 if (NILP (first_parallel))
4376 if (!NILP (p->next))
4378 /* This may happen for the minibuffer. In that case
4379 the window_deletion_count check below does not work. */
4380 if (XINT (CURSIZE (p->next)) - delta <= 0)
4382 Fset_window_configuration (old_config);
4383 error ("Cannot adjust window size as specified");
4386 XSETINT (CURBEG (p->next),
4387 XINT (CURBEG (p->next)) + delta);
4388 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4389 horiz_flag, 0, 1, 0);
4390 break;
4393 else
4394 /* Here we have a chain of parallel siblings, in the other dimension.
4395 Change the size of the other siblings. */
4396 for (child = first_parallel;
4397 ! NILP (child);
4398 child = XWINDOW (child)->next)
4399 if (! EQ (child, window))
4400 size_window (child, XINT (CURSIZE (child)) + delta,
4401 horiz_flag, 0, 0, 1);
4403 window = parent;
4406 /* If we made a window so small it got deleted,
4407 we failed. Report failure. */
4408 if (delcount != window_deletion_count)
4410 Fset_window_configuration (old_config);
4411 error ("Cannot adjust window size as specified");
4414 /* Adjust glyph matrices. */
4415 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4418 #undef CURBEG
4419 #undef CURSIZE
4421 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4422 Sadjust_window_trailing_edge, 3, 3, 0,
4423 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4424 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4425 Otherwise, adjust the height, moving the bottom edge.
4427 Following siblings of the selected window are resized to fulfill
4428 the size request. If they become too small in the process, they
4429 are not deleted; instead, we signal an error. */)
4430 (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal)
4432 CHECK_NUMBER (delta);
4433 if (NILP (window))
4434 window = selected_window;
4435 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4437 run_window_configuration_change_hook
4438 (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4440 return Qnil;
4445 /***********************************************************************
4446 Resizing Mini-Windows
4447 ***********************************************************************/
4449 static void shrink_window_lowest_first (struct window *, int);
4451 enum save_restore_action
4453 CHECK_ORIG_SIZES,
4454 SAVE_ORIG_SIZES,
4455 RESTORE_ORIG_SIZES
4458 static int save_restore_orig_size (struct window *,
4459 enum save_restore_action);
4461 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4462 from lowest windows first. */
4464 static void
4465 shrink_window_lowest_first (struct window *w, int height)
4467 struct window *c;
4468 Lisp_Object child;
4469 int old_height;
4471 xassert (!MINI_WINDOW_P (w));
4473 /* Set redisplay hints. */
4474 XSETFASTINT (w->last_modified, 0);
4475 XSETFASTINT (w->last_overlay_modified, 0);
4476 windows_or_buffers_changed++;
4477 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4479 old_height = XFASTINT (w->total_lines);
4480 XSETFASTINT (w->total_lines, height);
4482 if (!NILP (w->hchild))
4484 for (child = w->hchild; !NILP (child); child = c->next)
4486 c = XWINDOW (child);
4487 c->top_line = w->top_line;
4488 shrink_window_lowest_first (c, height);
4491 else if (!NILP (w->vchild))
4493 Lisp_Object last_child;
4494 int delta = old_height - height;
4495 int last_top;
4497 last_child = Qnil;
4499 /* Find the last child. We are taking space from lowest windows
4500 first, so we iterate over children from the last child
4501 backwards. */
4502 for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
4503 last_child = child;
4505 /* Size children down to their safe heights. */
4506 for (child = last_child; delta && !NILP (child); child = c->prev)
4508 int this_one;
4510 c = XWINDOW (child);
4511 this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
4513 if (this_one > delta)
4514 this_one = delta;
4516 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4517 delta -= this_one;
4520 /* Compute new positions. */
4521 last_top = XINT (w->top_line);
4522 for (child = w->vchild; !NILP (child); child = c->next)
4524 c = XWINDOW (child);
4525 c->top_line = make_number (last_top);
4526 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4527 last_top += XFASTINT (c->total_lines);
4533 /* Save, restore, or check positions and sizes in the window tree
4534 rooted at W. ACTION says what to do.
4536 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4537 orig_total_lines members are valid for all windows in the window
4538 tree. Value is non-zero if they are valid.
4540 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4541 orig_top_line and orig_total_lines for all windows in the tree.
4543 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4544 stored in orig_top_line and orig_total_lines for all windows. */
4546 static int
4547 save_restore_orig_size (struct window *w, enum save_restore_action action)
4549 int success_p = 1;
4551 while (w)
4553 if (!NILP (w->hchild))
4555 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4556 success_p = 0;
4558 else if (!NILP (w->vchild))
4560 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4561 success_p = 0;
4564 switch (action)
4566 case CHECK_ORIG_SIZES:
4567 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4568 return 0;
4569 break;
4571 case SAVE_ORIG_SIZES:
4572 w->orig_top_line = w->top_line;
4573 w->orig_total_lines = w->total_lines;
4574 XSETFASTINT (w->last_modified, 0);
4575 XSETFASTINT (w->last_overlay_modified, 0);
4576 break;
4578 case RESTORE_ORIG_SIZES:
4579 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4580 w->top_line = w->orig_top_line;
4581 w->total_lines = w->orig_total_lines;
4582 w->orig_total_lines = w->orig_top_line = Qnil;
4583 XSETFASTINT (w->last_modified, 0);
4584 XSETFASTINT (w->last_overlay_modified, 0);
4585 break;
4587 default:
4588 abort ();
4591 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4594 return success_p;
4598 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4599 without deleting other windows. */
4601 void
4602 grow_mini_window (struct window *w, int delta)
4604 struct frame *f = XFRAME (w->frame);
4605 struct window *root;
4607 xassert (MINI_WINDOW_P (w));
4608 /* Commenting out the following assertion goes against the stated interface
4609 of the function, but it currently does not seem to do anything useful.
4610 See discussion of this issue in the thread for bug#4534.
4611 xassert (delta >= 0); */
4613 /* Compute how much we can enlarge the mini-window without deleting
4614 other windows. */
4615 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4616 if (delta > 0)
4618 int min_height = window_min_size (root, 0, 0, 0, 0);
4619 if (XFASTINT (root->total_lines) - delta < min_height)
4620 /* Note that the root window may already be smaller than
4621 min_height. */
4622 delta = max (0, XFASTINT (root->total_lines) - min_height);
4625 if (delta)
4627 /* Save original window sizes and positions, if not already done. */
4628 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4629 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4631 /* Shrink other windows. */
4632 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4634 /* Grow the mini-window. */
4635 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4636 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4637 XSETFASTINT (w->last_modified, 0);
4638 XSETFASTINT (w->last_overlay_modified, 0);
4640 adjust_glyphs (f);
4645 /* Shrink mini-window W. If there is recorded info about window sizes
4646 before a call to grow_mini_window, restore recorded window sizes.
4647 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4648 line. */
4650 void
4651 shrink_mini_window (struct window *w)
4653 struct frame *f = XFRAME (w->frame);
4654 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4656 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4658 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4659 adjust_glyphs (f);
4660 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4661 windows_or_buffers_changed = 1;
4663 else if (XFASTINT (w->total_lines) > 1)
4665 /* Distribute the additional lines of the mini-window
4666 among the other windows. */
4667 Lisp_Object window;
4668 XSETWINDOW (window, w);
4669 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4675 /* Mark window cursors off for all windows in the window tree rooted
4676 at W by setting their phys_cursor_on_p flag to zero. Called from
4677 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4678 the frame are cleared. */
4680 void
4681 mark_window_cursors_off (struct window *w)
4683 while (w)
4685 if (!NILP (w->hchild))
4686 mark_window_cursors_off (XWINDOW (w->hchild));
4687 else if (!NILP (w->vchild))
4688 mark_window_cursors_off (XWINDOW (w->vchild));
4689 else
4690 w->phys_cursor_on_p = 0;
4692 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4697 /* Return number of lines of text (not counting mode lines) in W. */
4700 window_internal_height (struct window *w)
4702 int ht = XFASTINT (w->total_lines);
4704 if (!MINI_WINDOW_P (w))
4706 if (!NILP (w->parent)
4707 || !NILP (w->vchild)
4708 || !NILP (w->hchild)
4709 || !NILP (w->next)
4710 || !NILP (w->prev)
4711 || WINDOW_WANTS_MODELINE_P (w))
4712 --ht;
4714 if (WINDOW_WANTS_HEADER_LINE_P (w))
4715 --ht;
4718 return ht;
4722 /* Return the number of columns in W.
4723 Don't count columns occupied by scroll bars or the vertical bar
4724 separating W from the sibling to its right. */
4727 window_box_text_cols (struct window *w)
4729 struct frame *f = XFRAME (WINDOW_FRAME (w));
4730 int width = XINT (w->total_cols);
4732 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4733 /* Scroll bars occupy a few columns. */
4734 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4735 else if (!FRAME_WINDOW_P (f)
4736 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4737 /* The column of `|' characters separating side-by-side windows
4738 occupies one column only. */
4739 width -= 1;
4741 if (FRAME_WINDOW_P (f))
4742 /* On window-systems, fringes and display margins cannot be
4743 used for normal text. */
4744 width -= (WINDOW_FRINGE_COLS (w)
4745 + WINDOW_LEFT_MARGIN_COLS (w)
4746 + WINDOW_RIGHT_MARGIN_COLS (w));
4748 return width;
4752 /************************************************************************
4753 Window Scrolling
4754 ***********************************************************************/
4756 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4757 N screen-fulls, which is defined as the height of the window minus
4758 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4759 instead. Negative values of N mean scroll down. NOERROR non-zero
4760 means don't signal an error if we try to move over BEGV or ZV,
4761 respectively. */
4763 static void
4764 window_scroll (Lisp_Object window, int n, int whole, int noerror)
4766 immediate_quit = 1;
4768 /* If we must, use the pixel-based version which is much slower than
4769 the line-based one but can handle varying line heights. */
4770 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4771 window_scroll_pixel_based (window, n, whole, noerror);
4772 else
4773 window_scroll_line_based (window, n, whole, noerror);
4775 immediate_quit = 0;
4779 /* Implementation of window_scroll that works based on pixel line
4780 heights. See the comment of window_scroll for parameter
4781 descriptions. */
4783 static void
4784 window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4786 struct it it;
4787 struct window *w = XWINDOW (window);
4788 struct text_pos start;
4789 int this_scroll_margin;
4790 /* True if we fiddled the window vscroll field without really scrolling. */
4791 int vscrolled = 0;
4792 int x, y, rtop, rbot, rowh, vpos;
4794 SET_TEXT_POS_FROM_MARKER (start, w->start);
4796 /* If PT is not visible in WINDOW, move back one half of
4797 the screen. Allow PT to be partially visible, otherwise
4798 something like (scroll-down 1) with PT in the line before
4799 the partially visible one would recenter. */
4801 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4803 /* Move backward half the height of the window. Performance note:
4804 vmotion used here is about 10% faster, but would give wrong
4805 results for variable height lines. */
4806 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4807 it.current_y = it.last_visible_y;
4808 move_it_vertically_backward (&it, window_box_height (w) / 2);
4810 /* The function move_iterator_vertically may move over more than
4811 the specified y-distance. If it->w is small, e.g. a
4812 mini-buffer window, we may end up in front of the window's
4813 display area. This is the case when Start displaying at the
4814 start of the line containing PT in this case. */
4815 if (it.current_y <= 0)
4817 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4818 move_it_vertically_backward (&it, 0);
4819 it.current_y = 0;
4822 start = it.current.pos;
4824 else if (auto_window_vscroll_p)
4826 if (rtop || rbot) /* partially visible */
4828 int px;
4829 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4830 if (whole)
4831 dy = max ((window_box_height (w)
4832 - next_screen_context_lines * dy),
4833 dy);
4834 dy *= n;
4836 if (n < 0)
4838 /* Only vscroll backwards if already vscrolled forwards. */
4839 if (w->vscroll < 0 && rtop > 0)
4841 px = max (0, -w->vscroll - min (rtop, -dy));
4842 Fset_window_vscroll (window, make_number (px), Qt);
4843 return;
4846 if (n > 0)
4848 /* Do vscroll if already vscrolled or only display line. */
4849 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4851 px = max (0, -w->vscroll + min (rbot, dy));
4852 Fset_window_vscroll (window, make_number (px), Qt);
4853 return;
4856 /* Maybe modify window start instead of scrolling. */
4857 if (rbot > 0 || w->vscroll < 0)
4859 int spos;
4861 Fset_window_vscroll (window, make_number (0), Qt);
4862 /* If there are other text lines above the current row,
4863 move window start to current row. Else to next row. */
4864 if (rbot > 0)
4865 spos = XINT (Fline_beginning_position (Qnil));
4866 else
4867 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4868 set_marker_restricted (w->start, make_number (spos),
4869 w->buffer);
4870 w->start_at_line_beg = Qt;
4871 w->update_mode_line = Qt;
4872 XSETFASTINT (w->last_modified, 0);
4873 XSETFASTINT (w->last_overlay_modified, 0);
4874 /* Set force_start so that redisplay_window will run the
4875 window-scroll-functions. */
4876 w->force_start = Qt;
4877 return;
4881 /* Cancel previous vscroll. */
4882 Fset_window_vscroll (window, make_number (0), Qt);
4885 /* If scroll_preserve_screen_position is non-nil, we try to set
4886 point in the same window line as it is now, so get that line. */
4887 if (!NILP (Vscroll_preserve_screen_position))
4889 /* We preserve the goal pixel coordinate across consecutive
4890 calls to scroll-up, scroll-down and other commands that
4891 have the `scroll-command' property. This avoids the
4892 possibility of point becoming "stuck" on a tall line when
4893 scrolling by one line. */
4894 if (window_scroll_pixel_based_preserve_y < 0
4895 || !SYMBOLP (current_kboard->Vlast_command)
4896 || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
4898 start_display (&it, w, start);
4899 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4900 window_scroll_pixel_based_preserve_y = it.current_y;
4901 window_scroll_pixel_based_preserve_x = it.current_x;
4904 else
4905 window_scroll_pixel_based_preserve_y
4906 = window_scroll_pixel_based_preserve_x = -1;
4908 /* Move iterator it from start the specified distance forward or
4909 backward. The result is the new window start. */
4910 start_display (&it, w, start);
4911 if (whole)
4913 int start_pos = IT_CHARPOS (it);
4914 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4915 dy = max ((window_box_height (w)
4916 - next_screen_context_lines * dy),
4917 dy) * n;
4919 /* Note that move_it_vertically always moves the iterator to the
4920 start of a line. So, if the last line doesn't have a newline,
4921 we would end up at the start of the line ending at ZV. */
4922 if (dy <= 0)
4924 move_it_vertically_backward (&it, -dy);
4925 /* Ensure we actually do move, e.g. in case we are currently
4926 looking at an image that is taller that the window height. */
4927 while (start_pos == IT_CHARPOS (it)
4928 && start_pos > BEGV)
4929 move_it_by_lines (&it, -1, 1);
4931 else if (dy > 0)
4933 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4934 MOVE_TO_POS | MOVE_TO_Y);
4935 /* Ensure we actually do move, e.g. in case we are currently
4936 looking at an image that is taller that the window height. */
4937 while (start_pos == IT_CHARPOS (it)
4938 && start_pos < ZV)
4939 move_it_by_lines (&it, 1, 1);
4942 else
4943 move_it_by_lines (&it, n, 1);
4945 /* We failed if we find ZV is already on the screen (scrolling up,
4946 means there's nothing past the end), or if we can't start any
4947 earlier (scrolling down, means there's nothing past the top). */
4948 if ((n > 0 && IT_CHARPOS (it) == ZV)
4949 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4951 if (IT_CHARPOS (it) == ZV)
4953 if (it.current_y < it.last_visible_y
4954 && (it.current_y + it.max_ascent + it.max_descent
4955 > it.last_visible_y))
4957 /* The last line was only partially visible, make it fully
4958 visible. */
4959 w->vscroll = (it.last_visible_y
4960 - it.current_y + it.max_ascent + it.max_descent);
4961 adjust_glyphs (it.f);
4963 else if (noerror)
4964 return;
4965 else if (n < 0) /* could happen with empty buffers */
4966 xsignal0 (Qbeginning_of_buffer);
4967 else
4968 xsignal0 (Qend_of_buffer);
4970 else
4972 if (w->vscroll != 0)
4973 /* The first line was only partially visible, make it fully
4974 visible. */
4975 w->vscroll = 0;
4976 else if (noerror)
4977 return;
4978 else
4979 xsignal0 (Qbeginning_of_buffer);
4982 /* If control gets here, then we vscrolled. */
4984 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4986 /* Don't try to change the window start below. */
4987 vscrolled = 1;
4990 if (! vscrolled)
4992 int pos = IT_CHARPOS (it);
4993 int bytepos;
4995 /* If in the middle of a multi-glyph character move forward to
4996 the next character. */
4997 if (in_display_vector_p (&it))
4999 ++pos;
5000 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5003 /* Set the window start, and set up the window for redisplay. */
5004 set_marker_restricted (w->start, make_number (pos),
5005 w->buffer);
5006 bytepos = XMARKER (w->start)->bytepos;
5007 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5008 ? Qt : Qnil);
5009 w->update_mode_line = Qt;
5010 XSETFASTINT (w->last_modified, 0);
5011 XSETFASTINT (w->last_overlay_modified, 0);
5012 /* Set force_start so that redisplay_window will run the
5013 window-scroll-functions. */
5014 w->force_start = Qt;
5017 /* The rest of this function uses current_y in a nonstandard way,
5018 not including the height of the header line if any. */
5019 it.current_y = it.vpos = 0;
5021 /* Move PT out of scroll margins.
5022 This code wants current_y to be zero at the window start position
5023 even if there is a header line. */
5024 this_scroll_margin = max (0, scroll_margin);
5025 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5026 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5028 if (n > 0)
5030 /* We moved the window start towards ZV, so PT may be now
5031 in the scroll margin at the top. */
5032 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5033 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5034 && (NILP (Vscroll_preserve_screen_position)
5035 || EQ (Vscroll_preserve_screen_position, Qt)))
5036 /* We found PT at a legitimate height. Leave it alone. */
5038 else if (window_scroll_pixel_based_preserve_y >= 0)
5040 /* If we have a header line, take account of it.
5041 This is necessary because we set it.current_y to 0, above. */
5042 move_it_to (&it, -1,
5043 window_scroll_pixel_based_preserve_x,
5044 window_scroll_pixel_based_preserve_y
5045 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5046 -1, MOVE_TO_Y | MOVE_TO_X);
5047 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5049 else
5051 while (it.current_y < this_scroll_margin)
5053 int prev = it.current_y;
5054 move_it_by_lines (&it, 1, 1);
5055 if (prev == it.current_y)
5056 break;
5058 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5061 else if (n < 0)
5063 int charpos, bytepos;
5064 int partial_p;
5066 /* Save our position, for the
5067 window_scroll_pixel_based_preserve_y case. */
5068 charpos = IT_CHARPOS (it);
5069 bytepos = IT_BYTEPOS (it);
5071 /* We moved the window start towards BEGV, so PT may be now
5072 in the scroll margin at the bottom. */
5073 move_it_to (&it, PT, -1,
5074 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5075 - this_scroll_margin - 1),
5077 MOVE_TO_POS | MOVE_TO_Y);
5079 /* Save our position, in case it's correct. */
5080 charpos = IT_CHARPOS (it);
5081 bytepos = IT_BYTEPOS (it);
5083 /* See if point is on a partially visible line at the end. */
5084 if (it.what == IT_EOB)
5085 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5086 else
5088 move_it_by_lines (&it, 1, 1);
5089 partial_p = it.current_y > it.last_visible_y;
5092 if (charpos == PT && !partial_p
5093 && (NILP (Vscroll_preserve_screen_position)
5094 || EQ (Vscroll_preserve_screen_position, Qt)))
5095 /* We found PT before we found the display margin, so PT is ok. */
5097 else if (window_scroll_pixel_based_preserve_y >= 0)
5099 SET_TEXT_POS_FROM_MARKER (start, w->start);
5100 start_display (&it, w, start);
5101 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5102 here because we called start_display again and did not
5103 alter it.current_y this time. */
5104 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5105 window_scroll_pixel_based_preserve_y, -1,
5106 MOVE_TO_Y | MOVE_TO_X);
5107 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5109 else
5111 if (partial_p)
5112 /* The last line was only partially visible, so back up two
5113 lines to make sure we're on a fully visible line. */
5115 move_it_by_lines (&it, -2, 0);
5116 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5118 else
5119 /* No, the position we saved is OK, so use it. */
5120 SET_PT_BOTH (charpos, bytepos);
5126 /* Implementation of window_scroll that works based on screen lines.
5127 See the comment of window_scroll for parameter descriptions. */
5129 static void
5130 window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
5132 register struct window *w = XWINDOW (window);
5133 register int opoint = PT, opoint_byte = PT_BYTE;
5134 register int pos, pos_byte;
5135 register int ht = window_internal_height (w);
5136 register Lisp_Object tem;
5137 int lose;
5138 Lisp_Object bolp;
5139 int startpos;
5140 Lisp_Object original_pos = Qnil;
5142 /* If scrolling screen-fulls, compute the number of lines to
5143 scroll from the window's height. */
5144 if (whole)
5145 n *= max (1, ht - next_screen_context_lines);
5147 startpos = marker_position (w->start);
5149 if (!NILP (Vscroll_preserve_screen_position))
5151 if (window_scroll_preserve_vpos <= 0
5152 || !SYMBOLP (current_kboard->Vlast_command)
5153 || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
5155 struct position posit
5156 = *compute_motion (startpos, 0, 0, 0,
5157 PT, ht, 0,
5158 -1, XINT (w->hscroll),
5159 0, w);
5160 window_scroll_preserve_vpos = posit.vpos;
5161 window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
5164 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5165 make_number (window_scroll_preserve_vpos));
5168 XSETFASTINT (tem, PT);
5169 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5171 if (NILP (tem))
5173 Fvertical_motion (make_number (- (ht / 2)), window);
5174 startpos = PT;
5177 SET_PT (startpos);
5178 lose = n < 0 && PT == BEGV;
5179 Fvertical_motion (make_number (n), window);
5180 pos = PT;
5181 pos_byte = PT_BYTE;
5182 bolp = Fbolp ();
5183 SET_PT_BOTH (opoint, opoint_byte);
5185 if (lose)
5187 if (noerror)
5188 return;
5189 else
5190 xsignal0 (Qbeginning_of_buffer);
5193 if (pos < ZV)
5195 int this_scroll_margin = scroll_margin;
5197 /* Don't use a scroll margin that is negative or too large. */
5198 if (this_scroll_margin < 0)
5199 this_scroll_margin = 0;
5201 if (XINT (w->total_lines) < 4 * scroll_margin)
5202 this_scroll_margin = XINT (w->total_lines) / 4;
5204 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5205 w->start_at_line_beg = bolp;
5206 w->update_mode_line = Qt;
5207 XSETFASTINT (w->last_modified, 0);
5208 XSETFASTINT (w->last_overlay_modified, 0);
5209 /* Set force_start so that redisplay_window will run
5210 the window-scroll-functions. */
5211 w->force_start = Qt;
5213 if (!NILP (Vscroll_preserve_screen_position)
5214 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5216 SET_PT_BOTH (pos, pos_byte);
5217 Fvertical_motion (original_pos, window);
5219 /* If we scrolled forward, put point enough lines down
5220 that it is outside the scroll margin. */
5221 else if (n > 0)
5223 int top_margin;
5225 if (this_scroll_margin > 0)
5227 SET_PT_BOTH (pos, pos_byte);
5228 Fvertical_motion (make_number (this_scroll_margin), window);
5229 top_margin = PT;
5231 else
5232 top_margin = pos;
5234 if (top_margin <= opoint)
5235 SET_PT_BOTH (opoint, opoint_byte);
5236 else if (!NILP (Vscroll_preserve_screen_position))
5238 SET_PT_BOTH (pos, pos_byte);
5239 Fvertical_motion (original_pos, window);
5241 else
5242 SET_PT (top_margin);
5244 else if (n < 0)
5246 int bottom_margin;
5248 /* If we scrolled backward, put point near the end of the window
5249 but not within the scroll margin. */
5250 SET_PT_BOTH (pos, pos_byte);
5251 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5252 if (XFASTINT (tem) == ht - this_scroll_margin)
5253 bottom_margin = PT;
5254 else
5255 bottom_margin = PT + 1;
5257 if (bottom_margin > opoint)
5258 SET_PT_BOTH (opoint, opoint_byte);
5259 else
5261 if (!NILP (Vscroll_preserve_screen_position))
5263 SET_PT_BOTH (pos, pos_byte);
5264 Fvertical_motion (original_pos, window);
5266 else
5267 Fvertical_motion (make_number (-1), window);
5271 else
5273 if (noerror)
5274 return;
5275 else
5276 xsignal0 (Qend_of_buffer);
5281 /* Scroll selected_window up or down. If N is nil, scroll a
5282 screen-full which is defined as the height of the window minus
5283 next_screen_context_lines. If N is the symbol `-', scroll.
5284 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5285 up. This is the guts of Fscroll_up and Fscroll_down. */
5287 static void
5288 scroll_command (Lisp_Object n, int direction)
5290 int count = SPECPDL_INDEX ();
5292 xassert (eabs (direction) == 1);
5294 /* If selected window's buffer isn't current, make it current for
5295 the moment. But don't screw up if window_scroll gets an error. */
5296 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5298 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5299 Fset_buffer (XWINDOW (selected_window)->buffer);
5301 /* Make redisplay consider other windows than just selected_window. */
5302 ++windows_or_buffers_changed;
5305 if (NILP (n))
5306 window_scroll (selected_window, direction, 1, 0);
5307 else if (EQ (n, Qminus))
5308 window_scroll (selected_window, -direction, 1, 0);
5309 else
5311 n = Fprefix_numeric_value (n);
5312 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5315 unbind_to (count, Qnil);
5318 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5319 doc: /* Scroll text of selected window upward ARG lines.
5320 If ARG is omitted or nil, scroll upward by a near full screen.
5321 A near full screen is `next-screen-context-lines' less than a full screen.
5322 Negative ARG means scroll downward.
5323 If ARG is the atom `-', scroll downward by nearly full screen.
5324 When calling from a program, supply as argument a number, nil, or `-'. */)
5325 (Lisp_Object arg)
5327 scroll_command (arg, 1);
5328 return Qnil;
5331 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5332 doc: /* Scroll text of selected window down ARG lines.
5333 If ARG is omitted or nil, scroll down by a near full screen.
5334 A near full screen is `next-screen-context-lines' less than a full screen.
5335 Negative ARG means scroll upward.
5336 If ARG is the atom `-', scroll upward by nearly full screen.
5337 When calling from a program, supply as argument a number, nil, or `-'. */)
5338 (Lisp_Object arg)
5340 scroll_command (arg, -1);
5341 return Qnil;
5344 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5345 doc: /* Return the other window for \"other window scroll\" commands.
5346 If `other-window-scroll-buffer' is non-nil, a window
5347 showing that buffer is used.
5348 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5349 specifies the window. This takes precedence over
5350 `other-window-scroll-buffer'. */)
5351 (void)
5353 Lisp_Object window;
5355 if (MINI_WINDOW_P (XWINDOW (selected_window))
5356 && !NILP (Vminibuf_scroll_window))
5357 window = Vminibuf_scroll_window;
5358 /* If buffer is specified, scroll that buffer. */
5359 else if (!NILP (Vother_window_scroll_buffer))
5361 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5362 if (NILP (window))
5363 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5365 else
5367 /* Nothing specified; look for a neighboring window on the same
5368 frame. */
5369 window = Fnext_window (selected_window, Qnil, Qnil);
5371 if (EQ (window, selected_window))
5372 /* That didn't get us anywhere; look for a window on another
5373 visible frame. */
5375 window = Fnext_window (window, Qnil, Qt);
5376 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5377 && ! EQ (window, selected_window));
5380 CHECK_LIVE_WINDOW (window);
5382 if (EQ (window, selected_window))
5383 error ("There is no other window");
5385 return window;
5388 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5389 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5390 A near full screen is `next-screen-context-lines' less than a full screen.
5391 The next window is the one below the current one; or the one at the top
5392 if the current one is at the bottom. Negative ARG means scroll downward.
5393 If ARG is the atom `-', scroll downward by nearly full screen.
5394 When calling from a program, supply as argument a number, nil, or `-'.
5396 If `other-window-scroll-buffer' is non-nil, scroll the window
5397 showing that buffer, popping the buffer up if necessary.
5398 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5399 specifies the window to scroll. This takes precedence over
5400 `other-window-scroll-buffer'. */)
5401 (Lisp_Object arg)
5403 Lisp_Object window;
5404 struct window *w;
5405 int count = SPECPDL_INDEX ();
5407 window = Fother_window_for_scrolling ();
5408 w = XWINDOW (window);
5410 /* Don't screw up if window_scroll gets an error. */
5411 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5412 ++windows_or_buffers_changed;
5414 Fset_buffer (w->buffer);
5415 SET_PT (marker_position (w->pointm));
5417 if (NILP (arg))
5418 window_scroll (window, 1, 1, 1);
5419 else if (EQ (arg, Qminus))
5420 window_scroll (window, -1, 1, 1);
5421 else
5423 if (CONSP (arg))
5424 arg = Fcar (arg);
5425 CHECK_NUMBER (arg);
5426 window_scroll (window, XINT (arg), 0, 1);
5429 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5430 unbind_to (count, Qnil);
5432 return Qnil;
5435 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5436 doc: /* Scroll selected window display ARG columns left.
5437 Default for ARG is window width minus 2.
5438 Value is the total amount of leftward horizontal scrolling in
5439 effect after the change.
5440 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5441 lower bound for automatic scrolling, i.e. automatic scrolling
5442 will not scroll a window to a column less than the value returned
5443 by this function. This happens in an interactive call. */)
5444 (register Lisp_Object arg, Lisp_Object set_minimum)
5446 Lisp_Object result;
5447 int hscroll;
5448 struct window *w = XWINDOW (selected_window);
5450 if (NILP (arg))
5451 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5452 else
5453 arg = Fprefix_numeric_value (arg);
5455 hscroll = XINT (w->hscroll) + XINT (arg);
5456 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5458 if (!NILP (set_minimum))
5459 w->min_hscroll = w->hscroll;
5461 return result;
5464 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5465 doc: /* Scroll selected window display ARG columns right.
5466 Default for ARG is window width minus 2.
5467 Value is the total amount of leftward horizontal scrolling in
5468 effect after the change.
5469 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5470 lower bound for automatic scrolling, i.e. automatic scrolling
5471 will not scroll a window to a column less than the value returned
5472 by this function. This happens in an interactive call. */)
5473 (register Lisp_Object arg, Lisp_Object set_minimum)
5475 Lisp_Object result;
5476 int hscroll;
5477 struct window *w = XWINDOW (selected_window);
5479 if (NILP (arg))
5480 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5481 else
5482 arg = Fprefix_numeric_value (arg);
5484 hscroll = XINT (w->hscroll) - XINT (arg);
5485 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5487 if (!NILP (set_minimum))
5488 w->min_hscroll = w->hscroll;
5490 return result;
5493 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5494 doc: /* Return the window which was selected when entering the minibuffer.
5495 Returns nil, if selected window is not a minibuffer window. */)
5496 (void)
5498 if (minibuf_level > 0
5499 && MINI_WINDOW_P (XWINDOW (selected_window))
5500 && WINDOW_LIVE_P (minibuf_selected_window))
5501 return minibuf_selected_window;
5503 return Qnil;
5506 /* Value is the number of lines actually displayed in window W,
5507 as opposed to its height. */
5509 static int
5510 displayed_window_lines (struct window *w)
5512 struct it it;
5513 struct text_pos start;
5514 int height = window_box_height (w);
5515 struct buffer *old_buffer;
5516 int bottom_y;
5518 if (XBUFFER (w->buffer) != current_buffer)
5520 old_buffer = current_buffer;
5521 set_buffer_internal (XBUFFER (w->buffer));
5523 else
5524 old_buffer = NULL;
5526 /* In case W->start is out of the accessible range, do something
5527 reasonable. This happens in Info mode when Info-scroll-down
5528 calls (recenter -1) while W->start is 1. */
5529 if (XMARKER (w->start)->charpos < BEGV)
5530 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5531 else if (XMARKER (w->start)->charpos > ZV)
5532 SET_TEXT_POS (start, ZV, ZV_BYTE);
5533 else
5534 SET_TEXT_POS_FROM_MARKER (start, w->start);
5536 start_display (&it, w, start);
5537 move_it_vertically (&it, height);
5538 bottom_y = line_bottom_y (&it);
5540 /* rms: On a non-window display,
5541 the value of it.vpos at the bottom of the screen
5542 seems to be 1 larger than window_box_height (w).
5543 This kludge fixes a bug whereby (move-to-window-line -1)
5544 when ZV is on the last screen line
5545 moves to the previous screen line instead of the last one. */
5546 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5547 height++;
5549 /* Add in empty lines at the bottom of the window. */
5550 if (bottom_y < height)
5552 int uy = FRAME_LINE_HEIGHT (it.f);
5553 it.vpos += (height - bottom_y + uy - 1) / uy;
5556 if (old_buffer)
5557 set_buffer_internal (old_buffer);
5559 return it.vpos;
5563 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5564 doc: /* Center point in selected window and maybe redisplay frame.
5565 With prefix argument ARG, recenter putting point on screen line ARG
5566 relative to the selected window. If ARG is negative, it counts up from the
5567 bottom of the window. (ARG should be less than the height of the window.)
5569 If ARG is omitted or nil, then recenter with point on the middle line of
5570 the selected window; if the variable `recenter-redisplay' is non-nil,
5571 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5572 is set to `grow-only', this resets the tool-bar's height to the minimum
5573 height needed); if `recenter-redisplay' has the special value `tty',
5574 then only tty frame are redrawn.
5576 Just C-u as prefix means put point in the center of the window
5577 and redisplay normally--don't erase and redraw the frame. */)
5578 (register Lisp_Object arg)
5580 struct window *w = XWINDOW (selected_window);
5581 struct buffer *buf = XBUFFER (w->buffer);
5582 struct buffer *obuf = current_buffer;
5583 int center_p = 0;
5584 int charpos, bytepos;
5585 int iarg;
5586 int this_scroll_margin;
5588 /* If redisplay is suppressed due to an error, try again. */
5589 obuf->display_error_modiff = 0;
5591 if (NILP (arg))
5593 if (!NILP (Vrecenter_redisplay)
5594 && (!EQ (Vrecenter_redisplay, Qtty)
5595 || !NILP (Ftty_type (selected_frame))))
5597 int i;
5599 /* Invalidate pixel data calculated for all compositions. */
5600 for (i = 0; i < n_compositions; i++)
5601 composition_table[i]->font = NULL;
5603 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5605 Fredraw_frame (WINDOW_FRAME (w));
5606 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5609 center_p = 1;
5611 else if (CONSP (arg)) /* Just C-u. */
5612 center_p = 1;
5613 else
5615 arg = Fprefix_numeric_value (arg);
5616 CHECK_NUMBER (arg);
5617 iarg = XINT (arg);
5620 set_buffer_internal (buf);
5622 /* Do this after making BUF current
5623 in case scroll_margin is buffer-local. */
5624 this_scroll_margin = max (0, scroll_margin);
5625 this_scroll_margin = min (this_scroll_margin,
5626 XFASTINT (w->total_lines) / 4);
5628 /* Handle centering on a graphical frame specially. Such frames can
5629 have variable-height lines and centering point on the basis of
5630 line counts would lead to strange effects. */
5631 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5633 if (center_p)
5635 struct it it;
5636 struct text_pos pt;
5638 SET_TEXT_POS (pt, PT, PT_BYTE);
5639 start_display (&it, w, pt);
5640 move_it_vertically_backward (&it, window_box_height (w) / 2);
5641 charpos = IT_CHARPOS (it);
5642 bytepos = IT_BYTEPOS (it);
5644 else if (iarg < 0)
5646 struct it it;
5647 struct text_pos pt;
5648 int nlines = -iarg;
5649 int extra_line_spacing;
5650 int h = window_box_height (w);
5652 iarg = - max (-iarg, this_scroll_margin);
5654 SET_TEXT_POS (pt, PT, PT_BYTE);
5655 start_display (&it, w, pt);
5657 /* Be sure we have the exact height of the full line containing PT. */
5658 move_it_by_lines (&it, 0, 1);
5660 /* The amount of pixels we have to move back is the window
5661 height minus what's displayed in the line containing PT,
5662 and the lines below. */
5663 it.current_y = 0;
5664 it.vpos = 0;
5665 move_it_by_lines (&it, nlines, 1);
5667 if (it.vpos == nlines)
5668 h -= it.current_y;
5669 else
5671 /* Last line has no newline */
5672 h -= line_bottom_y (&it);
5673 it.vpos++;
5676 /* Don't reserve space for extra line spacing of last line. */
5677 extra_line_spacing = it.max_extra_line_spacing;
5679 /* If we can't move down NLINES lines because we hit
5680 the end of the buffer, count in some empty lines. */
5681 if (it.vpos < nlines)
5683 nlines -= it.vpos;
5684 extra_line_spacing = it.extra_line_spacing;
5685 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5687 if (h <= 0)
5688 return Qnil;
5690 /* Now find the new top line (starting position) of the window. */
5691 start_display (&it, w, pt);
5692 it.current_y = 0;
5693 move_it_vertically_backward (&it, h);
5695 /* If extra line spacing is present, we may move too far
5696 back. This causes the last line to be only partially
5697 visible (which triggers redisplay to recenter that line
5698 in the middle), so move forward.
5699 But ignore extra line spacing on last line, as it is not
5700 considered to be part of the visible height of the line.
5702 h += extra_line_spacing;
5703 while (-it.current_y > h)
5704 move_it_by_lines (&it, 1, 1);
5706 charpos = IT_CHARPOS (it);
5707 bytepos = IT_BYTEPOS (it);
5709 else
5711 struct position pos;
5713 iarg = max (iarg, this_scroll_margin);
5715 pos = *vmotion (PT, -iarg, w);
5716 charpos = pos.bufpos;
5717 bytepos = pos.bytepos;
5720 else
5722 struct position pos;
5723 int ht = window_internal_height (w);
5725 if (center_p)
5726 iarg = ht / 2;
5727 else if (iarg < 0)
5728 iarg += ht;
5730 /* Don't let it get into the margin at either top or bottom. */
5731 iarg = max (iarg, this_scroll_margin);
5732 iarg = min (iarg, ht - this_scroll_margin - 1);
5734 pos = *vmotion (PT, - iarg, w);
5735 charpos = pos.bufpos;
5736 bytepos = pos.bytepos;
5739 /* Set the new window start. */
5740 set_marker_both (w->start, w->buffer, charpos, bytepos);
5741 w->window_end_valid = Qnil;
5743 w->optional_new_start = Qt;
5745 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5746 w->start_at_line_beg = Qt;
5747 else
5748 w->start_at_line_beg = Qnil;
5750 set_buffer_internal (obuf);
5751 return Qnil;
5755 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5756 0, 1, 0,
5757 doc: /* Return the height in lines of the text display area of WINDOW.
5758 WINDOW defaults to the selected window.
5760 The return value does not include the mode line, any header line, nor
5761 any partial-height lines in the text display area. */)
5762 (Lisp_Object window)
5764 struct window *w = decode_window (window);
5765 int pixel_height = window_box_height (w);
5766 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5767 return make_number (line_height);
5772 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5773 1, 1, "P",
5774 doc: /* Position point relative to window.
5775 With no argument, position point at center of window.
5776 An argument specifies vertical position within the window;
5777 zero means top of window, negative means relative to bottom of window. */)
5778 (Lisp_Object arg)
5780 struct window *w = XWINDOW (selected_window);
5781 int lines, start;
5782 Lisp_Object window;
5783 #if 0
5784 int this_scroll_margin;
5785 #endif
5787 window = selected_window;
5788 start = marker_position (w->start);
5789 if (start < BEGV || start > ZV)
5791 int height = window_internal_height (w);
5792 Fvertical_motion (make_number (- (height / 2)), window);
5793 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5794 w->start_at_line_beg = Fbolp ();
5795 w->force_start = Qt;
5797 else
5798 Fgoto_char (w->start);
5800 lines = displayed_window_lines (w);
5802 #if 0
5803 this_scroll_margin = max (0, scroll_margin);
5804 this_scroll_margin = min (this_scroll_margin, lines / 4);
5805 #endif
5807 if (NILP (arg))
5808 XSETFASTINT (arg, lines / 2);
5809 else
5811 int iarg = XINT (Fprefix_numeric_value (arg));
5813 if (iarg < 0)
5814 iarg = iarg + lines;
5816 #if 0 /* This code would prevent move-to-window-line from moving point
5817 to a place inside the scroll margins (which would cause the
5818 next redisplay to scroll). I wrote this code, but then concluded
5819 it is probably better not to install it. However, it is here
5820 inside #if 0 so as not to lose it. -- rms. */
5822 /* Don't let it get into the margin at either top or bottom. */
5823 iarg = max (iarg, this_scroll_margin);
5824 iarg = min (iarg, lines - this_scroll_margin - 1);
5825 #endif
5827 arg = make_number (iarg);
5830 /* Skip past a partially visible first line. */
5831 if (w->vscroll)
5832 XSETINT (arg, XINT (arg) + 1);
5834 return Fvertical_motion (arg, window);
5839 /***********************************************************************
5840 Window Configuration
5841 ***********************************************************************/
5843 struct save_window_data
5845 EMACS_UINT size;
5846 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5847 Lisp_Object selected_frame;
5848 Lisp_Object current_window;
5849 Lisp_Object current_buffer;
5850 Lisp_Object minibuf_scroll_window;
5851 Lisp_Object minibuf_selected_window;
5852 Lisp_Object root_window;
5853 Lisp_Object focus_frame;
5854 /* A vector, each of whose elements is a struct saved_window
5855 for one window. */
5856 Lisp_Object saved_windows;
5858 /* All fields above are traced by the GC.
5859 From `fame-cols' down, the fields are ignored by the GC. */
5861 int frame_cols, frame_lines, frame_menu_bar_lines;
5862 int frame_tool_bar_lines;
5865 /* This is saved as a Lisp_Vector */
5866 struct saved_window
5868 /* these first two must agree with struct Lisp_Vector in lisp.h */
5869 EMACS_UINT size;
5870 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5872 Lisp_Object window;
5873 Lisp_Object buffer, start, pointm, mark;
5874 Lisp_Object left_col, top_line, total_cols, total_lines;
5875 Lisp_Object hscroll, min_hscroll;
5876 Lisp_Object parent, prev;
5877 Lisp_Object start_at_line_beg;
5878 Lisp_Object display_table;
5879 Lisp_Object orig_top_line, orig_total_lines;
5880 Lisp_Object left_margin_cols, right_margin_cols;
5881 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5882 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5883 Lisp_Object dedicated, resize_proportionally;
5886 #define SAVED_WINDOW_N(swv,n) \
5887 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5889 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5890 doc: /* Return t if OBJECT is a window-configuration object. */)
5891 (Lisp_Object object)
5893 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5896 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5897 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5898 (Lisp_Object config)
5900 register struct save_window_data *data;
5901 struct Lisp_Vector *saved_windows;
5903 CHECK_WINDOW_CONFIGURATION (config);
5905 data = (struct save_window_data *) XVECTOR (config);
5906 saved_windows = XVECTOR (data->saved_windows);
5907 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5910 DEFUN ("set-window-configuration", Fset_window_configuration,
5911 Sset_window_configuration, 1, 1, 0,
5912 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5913 CONFIGURATION must be a value previously returned
5914 by `current-window-configuration' (which see).
5915 If CONFIGURATION was made from a frame that is now deleted,
5916 only frame-independent values can be restored. In this case,
5917 the return value is nil. Otherwise the value is t. */)
5918 (Lisp_Object configuration)
5920 register struct save_window_data *data;
5921 struct Lisp_Vector *saved_windows;
5922 Lisp_Object new_current_buffer;
5923 Lisp_Object frame;
5924 FRAME_PTR f;
5925 int old_point = -1;
5927 CHECK_WINDOW_CONFIGURATION (configuration);
5929 data = (struct save_window_data *) XVECTOR (configuration);
5930 saved_windows = XVECTOR (data->saved_windows);
5932 new_current_buffer = data->current_buffer;
5933 if (NILP (XBUFFER (new_current_buffer)->name))
5934 new_current_buffer = Qnil;
5935 else
5937 if (XBUFFER (new_current_buffer) == current_buffer)
5938 /* The code further down "preserves point" by saving here PT in
5939 old_point and then setting it later back into PT. When the
5940 current-selected-window and the final-selected-window both show
5941 the current buffer, this suffers from the problem that the
5942 current PT is the window-point of the current-selected-window,
5943 while the final PT is the point of the final-selected-window, so
5944 this copy from one PT to the other would end up moving the
5945 window-point of the final-selected-window to the window-point of
5946 the current-selected-window. So we have to be careful which
5947 point of the current-buffer we copy into old_point. */
5948 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5949 && WINDOWP (selected_window)
5950 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5951 && !EQ (selected_window, data->current_window))
5952 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5953 else
5954 old_point = PT;
5955 else
5956 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5957 point in new_current_buffer as of the last time this buffer was
5958 used. This can be non-deterministic since it can be changed by
5959 things like jit-lock by mere temporary selection of some random
5960 window that happens to show this buffer.
5961 So if possible we want this arbitrary choice of "which point" to
5962 be the one from the to-be-selected-window so as to prevent this
5963 window's cursor from being copied from another window. */
5964 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5965 /* If current_window = selected_window, its point is in BUF_PT. */
5966 && !EQ (selected_window, data->current_window))
5967 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5968 else
5969 old_point = BUF_PT (XBUFFER (new_current_buffer));
5972 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5973 f = XFRAME (frame);
5975 /* If f is a dead frame, don't bother rebuilding its window tree.
5976 However, there is other stuff we should still try to do below. */
5977 if (FRAME_LIVE_P (f))
5979 register struct window *w;
5980 register struct saved_window *p;
5981 struct window *root_window;
5982 struct window **leaf_windows;
5983 int n_leaf_windows;
5984 int k, i, n;
5986 /* If the frame has been resized since this window configuration was
5987 made, we change the frame to the size specified in the
5988 configuration, restore the configuration, and then resize it
5989 back. We keep track of the prevailing height in these variables. */
5990 int previous_frame_lines = FRAME_LINES (f);
5991 int previous_frame_cols = FRAME_COLS (f);
5992 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5993 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5995 /* The mouse highlighting code could get screwed up
5996 if it runs during this. */
5997 BLOCK_INPUT;
5999 if (data->frame_lines != previous_frame_lines
6000 || data->frame_cols != previous_frame_cols)
6001 change_frame_size (f, data->frame_lines,
6002 data->frame_cols, 0, 0, 0);
6003 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6004 if (data->frame_menu_bar_lines
6005 != previous_frame_menu_bar_lines)
6006 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
6007 make_number (0));
6008 #ifdef HAVE_WINDOW_SYSTEM
6009 if (data->frame_tool_bar_lines
6010 != previous_frame_tool_bar_lines)
6011 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
6012 make_number (0));
6013 #endif
6014 #endif
6016 /* "Swap out" point from the selected window's buffer
6017 into the window itself. (Normally the pointm of the selected
6018 window holds garbage.) We do this now, before
6019 restoring the window contents, and prevent it from
6020 being done later on when we select a new window. */
6021 if (! NILP (XWINDOW (selected_window)->buffer))
6023 w = XWINDOW (selected_window);
6024 set_marker_both (w->pointm,
6025 w->buffer,
6026 BUF_PT (XBUFFER (w->buffer)),
6027 BUF_PT_BYTE (XBUFFER (w->buffer)));
6030 windows_or_buffers_changed++;
6031 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6033 /* Problem: Freeing all matrices and later allocating them again
6034 is a serious redisplay flickering problem. What we would
6035 really like to do is to free only those matrices not reused
6036 below. */
6037 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6038 leaf_windows
6039 = (struct window **) alloca (count_windows (root_window)
6040 * sizeof (struct window *));
6041 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6043 /* Kludge Alert!
6044 Mark all windows now on frame as "deleted".
6045 Restoring the new configuration "undeletes" any that are in it.
6047 Save their current buffers in their height fields, since we may
6048 need it later, if a buffer saved in the configuration is now
6049 dead. */
6050 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6052 for (k = 0; k < saved_windows->size; k++)
6054 p = SAVED_WINDOW_N (saved_windows, k);
6055 w = XWINDOW (p->window);
6056 w->next = Qnil;
6058 if (!NILP (p->parent))
6059 w->parent = SAVED_WINDOW_N (saved_windows,
6060 XFASTINT (p->parent))->window;
6061 else
6062 w->parent = Qnil;
6064 if (!NILP (p->prev))
6066 w->prev = SAVED_WINDOW_N (saved_windows,
6067 XFASTINT (p->prev))->window;
6068 XWINDOW (w->prev)->next = p->window;
6070 else
6072 w->prev = Qnil;
6073 if (!NILP (w->parent))
6075 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6077 XWINDOW (w->parent)->vchild = p->window;
6078 XWINDOW (w->parent)->hchild = Qnil;
6080 else
6082 XWINDOW (w->parent)->hchild = p->window;
6083 XWINDOW (w->parent)->vchild = Qnil;
6088 /* If we squirreled away the buffer in the window's height,
6089 restore it now. */
6090 if (BUFFERP (w->total_lines))
6091 w->buffer = w->total_lines;
6092 w->left_col = p->left_col;
6093 w->top_line = p->top_line;
6094 w->total_cols = p->total_cols;
6095 w->total_lines = p->total_lines;
6096 w->hscroll = p->hscroll;
6097 w->min_hscroll = p->min_hscroll;
6098 w->display_table = p->display_table;
6099 w->orig_top_line = p->orig_top_line;
6100 w->orig_total_lines = p->orig_total_lines;
6101 w->left_margin_cols = p->left_margin_cols;
6102 w->right_margin_cols = p->right_margin_cols;
6103 w->left_fringe_width = p->left_fringe_width;
6104 w->right_fringe_width = p->right_fringe_width;
6105 w->fringes_outside_margins = p->fringes_outside_margins;
6106 w->scroll_bar_width = p->scroll_bar_width;
6107 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6108 w->dedicated = p->dedicated;
6109 w->resize_proportionally = p->resize_proportionally;
6110 XSETFASTINT (w->last_modified, 0);
6111 XSETFASTINT (w->last_overlay_modified, 0);
6113 /* Reinstall the saved buffer and pointers into it. */
6114 if (NILP (p->buffer))
6115 w->buffer = p->buffer;
6116 else
6118 if (!NILP (XBUFFER (p->buffer)->name))
6119 /* If saved buffer is alive, install it. */
6121 w->buffer = p->buffer;
6122 w->start_at_line_beg = p->start_at_line_beg;
6123 set_marker_restricted (w->start, p->start, w->buffer);
6124 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6125 Fset_marker (XBUFFER (w->buffer)->mark,
6126 p->mark, w->buffer);
6128 /* As documented in Fcurrent_window_configuration, don't
6129 restore the location of point in the buffer which was
6130 current when the window configuration was recorded. */
6131 if (!EQ (p->buffer, new_current_buffer)
6132 && XBUFFER (p->buffer) == current_buffer)
6133 Fgoto_char (w->pointm);
6135 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6136 /* Else unless window has a live buffer, get one. */
6138 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6139 /* This will set the markers to beginning of visible
6140 range. */
6141 set_marker_restricted (w->start, make_number (0), w->buffer);
6142 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6143 w->start_at_line_beg = Qt;
6145 else
6146 /* Keeping window's old buffer; make sure the markers
6147 are real. */
6149 /* Set window markers at start of visible range. */
6150 if (XMARKER (w->start)->buffer == 0)
6151 set_marker_restricted (w->start, make_number (0),
6152 w->buffer);
6153 if (XMARKER (w->pointm)->buffer == 0)
6154 set_marker_restricted_both (w->pointm, w->buffer,
6155 BUF_PT (XBUFFER (w->buffer)),
6156 BUF_PT_BYTE (XBUFFER (w->buffer)));
6157 w->start_at_line_beg = Qt;
6162 FRAME_ROOT_WINDOW (f) = data->root_window;
6163 /* Prevent "swapping out point" in the old selected window
6164 using the buffer that has been restored into it.
6165 We already swapped out point that from that window's old buffer. */
6166 selected_window = Qnil;
6168 /* Arrange *not* to restore point in the buffer that was
6169 current when the window configuration was saved. */
6170 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6171 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6172 make_number (old_point),
6173 XWINDOW (data->current_window)->buffer);
6175 Fselect_window (data->current_window, Qnil);
6176 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6177 = selected_window;
6179 if (NILP (data->focus_frame)
6180 || (FRAMEP (data->focus_frame)
6181 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6182 Fredirect_frame_focus (frame, data->focus_frame);
6184 #if 0 /* I don't understand why this is needed, and it causes problems
6185 when the frame's old selected window has been deleted. */
6186 if (f != selected_frame && FRAME_WINDOW_P (f))
6187 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6188 0, 0, Qnil);
6189 #endif
6191 /* Set the screen height to the value it had before this function. */
6192 if (previous_frame_lines != FRAME_LINES (f)
6193 || previous_frame_cols != FRAME_COLS (f))
6194 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6195 0, 0, 0);
6196 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6197 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6198 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6199 make_number (0));
6200 #ifdef HAVE_WINDOW_SYSTEM
6201 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6202 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6203 make_number (0));
6204 #endif
6205 #endif
6207 /* Now, free glyph matrices in windows that were not reused. */
6208 for (i = n = 0; i < n_leaf_windows; ++i)
6210 if (NILP (leaf_windows[i]->buffer))
6212 /* Assert it's not reused as a combination. */
6213 xassert (NILP (leaf_windows[i]->hchild)
6214 && NILP (leaf_windows[i]->vchild));
6215 free_window_matrices (leaf_windows[i]);
6217 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6218 ++n;
6221 adjust_glyphs (f);
6223 UNBLOCK_INPUT;
6225 /* Fselect_window will have made f the selected frame, so we
6226 reselect the proper frame here. Fhandle_switch_frame will change the
6227 selected window too, but that doesn't make the call to
6228 Fselect_window above totally superfluous; it still sets f's
6229 selected window. */
6230 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6231 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6233 run_window_configuration_change_hook (f);
6236 if (!NILP (new_current_buffer))
6237 Fset_buffer (new_current_buffer);
6239 Vminibuf_scroll_window = data->minibuf_scroll_window;
6240 minibuf_selected_window = data->minibuf_selected_window;
6242 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6245 /* Mark all windows now on frame as deleted
6246 by setting their buffers to nil. */
6248 void
6249 delete_all_subwindows (register struct window *w)
6251 if (!NILP (w->next))
6252 delete_all_subwindows (XWINDOW (w->next));
6253 if (!NILP (w->vchild))
6254 delete_all_subwindows (XWINDOW (w->vchild));
6255 if (!NILP (w->hchild))
6256 delete_all_subwindows (XWINDOW (w->hchild));
6258 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6260 if (!NILP (w->buffer))
6261 unshow_buffer (w);
6263 /* We set all three of these fields to nil, to make sure that we can
6264 distinguish this dead window from any live window. Live leaf
6265 windows will have buffer set, and combination windows will have
6266 vchild or hchild set. */
6267 w->buffer = Qnil;
6268 w->vchild = Qnil;
6269 w->hchild = Qnil;
6271 Vwindow_list = Qnil;
6274 static int
6275 count_windows (register struct window *window)
6277 register int count = 1;
6278 if (!NILP (window->next))
6279 count += count_windows (XWINDOW (window->next));
6280 if (!NILP (window->vchild))
6281 count += count_windows (XWINDOW (window->vchild));
6282 if (!NILP (window->hchild))
6283 count += count_windows (XWINDOW (window->hchild));
6284 return count;
6288 /* Fill vector FLAT with leaf windows under W, starting at index I.
6289 Value is last index + 1. */
6291 static int
6292 get_leaf_windows (struct window *w, struct window **flat, int i)
6294 while (w)
6296 if (!NILP (w->hchild))
6297 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6298 else if (!NILP (w->vchild))
6299 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6300 else
6301 flat[i++] = w;
6303 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6306 return i;
6310 /* Return a pointer to the glyph W's physical cursor is on. Value is
6311 null if W's current matrix is invalid, so that no meaningfull glyph
6312 can be returned. */
6314 struct glyph *
6315 get_phys_cursor_glyph (struct window *w)
6317 struct glyph_row *row;
6318 struct glyph *glyph;
6320 if (w->phys_cursor.vpos >= 0
6321 && w->phys_cursor.vpos < w->current_matrix->nrows
6322 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6323 row->enabled_p)
6324 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6325 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6326 else
6327 glyph = NULL;
6329 return glyph;
6333 static int
6334 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
6336 register struct saved_window *p;
6337 register struct window *w;
6338 register Lisp_Object tem;
6340 for (;!NILP (window); window = w->next)
6342 p = SAVED_WINDOW_N (vector, i);
6343 w = XWINDOW (window);
6345 XSETFASTINT (w->temslot, i); i++;
6346 p->window = window;
6347 p->buffer = w->buffer;
6348 p->left_col = w->left_col;
6349 p->top_line = w->top_line;
6350 p->total_cols = w->total_cols;
6351 p->total_lines = w->total_lines;
6352 p->hscroll = w->hscroll;
6353 p->min_hscroll = w->min_hscroll;
6354 p->display_table = w->display_table;
6355 p->orig_top_line = w->orig_top_line;
6356 p->orig_total_lines = w->orig_total_lines;
6357 p->left_margin_cols = w->left_margin_cols;
6358 p->right_margin_cols = w->right_margin_cols;
6359 p->left_fringe_width = w->left_fringe_width;
6360 p->right_fringe_width = w->right_fringe_width;
6361 p->fringes_outside_margins = w->fringes_outside_margins;
6362 p->scroll_bar_width = w->scroll_bar_width;
6363 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6364 p->dedicated = w->dedicated;
6365 p->resize_proportionally = w->resize_proportionally;
6366 if (!NILP (w->buffer))
6368 /* Save w's value of point in the window configuration.
6369 If w is the selected window, then get the value of point
6370 from the buffer; pointm is garbage in the selected window. */
6371 if (EQ (window, selected_window))
6373 p->pointm = Fmake_marker ();
6374 set_marker_both (p->pointm, w->buffer,
6375 BUF_PT (XBUFFER (w->buffer)),
6376 BUF_PT_BYTE (XBUFFER (w->buffer)));
6378 else
6379 p->pointm = Fcopy_marker (w->pointm, Qnil);
6381 p->start = Fcopy_marker (w->start, Qnil);
6382 p->start_at_line_beg = w->start_at_line_beg;
6384 tem = XBUFFER (w->buffer)->mark;
6385 p->mark = Fcopy_marker (tem, Qnil);
6387 else
6389 p->pointm = Qnil;
6390 p->start = Qnil;
6391 p->mark = Qnil;
6392 p->start_at_line_beg = Qnil;
6395 if (NILP (w->parent))
6396 p->parent = Qnil;
6397 else
6398 p->parent = XWINDOW (w->parent)->temslot;
6400 if (NILP (w->prev))
6401 p->prev = Qnil;
6402 else
6403 p->prev = XWINDOW (w->prev)->temslot;
6405 if (!NILP (w->vchild))
6406 i = save_window_save (w->vchild, vector, i);
6407 if (!NILP (w->hchild))
6408 i = save_window_save (w->hchild, vector, i);
6411 return i;
6414 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6415 Scurrent_window_configuration, 0, 1, 0,
6416 doc: /* Return an object representing the current window configuration of FRAME.
6417 If FRAME is nil or omitted, use the selected frame.
6418 This describes the number of windows, their sizes and current buffers,
6419 and for each displayed buffer, where display starts, and the positions of
6420 point and mark. An exception is made for point in the current buffer:
6421 its value is -not- saved.
6422 This also records the currently selected frame, and FRAME's focus
6423 redirection (see `redirect-frame-focus'). */)
6424 (Lisp_Object frame)
6426 register Lisp_Object tem;
6427 register int n_windows;
6428 register struct save_window_data *data;
6429 register int i;
6430 FRAME_PTR f;
6432 if (NILP (frame))
6433 frame = selected_frame;
6434 CHECK_LIVE_FRAME (frame);
6435 f = XFRAME (frame);
6437 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6438 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6439 PVEC_WINDOW_CONFIGURATION);
6441 data->frame_cols = FRAME_COLS (f);
6442 data->frame_lines = FRAME_LINES (f);
6443 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6444 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6445 data->selected_frame = selected_frame;
6446 data->current_window = FRAME_SELECTED_WINDOW (f);
6447 XSETBUFFER (data->current_buffer, current_buffer);
6448 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6449 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6450 data->root_window = FRAME_ROOT_WINDOW (f);
6451 data->focus_frame = FRAME_FOCUS_FRAME (f);
6452 tem = Fmake_vector (make_number (n_windows), Qnil);
6453 data->saved_windows = tem;
6454 for (i = 0; i < n_windows; i++)
6455 XVECTOR (tem)->contents[i]
6456 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6457 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6458 XSETWINDOW_CONFIGURATION (tem, data);
6459 return (tem);
6462 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6463 0, UNEVALLED, 0,
6464 doc: /* Execute BODY, preserving window sizes and contents.
6465 Return the value of the last form in BODY.
6466 Restore which buffer appears in which window, where display starts,
6467 and the value of point and mark for each window.
6468 Also restore the choice of selected window.
6469 Also restore which buffer is current.
6470 Does not restore the value of point in current buffer.
6471 usage: (save-window-excursion BODY...) */)
6472 (Lisp_Object args)
6474 register Lisp_Object val;
6475 register int count = SPECPDL_INDEX ();
6477 record_unwind_protect (Fset_window_configuration,
6478 Fcurrent_window_configuration (Qnil));
6479 val = Fprogn (args);
6480 return unbind_to (count, val);
6485 /***********************************************************************
6486 Window Split Tree
6487 ***********************************************************************/
6489 static Lisp_Object
6490 window_tree (struct window *w)
6492 Lisp_Object tail = Qnil;
6493 Lisp_Object result = Qnil;
6495 while (w)
6497 Lisp_Object wn;
6499 XSETWINDOW (wn, w);
6500 if (!NILP (w->hchild))
6501 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6502 window_tree (XWINDOW (w->hchild))));
6503 else if (!NILP (w->vchild))
6504 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6505 window_tree (XWINDOW (w->vchild))));
6507 if (NILP (result))
6509 result = tail = Fcons (wn, Qnil);
6511 else
6513 XSETCDR (tail, Fcons (wn, Qnil));
6514 tail = XCDR (tail);
6517 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6520 return result;
6525 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6526 0, 1, 0,
6527 doc: /* Return the window tree for frame FRAME.
6529 The return value is a list of the form (ROOT MINI), where ROOT
6530 represents the window tree of the frame's root window, and MINI
6531 is the frame's minibuffer window.
6533 If the root window is not split, ROOT is the root window itself.
6534 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6535 horizontal split, and t for a vertical split, EDGES gives the combined
6536 size and position of the subwindows in the split, and the rest of the
6537 elements are the subwindows in the split. Each of the subwindows may
6538 again be a window or a list representing a window split, and so on.
6539 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6541 If FRAME is nil or omitted, return information on the currently
6542 selected frame. */)
6543 (Lisp_Object frame)
6545 FRAME_PTR f;
6547 if (NILP (frame))
6548 frame = selected_frame;
6550 CHECK_FRAME (frame);
6551 f = XFRAME (frame);
6553 if (!FRAME_LIVE_P (f))
6554 return Qnil;
6556 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6560 /***********************************************************************
6561 Marginal Areas
6562 ***********************************************************************/
6564 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6565 2, 3, 0,
6566 doc: /* Set width of marginal areas of window WINDOW.
6567 If WINDOW is nil, set margins of the currently selected window.
6568 Second arg LEFT-WIDTH specifies the number of character cells to
6569 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6570 does the same for the right marginal area. A nil width parameter
6571 means no margin. */)
6572 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6574 struct window *w = decode_window (window);
6576 /* Translate negative or zero widths to nil.
6577 Margins that are too wide have to be checked elsewhere. */
6579 if (!NILP (left_width))
6581 CHECK_NUMBER (left_width);
6582 if (XINT (left_width) <= 0)
6583 left_width = Qnil;
6586 if (!NILP (right_width))
6588 CHECK_NUMBER (right_width);
6589 if (XINT (right_width) <= 0)
6590 right_width = Qnil;
6593 if (!EQ (w->left_margin_cols, left_width)
6594 || !EQ (w->right_margin_cols, right_width))
6596 w->left_margin_cols = left_width;
6597 w->right_margin_cols = right_width;
6599 adjust_window_margins (w);
6601 ++windows_or_buffers_changed;
6602 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6605 return Qnil;
6609 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6610 0, 1, 0,
6611 doc: /* Get width of marginal areas of window WINDOW.
6612 If WINDOW is omitted or nil, use the currently selected window.
6613 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6614 If a marginal area does not exist, its width will be returned
6615 as nil. */)
6616 (Lisp_Object window)
6618 struct window *w = decode_window (window);
6619 return Fcons (w->left_margin_cols, w->right_margin_cols);
6624 /***********************************************************************
6625 Fringes
6626 ***********************************************************************/
6628 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6629 2, 4, 0,
6630 doc: /* Set the fringe widths of window WINDOW.
6631 If WINDOW is nil, set the fringe widths of the currently selected
6632 window.
6633 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6634 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6635 fringe width. If a fringe width arg is nil, that means to use the
6636 frame's default fringe width. Default fringe widths can be set with
6637 the command `set-fringe-style'.
6638 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6639 outside of the display margins. By default, fringes are drawn between
6640 display marginal areas and the text area. */)
6641 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
6643 struct window *w = decode_window (window);
6645 if (!NILP (left_width))
6646 CHECK_NATNUM (left_width);
6647 if (!NILP (right_width))
6648 CHECK_NATNUM (right_width);
6650 /* Do nothing on a tty. */
6651 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6652 && (!EQ (w->left_fringe_width, left_width)
6653 || !EQ (w->right_fringe_width, right_width)
6654 || !EQ (w->fringes_outside_margins, outside_margins)))
6656 w->left_fringe_width = left_width;
6657 w->right_fringe_width = right_width;
6658 w->fringes_outside_margins = outside_margins;
6660 adjust_window_margins (w);
6662 clear_glyph_matrix (w->current_matrix);
6663 w->window_end_valid = Qnil;
6665 ++windows_or_buffers_changed;
6666 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6669 return Qnil;
6673 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6674 0, 1, 0,
6675 doc: /* Get width of fringes of window WINDOW.
6676 If WINDOW is omitted or nil, use the currently selected window.
6677 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6678 (Lisp_Object window)
6680 struct window *w = decode_window (window);
6682 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6683 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6684 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6685 ? Qt : Qnil), Qnil)));
6690 /***********************************************************************
6691 Scroll bars
6692 ***********************************************************************/
6694 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6695 2, 4, 0,
6696 doc: /* Set width and type of scroll bars of window WINDOW.
6697 If window is nil, set scroll bars of the currently selected window.
6698 Second parameter WIDTH specifies the pixel width for the scroll bar;
6699 this is automatically adjusted to a multiple of the frame column width.
6700 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6701 bar: left, right, or nil.
6702 If WIDTH is nil, use the frame's scroll-bar width.
6703 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6704 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6705 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6707 struct window *w = decode_window (window);
6709 if (!NILP (width))
6711 CHECK_NATNUM (width);
6713 if (XINT (width) == 0)
6714 vertical_type = Qnil;
6717 if (!(NILP (vertical_type)
6718 || EQ (vertical_type, Qleft)
6719 || EQ (vertical_type, Qright)
6720 || EQ (vertical_type, Qt)))
6721 error ("Invalid type of vertical scroll bar");
6723 if (!EQ (w->scroll_bar_width, width)
6724 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6726 w->scroll_bar_width = width;
6727 w->vertical_scroll_bar_type = vertical_type;
6729 adjust_window_margins (w);
6731 clear_glyph_matrix (w->current_matrix);
6732 w->window_end_valid = Qnil;
6734 ++windows_or_buffers_changed;
6735 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6738 return Qnil;
6742 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6743 0, 1, 0,
6744 doc: /* Get width and type of scroll bars of window WINDOW.
6745 If WINDOW is omitted or nil, use the currently selected window.
6746 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6747 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6748 value. */)
6749 (Lisp_Object window)
6751 struct window *w = decode_window (window);
6752 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6753 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6754 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6755 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6756 Fcons (w->vertical_scroll_bar_type,
6757 Fcons (Qnil, Qnil))));
6762 /***********************************************************************
6763 Smooth scrolling
6764 ***********************************************************************/
6766 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6767 doc: /* Return the amount by which WINDOW is scrolled vertically.
6768 Use the selected window if WINDOW is nil or omitted.
6769 Normally, value is a multiple of the canonical character height of WINDOW;
6770 optional second arg PIXELS-P means value is measured in pixels. */)
6771 (Lisp_Object window, Lisp_Object pixels_p)
6773 Lisp_Object result;
6774 struct frame *f;
6775 struct window *w;
6777 if (NILP (window))
6778 window = selected_window;
6779 else
6780 CHECK_WINDOW (window);
6781 w = XWINDOW (window);
6782 f = XFRAME (w->frame);
6784 if (FRAME_WINDOW_P (f))
6785 result = (NILP (pixels_p)
6786 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6787 : make_number (-w->vscroll));
6788 else
6789 result = make_number (0);
6790 return result;
6794 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6795 2, 3, 0,
6796 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6797 WINDOW nil means use the selected window. Normally, VSCROLL is a
6798 non-negative multiple of the canonical character height of WINDOW;
6799 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6800 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6801 corresponds to an integral number of pixels. The return value is the
6802 result of this rounding.
6803 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6804 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6806 struct window *w;
6807 struct frame *f;
6809 if (NILP (window))
6810 window = selected_window;
6811 else
6812 CHECK_WINDOW (window);
6813 CHECK_NUMBER_OR_FLOAT (vscroll);
6815 w = XWINDOW (window);
6816 f = XFRAME (w->frame);
6818 if (FRAME_WINDOW_P (f))
6820 int old_dy = w->vscroll;
6822 w->vscroll = - (NILP (pixels_p)
6823 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6824 : XFLOATINT (vscroll));
6825 w->vscroll = min (w->vscroll, 0);
6827 if (w->vscroll != old_dy)
6829 /* Adjust glyph matrix of the frame if the virtual display
6830 area becomes larger than before. */
6831 if (w->vscroll < 0 && w->vscroll < old_dy)
6832 adjust_glyphs (f);
6834 /* Prevent redisplay shortcuts. */
6835 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6839 return Fwindow_vscroll (window, pixels_p);
6843 /* Call FN for all leaf windows on frame F. FN is called with the
6844 first argument being a pointer to the leaf window, and with
6845 additional argument USER_DATA. Stops when FN returns 0. */
6847 void
6848 foreach_window (struct frame *f, int (*fn) (struct window *, void *), void *user_data)
6850 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6851 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6852 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6856 /* Helper function for foreach_window. Call FN for all leaf windows
6857 reachable from W. FN is called with the first argument being a
6858 pointer to the leaf window, and with additional argument USER_DATA.
6859 Stop when FN returns 0. Value is 0 if stopped by FN. */
6861 static int
6862 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6864 int cont;
6866 for (cont = 1; w && cont;)
6868 if (!NILP (w->hchild))
6869 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6870 else if (!NILP (w->vchild))
6871 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6872 else
6873 cont = fn (w, user_data);
6875 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6878 return cont;
6882 /* Freeze or unfreeze the window start of W unless it is a
6883 mini-window or the selected window. FREEZE_P non-null means freeze
6884 the window start. */
6886 static int
6887 freeze_window_start (struct window *w, void *freeze_p)
6889 if (MINI_WINDOW_P (w)
6890 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
6891 && (w == XWINDOW (selected_window)
6892 || (MINI_WINDOW_P (XWINDOW (selected_window))
6893 && ! NILP (Vminibuf_scroll_window)
6894 && w == XWINDOW (Vminibuf_scroll_window)))))
6895 freeze_p = NULL;
6897 w->frozen_window_start_p = freeze_p != NULL;
6898 return 1;
6902 /* Freeze or unfreeze the window starts of all leaf windows on frame
6903 F, except the selected window and a mini-window. FREEZE_P non-zero
6904 means freeze the window start. */
6906 void
6907 freeze_window_starts (struct frame *f, int freeze_p)
6909 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6913 /***********************************************************************
6914 Initialization
6915 ***********************************************************************/
6917 /* Return 1 if window configurations C1 and C2
6918 describe the same state of affairs. This is used by Fequal. */
6921 compare_window_configurations (Lisp_Object c1, Lisp_Object c2, int ignore_positions)
6923 register struct save_window_data *d1, *d2;
6924 struct Lisp_Vector *sw1, *sw2;
6925 int i;
6927 CHECK_WINDOW_CONFIGURATION (c1);
6928 CHECK_WINDOW_CONFIGURATION (c2);
6930 d1 = (struct save_window_data *) XVECTOR (c1);
6931 d2 = (struct save_window_data *) XVECTOR (c2);
6932 sw1 = XVECTOR (d1->saved_windows);
6933 sw2 = XVECTOR (d2->saved_windows);
6935 if (d1->frame_cols != d2->frame_cols)
6936 return 0;
6937 if (d1->frame_lines != d2->frame_lines)
6938 return 0;
6939 if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines)
6940 return 0;
6941 if (! EQ (d1->selected_frame, d2->selected_frame))
6942 return 0;
6943 /* Don't compare the current_window field directly.
6944 Instead see w1_is_current and w2_is_current, below. */
6945 if (! EQ (d1->current_buffer, d2->current_buffer))
6946 return 0;
6947 if (! ignore_positions)
6949 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6950 return 0;
6951 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6952 return 0;
6954 /* Don't compare the root_window field.
6955 We don't require the two configurations
6956 to use the same window object,
6957 and the two root windows must be equivalent
6958 if everything else compares equal. */
6959 if (! EQ (d1->focus_frame, d2->focus_frame))
6960 return 0;
6962 /* Verify that the two confis have the same number of windows. */
6963 if (sw1->size != sw2->size)
6964 return 0;
6966 for (i = 0; i < sw1->size; i++)
6968 struct saved_window *p1, *p2;
6969 int w1_is_current, w2_is_current;
6971 p1 = SAVED_WINDOW_N (sw1, i);
6972 p2 = SAVED_WINDOW_N (sw2, i);
6974 /* Verify that the current windows in the two
6975 configurations correspond to each other. */
6976 w1_is_current = EQ (d1->current_window, p1->window);
6977 w2_is_current = EQ (d2->current_window, p2->window);
6979 if (w1_is_current != w2_is_current)
6980 return 0;
6982 /* Verify that the corresponding windows do match. */
6983 if (! EQ (p1->buffer, p2->buffer))
6984 return 0;
6985 if (! EQ (p1->left_col, p2->left_col))
6986 return 0;
6987 if (! EQ (p1->top_line, p2->top_line))
6988 return 0;
6989 if (! EQ (p1->total_cols, p2->total_cols))
6990 return 0;
6991 if (! EQ (p1->total_lines, p2->total_lines))
6992 return 0;
6993 if (! EQ (p1->display_table, p2->display_table))
6994 return 0;
6995 if (! EQ (p1->parent, p2->parent))
6996 return 0;
6997 if (! EQ (p1->prev, p2->prev))
6998 return 0;
6999 if (! ignore_positions)
7001 if (! EQ (p1->hscroll, p2->hscroll))
7002 return 0;
7003 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7004 return 0;
7005 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7006 return 0;
7007 if (NILP (Fequal (p1->start, p2->start)))
7008 return 0;
7009 if (NILP (Fequal (p1->pointm, p2->pointm)))
7010 return 0;
7011 if (NILP (Fequal (p1->mark, p2->mark)))
7012 return 0;
7014 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7015 return 0;
7016 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7017 return 0;
7018 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7019 return 0;
7020 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7021 return 0;
7022 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7023 return 0;
7024 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7025 return 0;
7026 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7027 return 0;
7030 return 1;
7033 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7034 Scompare_window_configurations, 2, 2, 0,
7035 doc: /* Compare two window configurations as regards the structure of windows.
7036 This function ignores details such as the values of point and mark
7037 and scrolling positions. */)
7038 (Lisp_Object x, Lisp_Object y)
7040 if (compare_window_configurations (x, y, 1))
7041 return Qt;
7042 return Qnil;
7045 void
7046 init_window_once (void)
7048 struct frame *f = make_initial_frame ();
7049 XSETFRAME (selected_frame, f);
7050 Vterminal_frame = selected_frame;
7051 minibuf_window = f->minibuffer_window;
7052 selected_window = f->selected_window;
7053 last_nonminibuf_frame = f;
7055 window_initialized = 1;
7058 void
7059 init_window (void)
7061 Vwindow_list = Qnil;
7064 void
7065 syms_of_window (void)
7067 Qscroll_up = intern_c_string ("scroll-up");
7068 staticpro (&Qscroll_up);
7070 Qscroll_down = intern_c_string ("scroll-down");
7071 staticpro (&Qscroll_down);
7073 Qscroll_command = intern_c_string ("scroll-command");
7074 staticpro (&Qscroll_command);
7076 Fput (Qscroll_up, Qscroll_command, Qt);
7077 Fput (Qscroll_down, Qscroll_command, Qt);
7079 Qwindow_size_fixed = intern_c_string ("window-size-fixed");
7080 staticpro (&Qwindow_size_fixed);
7081 Fset (Qwindow_size_fixed, Qnil);
7083 staticpro (&Qwindow_configuration_change_hook);
7084 Qwindow_configuration_change_hook
7085 = intern_c_string ("window-configuration-change-hook");
7087 Qwindowp = intern_c_string ("windowp");
7088 staticpro (&Qwindowp);
7090 Qwindow_configuration_p = intern_c_string ("window-configuration-p");
7091 staticpro (&Qwindow_configuration_p);
7093 Qwindow_live_p = intern_c_string ("window-live-p");
7094 staticpro (&Qwindow_live_p);
7096 Qdisplay_buffer = intern_c_string ("display-buffer");
7097 staticpro (&Qdisplay_buffer);
7099 Qtemp_buffer_show_hook = intern_c_string ("temp-buffer-show-hook");
7100 staticpro (&Qtemp_buffer_show_hook);
7102 staticpro (&Vwindow_list);
7104 minibuf_selected_window = Qnil;
7105 staticpro (&minibuf_selected_window);
7107 window_scroll_pixel_based_preserve_x = -1;
7108 window_scroll_pixel_based_preserve_y = -1;
7109 window_scroll_preserve_hpos = -1;
7110 window_scroll_preserve_vpos = -1;
7112 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7113 doc: /* Non-nil means call as function to display a help buffer.
7114 The function is called with one argument, the buffer to be displayed.
7115 Used by `with-output-to-temp-buffer'.
7116 If this function is used, then it must do the entire job of showing
7117 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7118 Vtemp_buffer_show_function = Qnil;
7120 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7121 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7122 Vminibuf_scroll_window = Qnil;
7124 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7125 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7126 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7127 is displayed in the `mode-line' face. */);
7128 mode_line_in_non_selected_windows = 1;
7130 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7131 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7132 Vother_window_scroll_buffer = Qnil;
7134 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7135 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7136 auto_window_vscroll_p = 1;
7138 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7139 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7140 next_screen_context_lines = 2;
7142 DEFVAR_INT ("window-min-height", &window_min_height,
7143 doc: /* Allow deleting windows less than this tall.
7144 The value is measured in line units. If a window wants a modeline it
7145 is counted as one line.
7147 Emacs honors settings of this variable when enlarging or shrinking
7148 windows vertically. A value less than 1 is invalid. */);
7149 window_min_height = 4;
7151 DEFVAR_INT ("window-min-width", &window_min_width,
7152 doc: /* Allow deleting windows less than this wide.
7153 The value is measured in characters and includes any fringes or
7154 the scrollbar.
7156 Emacs honors settings of this variable when enlarging or shrinking
7157 windows horizontally. A value less than 2 is invalid. */);
7158 window_min_width = 10;
7160 DEFVAR_LISP ("scroll-preserve-screen-position",
7161 &Vscroll_preserve_screen_position,
7162 doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
7163 A value of nil means point does not keep its screen position except
7164 at the scroll margin or window boundary respectively.
7165 A value of t means point keeps its screen position if the scroll
7166 command moved it vertically out of the window, e.g. when scrolling
7167 by full screens.
7168 Any other value means point always keeps its screen position.
7169 Scroll commands should have the `scroll-command' property
7170 on their symbols to be controlled by this variable. */);
7171 Vscroll_preserve_screen_position = Qnil;
7173 DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type,
7174 doc: /* Type of marker to use for `window-point'. */);
7175 Vwindow_point_insertion_type = Qnil;
7177 DEFVAR_LISP ("window-configuration-change-hook",
7178 &Vwindow_configuration_change_hook,
7179 doc: /* Functions to call when window configuration changes.
7180 The buffer-local part is run once per window, with the relevant window
7181 selected; while the global part is run only once for the modified frame,
7182 with the relevant frame selected. */);
7183 Vwindow_configuration_change_hook = Qnil;
7185 DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay,
7186 doc: /* If non-nil, then the `recenter' command with a nil argument
7187 will redraw the entire frame; the special value `tty' causes the
7188 frame to be redrawn only if it is a tty frame. */);
7189 Vrecenter_redisplay = Qtty;
7192 defsubr (&Sselected_window);
7193 defsubr (&Sminibuffer_window);
7194 defsubr (&Swindow_minibuffer_p);
7195 defsubr (&Swindowp);
7196 defsubr (&Swindow_live_p);
7197 defsubr (&Spos_visible_in_window_p);
7198 defsubr (&Swindow_line_height);
7199 defsubr (&Swindow_buffer);
7200 defsubr (&Swindow_height);
7201 defsubr (&Swindow_width);
7202 defsubr (&Swindow_full_width_p);
7203 defsubr (&Swindow_hscroll);
7204 defsubr (&Sset_window_hscroll);
7205 defsubr (&Swindow_redisplay_end_trigger);
7206 defsubr (&Sset_window_redisplay_end_trigger);
7207 defsubr (&Swindow_edges);
7208 defsubr (&Swindow_pixel_edges);
7209 defsubr (&Swindow_absolute_pixel_edges);
7210 defsubr (&Swindow_inside_edges);
7211 defsubr (&Swindow_inside_pixel_edges);
7212 defsubr (&Swindow_inside_absolute_pixel_edges);
7213 defsubr (&Scoordinates_in_window_p);
7214 defsubr (&Swindow_at);
7215 defsubr (&Swindow_point);
7216 defsubr (&Swindow_start);
7217 defsubr (&Swindow_end);
7218 defsubr (&Sset_window_point);
7219 defsubr (&Sset_window_start);
7220 defsubr (&Swindow_dedicated_p);
7221 defsubr (&Sset_window_dedicated_p);
7222 defsubr (&Swindow_display_table);
7223 defsubr (&Sset_window_display_table);
7224 defsubr (&Snext_window);
7225 defsubr (&Sprevious_window);
7226 defsubr (&Sother_window);
7227 defsubr (&Sget_lru_window);
7228 defsubr (&Sget_largest_window);
7229 defsubr (&Sget_buffer_window);
7230 defsubr (&Sdelete_other_windows);
7231 defsubr (&Sdelete_windows_on);
7232 defsubr (&Sreplace_buffer_in_windows);
7233 defsubr (&Sdelete_window);
7234 defsubr (&Sset_window_buffer);
7235 defsubr (&Sselect_window);
7236 defsubr (&Sforce_window_update);
7237 defsubr (&Ssplit_window);
7238 defsubr (&Senlarge_window);
7239 defsubr (&Sshrink_window);
7240 defsubr (&Sadjust_window_trailing_edge);
7241 defsubr (&Sscroll_up);
7242 defsubr (&Sscroll_down);
7243 defsubr (&Sscroll_left);
7244 defsubr (&Sscroll_right);
7245 defsubr (&Sother_window_for_scrolling);
7246 defsubr (&Sscroll_other_window);
7247 defsubr (&Sminibuffer_selected_window);
7248 defsubr (&Srecenter);
7249 defsubr (&Swindow_text_height);
7250 defsubr (&Smove_to_window_line);
7251 defsubr (&Swindow_configuration_p);
7252 defsubr (&Swindow_configuration_frame);
7253 defsubr (&Sset_window_configuration);
7254 defsubr (&Scurrent_window_configuration);
7255 defsubr (&Ssave_window_excursion);
7256 defsubr (&Swindow_tree);
7257 defsubr (&Sset_window_margins);
7258 defsubr (&Swindow_margins);
7259 defsubr (&Sset_window_fringes);
7260 defsubr (&Swindow_fringes);
7261 defsubr (&Sset_window_scroll_bars);
7262 defsubr (&Swindow_scroll_bars);
7263 defsubr (&Swindow_vscroll);
7264 defsubr (&Sset_window_vscroll);
7265 defsubr (&Scompare_window_configurations);
7266 defsubr (&Swindow_list);
7267 defsubr (&Swindow_parameters);
7268 defsubr (&Swindow_parameter);
7269 defsubr (&Sset_window_parameter);
7273 void
7274 keys_of_window (void)
7276 initial_define_key (control_x_map, '1', "delete-other-windows");
7277 initial_define_key (control_x_map, '2', "split-window");
7278 initial_define_key (control_x_map, '0', "delete-window");
7279 initial_define_key (control_x_map, 'o', "other-window");
7280 initial_define_key (control_x_map, '^', "enlarge-window");
7281 initial_define_key (control_x_map, '<', "scroll-left");
7282 initial_define_key (control_x_map, '>', "scroll-right");
7284 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
7285 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7286 initial_define_key (meta_map, 'v', "scroll-down-command");
7289 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7290 (do not change this comment) */