1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
34 #include "dispextern.h"
35 #include "blockinput.h"
36 #include "intervals.h"
40 #endif /* HAVE_X_WINDOWS */
51 /* Values returned from coordinates_in_window. */
65 Lisp_Object Qwindowp
, Qwindow_live_p
, Qwindow_configuration_p
;
66 Lisp_Object Qwindow_size_fixed
;
67 extern Lisp_Object Qheight
, Qwidth
;
69 static int displayed_window_lines
P_ ((struct window
*));
70 static struct window
*decode_window
P_ ((Lisp_Object
));
71 static Lisp_Object select_window_1
P_ ((Lisp_Object
, int));
72 static int count_windows
P_ ((struct window
*));
73 static int get_leaf_windows
P_ ((struct window
*, struct window
**, int));
74 static void window_scroll
P_ ((Lisp_Object
, int, int, int));
75 static void window_scroll_pixel_based
P_ ((Lisp_Object
, int, int, int));
76 static void window_scroll_line_based
P_ ((Lisp_Object
, int, int, int));
77 static int window_min_size_1
P_ ((struct window
*, int));
78 static int window_min_size
P_ ((struct window
*, int, int, int *));
79 static void size_window
P_ ((Lisp_Object
, int, int, int));
80 static int freeze_window_start
P_ ((struct window
*, void *));
81 static int window_fixed_size_p
P_ ((struct window
*, int, int));
82 static void enlarge_window
P_ ((Lisp_Object
, int, int, int));
83 static Lisp_Object window_list
P_ ((void));
84 static int add_window_to_list
P_ ((struct window
*, void *));
85 static int candidate_window_p
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
87 static Lisp_Object next_window
P_ ((Lisp_Object
, Lisp_Object
,
89 static void decode_next_window_args
P_ ((Lisp_Object
*, Lisp_Object
*,
91 static int foreach_window_1
P_ ((struct window
*,
92 int (* fn
) (struct window
*, void *),
94 static Lisp_Object window_list_1
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
));
96 /* The value of `window-size-fixed'. */
98 int window_size_fixed
;
100 /* This is the window in which the terminal's cursor should
101 be left when nothing is being done with it. This must
102 always be a leaf window, and its buffer is selected by
103 the top level editing loop at the end of each command.
105 This value is always the same as
106 FRAME_SELECTED_WINDOW (selected_frame). */
108 Lisp_Object selected_window
;
110 /* A list of all windows for use by next_window and Fwindow_list.
111 Functions creating or deleting windows should invalidate this cache
112 by setting it to nil. */
114 Lisp_Object Vwindow_list
;
116 /* The mini-buffer window of the selected frame.
117 Note that you cannot test for mini-bufferness of an arbitrary window
118 by comparing against this; but you can test for mini-bufferness of
119 the selected window. */
121 Lisp_Object minibuf_window
;
123 /* Non-nil means it is the window whose mode line should be
124 shown as the selected window when the minibuffer is selected. */
126 Lisp_Object minibuf_selected_window
;
128 /* Non-nil means it is the window for C-M-v to scroll
129 when the mini-buffer is selected. */
131 Lisp_Object Vminibuf_scroll_window
;
133 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
135 Lisp_Object Vother_window_scroll_buffer
;
137 /* Non-nil means it's function to call to display temp buffers. */
139 Lisp_Object Vtemp_buffer_show_function
;
141 /* Non-zero means to use mode-line-inactive face in all windows but the
142 selected-window and the minibuffer-scroll-window when the
143 minibuffer is active. */
144 int mode_line_in_non_selected_windows
;
146 /* If a window gets smaller than either of these, it is removed. */
148 EMACS_INT window_min_height
;
149 EMACS_INT window_min_width
;
151 /* Nonzero implies Fdisplay_buffer should create windows. */
155 /* Nonzero implies make new frames for Fdisplay_buffer. */
159 /* Nonzero means reuse existing frames for displaying buffers. */
161 int display_buffer_reuse_frames
;
163 /* Non-nil means use this function instead of default */
165 Lisp_Object Vpop_up_frame_function
;
167 /* Function to call to handle Fdisplay_buffer. */
169 Lisp_Object Vdisplay_buffer_function
;
171 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
173 Lisp_Object Veven_window_heights
;
175 /* List of buffer *names* for buffers that should have their own frames. */
177 Lisp_Object Vspecial_display_buffer_names
;
179 /* List of regexps for buffer names that should have their own frames. */
181 Lisp_Object Vspecial_display_regexps
;
183 /* Function to pop up a special frame. */
185 Lisp_Object Vspecial_display_function
;
187 /* List of buffer *names* for buffers to appear in selected window. */
189 Lisp_Object Vsame_window_buffer_names
;
191 /* List of regexps for buffer names to appear in selected window. */
193 Lisp_Object Vsame_window_regexps
;
195 /* Hook run at end of temp_output_buffer_show. */
197 Lisp_Object Qtemp_buffer_show_hook
;
199 /* Fdisplay_buffer always splits the largest window
200 if that window is more than this high. */
202 EMACS_INT split_height_threshold
;
204 /* Number of lines of continuity in scrolling by screenfuls. */
206 EMACS_INT next_screen_context_lines
;
208 /* Incremented for each window created. */
210 static int sequence_number
;
212 /* Nonzero after init_window_once has finished. */
214 static int window_initialized
;
216 /* Hook to run when window config changes. */
218 Lisp_Object Qwindow_configuration_change_hook
;
219 Lisp_Object Vwindow_configuration_change_hook
;
221 /* Nonzero means scroll commands try to put point
222 at the same screen height as previously. */
224 Lisp_Object Vscroll_preserve_screen_position
;
226 #if 0 /* This isn't used anywhere. */
227 /* Nonzero means we can split a frame even if it is "unsplittable". */
228 static int inhibit_frame_unsplittable
;
231 extern EMACS_INT scroll_margin
;
233 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
235 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
236 doc
: /* Returns t if OBJECT is a window. */)
240 return WINDOWP (object
) ? Qt
: Qnil
;
243 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
244 doc
: /* Returns t if OBJECT is a window which is currently visible. */)
248 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
255 register struct window
*p
;
257 p
= allocate_window ();
258 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
259 XSETFASTINT (p
->left
, 0);
260 XSETFASTINT (p
->top
, 0);
261 XSETFASTINT (p
->height
, 0);
262 XSETFASTINT (p
->width
, 0);
263 XSETFASTINT (p
->hscroll
, 0);
264 XSETFASTINT (p
->min_hscroll
, 0);
265 p
->orig_top
= p
->orig_height
= Qnil
;
266 p
->start
= Fmake_marker ();
267 p
->pointm
= Fmake_marker ();
268 XSETFASTINT (p
->use_time
, 0);
270 p
->display_table
= Qnil
;
272 p
->pseudo_window_p
= 0;
273 bzero (&p
->cursor
, sizeof (p
->cursor
));
274 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
275 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
276 p
->desired_matrix
= p
->current_matrix
= 0;
277 p
->phys_cursor_type
= -1;
278 p
->phys_cursor_width
= -1;
279 p
->must_be_updated_p
= 0;
280 XSETFASTINT (p
->window_end_vpos
, 0);
281 XSETFASTINT (p
->window_end_pos
, 0);
282 p
->window_end_valid
= Qnil
;
285 XSETFASTINT (p
->last_point
, 0);
286 p
->frozen_window_start_p
= 0;
292 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
293 doc
: /* Return the window that the cursor now appears in and commands apply to. */)
296 return selected_window
;
299 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
300 doc
: /* Return the window used now for minibuffers.
301 If the optional argument FRAME is specified, return the minibuffer window
302 used by that frame. */)
307 frame
= selected_frame
;
308 CHECK_LIVE_FRAME (frame
);
309 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
312 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
313 doc
: /* Returns non-nil if WINDOW is a minibuffer window. */)
317 struct window
*w
= decode_window (window
);
318 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
322 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
323 Spos_visible_in_window_p
, 0, 3, 0,
324 doc
: /* Return t if position POS is currently on the frame in WINDOW.
325 Return nil if that position is scrolled vertically out of view.
326 If a character is only partially visible, nil is returned, unless the
327 optional argument PARTIALLY is non-nil.
328 POS defaults to point in WINDOW; WINDOW defaults to the selected window. */)
329 (pos
, window
, partially
)
330 Lisp_Object pos
, window
, partially
;
332 register struct window
*w
;
334 register struct buffer
*buf
;
336 Lisp_Object in_window
;
339 w
= decode_window (window
);
340 buf
= XBUFFER (w
->buffer
);
341 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
345 CHECK_NUMBER_COERCE_MARKER (pos
);
348 else if (w
== XWINDOW (selected_window
))
351 posint
= XMARKER (w
->pointm
)->charpos
;
353 /* If position is above window start, it's not visible. */
354 if (posint
< CHARPOS (top
))
356 else if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
)
357 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (buf
)
358 && posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
))
360 /* If frame is up-to-date, and POSINT is < window end pos, use
361 that info. This doesn't work for POSINT == end pos, because
362 the window end pos is actually the position _after_ the last
363 char in the window. */
364 if (NILP (partially
))
366 pos_visible_p (w
, posint
, &fully_p
, NILP (partially
));
367 in_window
= fully_p
? Qt
: Qnil
;
372 else if (posint
> BUF_ZV (buf
))
374 else if (CHARPOS (top
) < BUF_BEGV (buf
) || CHARPOS (top
) > BUF_ZV (buf
))
375 /* If window start is out of range, do something reasonable. */
379 if (pos_visible_p (w
, posint
, &fully_p
, NILP (partially
)))
380 in_window
= !NILP (partially
) || fully_p
? Qt
: Qnil
;
389 static struct window
*
390 decode_window (window
)
391 register Lisp_Object window
;
394 return XWINDOW (selected_window
);
396 CHECK_LIVE_WINDOW (window
);
397 return XWINDOW (window
);
400 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
401 doc
: /* Return the buffer that WINDOW is displaying. */)
405 return decode_window (window
)->buffer
;
408 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
409 doc
: /* Return the number of lines in WINDOW (including its mode line). */)
413 return decode_window (window
)->height
;
416 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
417 doc
: /* Return the number of display columns in WINDOW.
418 This is the width that is usable columns available for text in WINDOW.
419 If you want to find out how many columns WINDOW takes up,
420 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
424 return make_number (window_internal_width (decode_window (window
)));
427 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
428 doc
: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
432 return decode_window (window
)->hscroll
;
435 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
436 doc
: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
437 NCOL should be zero or positive. */)
439 Lisp_Object window
, ncol
;
441 struct window
*w
= decode_window (window
);
445 hscroll
= max (0, XINT (ncol
));
447 /* Prevent redisplay shortcuts when changing the hscroll. */
448 if (XINT (w
->hscroll
) != hscroll
)
449 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
451 w
->hscroll
= make_number (hscroll
);
455 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
456 Swindow_redisplay_end_trigger
, 0, 1, 0,
457 doc
: /* Return WINDOW's redisplay end trigger value.
458 See `set-window-redisplay-end-trigger' for more information. */)
462 return decode_window (window
)->redisplay_end_trigger
;
465 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
466 Sset_window_redisplay_end_trigger
, 2, 2, 0,
467 doc
: /* Set WINDOW's redisplay end trigger value to VALUE.
468 VALUE should be a buffer position (typically a marker) or nil.
469 If it is a buffer position, then if redisplay in WINDOW reaches a position
470 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
471 with two arguments: WINDOW, and the end trigger value.
472 Afterwards the end-trigger value is reset to nil. */)
474 register Lisp_Object window
, value
;
476 register struct window
*w
;
478 w
= decode_window (window
);
479 w
->redisplay_end_trigger
= value
;
483 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
484 doc
: /* Return a list of the edge coordinates of WINDOW.
485 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
486 RIGHT is one more than the rightmost column used by WINDOW,
487 and BOTTOM is one more than the bottommost row used by WINDOW
488 and its mode-line. */)
492 register struct window
*w
= decode_window (window
);
494 return Fcons (w
->left
, Fcons (w
->top
,
495 Fcons (make_number (WINDOW_RIGHT_EDGE (w
)),
496 Fcons (make_number (XFASTINT (w
->top
)
497 + XFASTINT (w
->height
)),
501 /* Test if the character at column *X, row *Y is within window W.
502 If it is not, return 0;
503 if it is in the window's text area,
504 set *x and *y to its location relative to the upper left corner
507 if it is on the window's modeline, return 2;
508 if it is on the border between the window and its right sibling,
510 if it is on the window's top line, return 4;
511 if it is in left or right fringe of the window,
512 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
514 X and Y are frame relative pixel coordinates. */
516 static enum window_part
517 coordinates_in_window (w
, x
, y
)
518 register struct window
*w
;
521 /* Let's make this a global enum later, instead of using numbers
523 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
524 int left_x
, right_x
, top_y
, bottom_y
;
525 enum window_part part
;
526 int ux
= CANON_X_UNIT (f
);
527 int x0
= XFASTINT (w
->left
) * ux
;
528 int x1
= x0
+ XFASTINT (w
->width
) * ux
;
529 /* The width of the area where the vertical line can be dragged.
530 (Between mode lines for instance. */
531 int grabbable_width
= ux
;
533 if (*x
< x0
|| *x
>= x1
)
536 /* In what's below, we subtract 1 when computing right_x because we
537 want the rightmost pixel, which is given by left_pixel+width-1. */
538 if (w
->pseudo_window_p
)
541 right_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
) - 1;
542 top_y
= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w
);
543 bottom_y
= WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w
);
547 left_x
= (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w
)
548 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
));
549 right_x
= WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w
) - 1;
550 top_y
= (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w
)
551 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
));
552 bottom_y
= WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w
);
555 /* On the mode line or header line? If it's near the start of
556 the mode or header line of window that's has a horizontal
557 sibling, say it's on the vertical line. That's to be able
558 to resize windows horizontally in case we're using toolkit
561 if (WINDOW_WANTS_MODELINE_P (w
)
562 && *y
>= bottom_y
- CURRENT_MODE_LINE_HEIGHT (w
)
565 /* We're somewhere on the mode line. We consider the place
566 between mode lines of horizontally adjacent mode lines
567 as the vertical border. If scroll bars on the left,
568 return the right window. */
571 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
573 if (abs (*x
- x0
) < grabbable_width
)
574 part
= ON_VERTICAL_BORDER
;
576 else if (!WINDOW_RIGHTMOST_P (w
) && abs (*x
- x1
) < grabbable_width
)
577 part
= ON_VERTICAL_BORDER
;
579 else if (WINDOW_WANTS_HEADER_LINE_P (w
)
580 && *y
< top_y
+ CURRENT_HEADER_LINE_HEIGHT (w
)
583 part
= ON_HEADER_LINE
;
585 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
587 if (abs (*x
- x0
) < grabbable_width
)
588 part
= ON_VERTICAL_BORDER
;
590 else if (!WINDOW_RIGHTMOST_P (w
) && abs (*x
- x1
) < grabbable_width
)
591 part
= ON_VERTICAL_BORDER
;
593 /* Outside anything interesting? */
597 - FRAME_LEFT_FRINGE_WIDTH (f
)
598 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * ux
)
600 + FRAME_RIGHT_FRINGE_WIDTH (f
)
601 + FRAME_RIGHT_SCROLL_BAR_WIDTH (f
) * ux
))
605 else if (FRAME_WINDOW_P (f
))
607 if (!w
->pseudo_window_p
608 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
609 && !WINDOW_RIGHTMOST_P (w
)
610 && (abs (*x
- right_x
- FRAME_RIGHT_FRINGE_WIDTH (f
)) < grabbable_width
))
612 part
= ON_VERTICAL_BORDER
;
614 else if (*x
< left_x
|| *x
> right_x
)
616 /* Other lines than the mode line don't include fringes and
617 scroll bars on the left. */
619 /* Convert X and Y to window-relative pixel coordinates. */
622 part
= *x
< left_x
? ON_LEFT_FRINGE
: ON_RIGHT_FRINGE
;
633 /* Need to say "*x > right_x" rather than >=, since on character
634 terminals, the vertical line's x coordinate is right_x. */
635 if (*x
< left_x
|| *x
> right_x
)
637 /* Other lines than the mode line don't include fringes and
638 scroll bars on the left. */
640 /* Convert X and Y to window-relative pixel coordinates. */
643 part
= *x
< left_x
? ON_LEFT_FRINGE
: ON_RIGHT_FRINGE
;
645 /* Here, too, "*x > right_x" is because of character terminals. */
646 else if (!w
->pseudo_window_p
647 && !WINDOW_RIGHTMOST_P (w
)
648 && *x
> right_x
- ux
)
650 /* On the border on the right side of the window? Assume that
651 this area begins at RIGHT_X minus a canonical char width. */
652 part
= ON_VERTICAL_BORDER
;
656 /* Convert X and Y to window-relative pixel coordinates. */
667 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
668 Scoordinates_in_window_p
, 2, 2, 0,
669 doc
: /* Return non-nil if COORDINATES are in WINDOW.
670 COORDINATES is a cons of the form (X . Y), X and Y being distances
671 measured in characters from the upper-left corner of the frame.
672 \(0 . 0) denotes the character in the upper left corner of the
674 If COORDINATES are in the text portion of WINDOW,
675 the coordinates relative to the window are returned.
676 If they are in the mode line of WINDOW, `mode-line' is returned.
677 If they are in the top mode line of WINDOW, `header-line' is returned.
678 If they are in the left fringe of WINDOW, `left-fringe' is returned.
679 If they are in the right fringe of WINDOW, `right-fringe' is returned.
680 If they are on the border between WINDOW and its right sibling,
681 `vertical-line' is returned. */)
682 (coordinates
, window
)
683 register Lisp_Object coordinates
, window
;
690 CHECK_LIVE_WINDOW (window
);
691 w
= XWINDOW (window
);
692 f
= XFRAME (w
->frame
);
693 CHECK_CONS (coordinates
);
694 lx
= Fcar (coordinates
);
695 ly
= Fcdr (coordinates
);
696 CHECK_NUMBER_OR_FLOAT (lx
);
697 CHECK_NUMBER_OR_FLOAT (ly
);
698 x
= PIXEL_X_FROM_CANON_X (f
, lx
);
699 y
= PIXEL_Y_FROM_CANON_Y (f
, ly
);
701 switch (coordinates_in_window (w
, &x
, &y
))
707 /* X and Y are now window relative pixel coordinates. Convert
708 them to canonical char units before returning them. */
709 return Fcons (CANON_X_FROM_PIXEL_X (f
, x
),
710 CANON_Y_FROM_PIXEL_Y (f
, y
));
715 case ON_VERTICAL_BORDER
:
716 return Qvertical_line
;
724 case ON_RIGHT_FRINGE
:
725 return Qright_fringe
;
733 /* Callback for foreach_window, used in window_from_coordinates.
734 Check if window W contains coordinates specified by USER_DATA which
735 is actually a pointer to a struct check_window_data CW.
737 Check if window W contains coordinates *CW->x and *CW->y. If it
738 does, return W in *CW->window, as Lisp_Object, and return in
739 *CW->part the part of the window under coordinates *X,*Y. Return
740 zero from this function to stop iterating over windows. */
742 struct check_window_data
749 check_window_containing (w
, user_data
)
753 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
754 enum window_part found
;
757 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
758 if (found
!= ON_NOTHING
)
760 *cw
->part
= found
- 1;
761 XSETWINDOW (*cw
->window
, w
);
769 /* Find the window containing frame-relative pixel position X/Y and
770 return it as a Lisp_Object. If X, Y is on the window's modeline,
771 set *PART to 1; if it is on the separating line between the window
772 and its right sibling, set it to 2; otherwise set it to 0. If
773 there is no window under X, Y return nil and leave *PART
774 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
776 This function was previously implemented with a loop cycling over
777 windows with Fnext_window, and starting with the frame's selected
778 window. It turned out that this doesn't work with an
779 implementation of next_window using Vwindow_list, because
780 FRAME_SELECTED_WINDOW (F) is not always contained in the window
781 tree of F when this function is called asynchronously from
782 note_mouse_highlight. The original loop didn't terminate in this
786 window_from_coordinates (f
, x
, y
, part
, tool_bar_p
)
793 struct check_window_data cw
;
796 cw
.window
= &window
, cw
.x
= &x
, cw
.y
= &y
; cw
.part
= part
;
797 foreach_window (f
, check_window_containing
, &cw
);
799 /* If not found above, see if it's in the tool bar window, if a tool
803 && WINDOWP (f
->tool_bar_window
)
804 && XINT (XWINDOW (f
->tool_bar_window
)->height
) > 0
805 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), &x
, &y
)
809 window
= f
->tool_bar_window
;
815 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
816 doc
: /* Return window containing coordinates X and Y on FRAME.
817 If omitted, FRAME defaults to the currently selected frame.
818 The top left corner of the frame is considered to be row 0,
821 Lisp_Object x
, y
, frame
;
827 frame
= selected_frame
;
828 CHECK_LIVE_FRAME (frame
);
831 /* Check that arguments are integers or floats. */
832 CHECK_NUMBER_OR_FLOAT (x
);
833 CHECK_NUMBER_OR_FLOAT (y
);
835 return window_from_coordinates (f
,
836 PIXEL_X_FROM_CANON_X (f
, x
),
837 PIXEL_Y_FROM_CANON_Y (f
, y
),
841 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
842 doc
: /* Return current value of point in WINDOW.
843 For a nonselected window, this is the value point would have
844 if that window were selected.
846 Note that, when WINDOW is the selected window and its buffer
847 is also currently selected, the value returned is the same as (point).
848 It would be more strictly correct to return the `top-level' value
849 of point, outside of any save-excursion forms.
850 But that is hard to define. */)
854 register struct window
*w
= decode_window (window
);
856 if (w
== XWINDOW (selected_window
)
857 && current_buffer
== XBUFFER (w
->buffer
))
859 return Fmarker_position (w
->pointm
);
862 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
863 doc
: /* Return position at which display currently starts in WINDOW.
864 This is updated by redisplay or by calling `set-window-start'. */)
868 return Fmarker_position (decode_window (window
)->start
);
871 /* This is text temporarily removed from the doc string below.
873 This function returns nil if the position is not currently known.
874 That happens when redisplay is preempted and doesn't finish.
875 If in that case you want to compute where the end of the window would
876 have been if redisplay had finished, do this:
878 (goto-char (window-start window))
879 (vertical-motion (1- (window-height window)) window)
882 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
883 doc
: /* Return position at which display currently ends in WINDOW.
884 This is updated by redisplay, when it runs to completion.
885 Simply changing the buffer text or setting `window-start'
886 does not update this value.
887 If UPDATE is non-nil, compute the up-to-date position
888 if it isn't already recorded. */)
890 Lisp_Object window
, update
;
893 struct window
*w
= decode_window (window
);
899 #if 0 /* This change broke some things. We should make it later. */
900 /* If we don't know the end position, return nil.
901 The user can compute it with vertical-motion if he wants to.
902 It would be nicer to do it automatically,
903 but that's so slow that it would probably bother people. */
904 if (NILP (w
->window_end_valid
))
909 && ! (! NILP (w
->window_end_valid
)
910 && XFASTINT (w
->last_modified
) >= MODIFF
))
912 struct text_pos startp
;
914 struct buffer
*old_buffer
= NULL
, *b
= XBUFFER (buf
);
916 /* In case W->start is out of the range, use something
917 reasonable. This situation occured when loading a file with
918 `-l' containing a call to `rmail' with subsequent other
919 commands. At the end, W->start happened to be BEG, while
920 rmail had already narrowed the buffer. */
921 if (XMARKER (w
->start
)->charpos
< BEGV
)
922 SET_TEXT_POS (startp
, BEGV
, BEGV_BYTE
);
923 else if (XMARKER (w
->start
)->charpos
> ZV
)
924 SET_TEXT_POS (startp
, ZV
, ZV_BYTE
);
926 SET_TEXT_POS_FROM_MARKER (startp
, w
->start
);
928 /* Cannot use Fvertical_motion because that function doesn't
929 cope with variable-height lines. */
930 if (b
!= current_buffer
)
932 old_buffer
= current_buffer
;
933 set_buffer_internal (b
);
936 start_display (&it
, w
, startp
);
937 move_it_vertically (&it
, window_box_height (w
));
938 if (it
.current_y
< it
.last_visible_y
)
939 move_it_past_eol (&it
);
940 value
= make_number (IT_CHARPOS (it
));
943 set_buffer_internal (old_buffer
);
946 XSETINT (value
, BUF_Z (XBUFFER (buf
)) - XFASTINT (w
->window_end_pos
));
951 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
952 doc
: /* Make point value in WINDOW be at position POS in WINDOW's buffer. */)
954 Lisp_Object window
, pos
;
956 register struct window
*w
= decode_window (window
);
958 CHECK_NUMBER_COERCE_MARKER (pos
);
959 if (w
== XWINDOW (selected_window
)
960 && XBUFFER (w
->buffer
) == current_buffer
)
963 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
965 /* We have to make sure that redisplay updates the window to show
966 the new value of point. */
967 if (!EQ (window
, selected_window
))
968 ++windows_or_buffers_changed
;
973 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
974 doc
: /* Make display in WINDOW start at position POS in WINDOW's buffer.
975 Optional third arg NOFORCE non-nil inhibits next redisplay
976 from overriding motion of point in order to display at this exact start. */)
977 (window
, pos
, noforce
)
978 Lisp_Object window
, pos
, noforce
;
980 register struct window
*w
= decode_window (window
);
982 CHECK_NUMBER_COERCE_MARKER (pos
);
983 set_marker_restricted (w
->start
, pos
, w
->buffer
);
984 /* this is not right, but much easier than doing what is right. */
985 w
->start_at_line_beg
= Qnil
;
988 w
->update_mode_line
= Qt
;
989 XSETFASTINT (w
->last_modified
, 0);
990 XSETFASTINT (w
->last_overlay_modified
, 0);
991 if (!EQ (window
, selected_window
))
992 windows_or_buffers_changed
++;
997 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
999 doc
: /* Return WINDOW's dedicated object, usually t or nil.
1000 See also `set-window-dedicated-p'. */)
1004 return decode_window (window
)->dedicated
;
1007 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
1008 Sset_window_dedicated_p
, 2, 2, 0,
1009 doc
: /* Control whether WINDOW is dedicated to the buffer it displays.
1010 If it is dedicated, Emacs will not automatically change
1011 which buffer appears in it.
1012 The second argument is the new value for the dedication flag;
1013 non-nil means yes. */)
1015 Lisp_Object window
, arg
;
1017 register struct window
*w
= decode_window (window
);
1020 w
->dedicated
= Qnil
;
1024 return w
->dedicated
;
1027 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1029 doc
: /* Return the display-table that WINDOW is using. */)
1033 return decode_window (window
)->display_table
;
1036 /* Get the display table for use on window W. This is either W's
1037 display table or W's buffer's display table. Ignore the specified
1038 tables if they are not valid; if no valid table is specified,
1041 struct Lisp_Char_Table
*
1042 window_display_table (w
)
1045 struct Lisp_Char_Table
*dp
= NULL
;
1047 if (DISP_TABLE_P (w
->display_table
))
1048 dp
= XCHAR_TABLE (w
->display_table
);
1049 else if (BUFFERP (w
->buffer
))
1051 struct buffer
*b
= XBUFFER (w
->buffer
);
1053 if (DISP_TABLE_P (b
->display_table
))
1054 dp
= XCHAR_TABLE (b
->display_table
);
1055 else if (DISP_TABLE_P (Vstandard_display_table
))
1056 dp
= XCHAR_TABLE (Vstandard_display_table
);
1062 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1063 doc
: /* Set WINDOW's display-table to TABLE. */)
1065 register Lisp_Object window
, table
;
1067 register struct window
*w
;
1069 w
= decode_window (window
);
1070 w
->display_table
= table
;
1074 /* Record info on buffer window w is displaying
1075 when it is about to cease to display that buffer. */
1078 register struct window
*w
;
1085 if (b
!= XMARKER (w
->pointm
)->buffer
)
1089 if (w
== XWINDOW (selected_window
)
1090 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1091 /* Do this except when the selected window's buffer
1092 is being removed from some other window. */
1094 /* last_window_start records the start position that this buffer
1095 had in the last window to be disconnected from it.
1096 Now that this statement is unconditional,
1097 it is possible for the buffer to be displayed in the
1098 selected window, while last_window_start reflects another
1099 window which was recently showing the same buffer.
1100 Some people might say that might be a good thing. Let's see. */
1101 b
->last_window_start
= marker_position (w
->start
);
1103 /* Point in the selected window's buffer
1104 is actually stored in that buffer, and the window's pointm isn't used.
1105 So don't clobber point in that buffer. */
1106 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1107 /* This line helps to fix Horsley's testbug.el bug. */
1108 && !(WINDOWP (b
->last_selected_window
)
1109 && w
!= XWINDOW (b
->last_selected_window
)
1110 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1111 temp_set_point_both (b
,
1112 clip_to_bounds (BUF_BEGV (b
),
1113 XMARKER (w
->pointm
)->charpos
,
1115 clip_to_bounds (BUF_BEGV_BYTE (b
),
1116 marker_byte_position (w
->pointm
),
1119 if (WINDOWP (b
->last_selected_window
)
1120 && w
== XWINDOW (b
->last_selected_window
))
1121 b
->last_selected_window
= Qnil
;
1124 /* Put replacement into the window structure in place of old. */
1126 replace_window (old
, replacement
)
1127 Lisp_Object old
, replacement
;
1129 register Lisp_Object tem
;
1130 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1132 /* If OLD is its frame's root_window, then replacement is the new
1133 root_window for that frame. */
1135 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1136 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1140 p
->width
= o
->width
;
1141 p
->height
= o
->height
;
1142 p
->desired_matrix
= p
->current_matrix
= 0;
1144 bzero (&p
->cursor
, sizeof (p
->cursor
));
1145 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
1146 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
1147 p
->phys_cursor_type
= -1;
1148 p
->phys_cursor_width
= -1;
1149 p
->must_be_updated_p
= 0;
1150 p
->pseudo_window_p
= 0;
1151 XSETFASTINT (p
->window_end_vpos
, 0);
1152 XSETFASTINT (p
->window_end_pos
, 0);
1153 p
->window_end_valid
= Qnil
;
1154 p
->frozen_window_start_p
= 0;
1155 p
->orig_top
= p
->orig_height
= Qnil
;
1157 p
->next
= tem
= o
->next
;
1159 XWINDOW (tem
)->prev
= replacement
;
1161 p
->prev
= tem
= o
->prev
;
1163 XWINDOW (tem
)->next
= replacement
;
1165 p
->parent
= tem
= o
->parent
;
1168 if (EQ (XWINDOW (tem
)->vchild
, old
))
1169 XWINDOW (tem
)->vchild
= replacement
;
1170 if (EQ (XWINDOW (tem
)->hchild
, old
))
1171 XWINDOW (tem
)->hchild
= replacement
;
1174 /*** Here, if replacement is a vertical combination
1175 and so is its new parent, we should make replacement's
1176 children be children of that parent instead. ***/
1179 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1180 doc
: /* Remove WINDOW from the display. Default is selected window. */)
1182 register Lisp_Object window
;
1184 delete_window (window
);
1186 if (! NILP (Vwindow_configuration_change_hook
)
1187 && ! NILP (Vrun_hooks
))
1188 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
1194 delete_window (window
)
1195 register Lisp_Object window
;
1197 register Lisp_Object tem
, parent
, sib
;
1198 register struct window
*p
;
1199 register struct window
*par
;
1202 /* Because this function is called by other C code on non-leaf
1203 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1204 so we can't decode_window here. */
1206 window
= selected_window
;
1208 CHECK_WINDOW (window
);
1209 p
= XWINDOW (window
);
1211 /* It's okay to delete an already-deleted window. */
1212 if (NILP (p
->buffer
)
1214 && NILP (p
->vchild
))
1219 error ("Attempt to delete minibuffer or sole ordinary window");
1220 par
= XWINDOW (parent
);
1222 windows_or_buffers_changed
++;
1223 Vwindow_list
= Qnil
;
1224 f
= XFRAME (WINDOW_FRAME (p
));
1225 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1227 /* Are we trying to delete any frame's selected window? */
1229 Lisp_Object swindow
, pwindow
;
1231 /* See if the frame's selected window is either WINDOW
1232 or any subwindow of it, by finding all that window's parents
1233 and comparing each one with WINDOW. */
1234 swindow
= FRAME_SELECTED_WINDOW (f
);
1239 while (!NILP (pwindow
))
1241 if (EQ (window
, pwindow
))
1243 pwindow
= XWINDOW (pwindow
)->parent
;
1246 /* If the window being deleted is not a parent of SWINDOW,
1247 then SWINDOW is ok as the new selected window. */
1248 if (!EQ (window
, pwindow
))
1250 /* Otherwise, try another window for SWINDOW. */
1251 swindow
= Fnext_window (swindow
, Qlambda
, Qnil
);;
1253 /* If we get back to the frame's selected window,
1254 it means there was no acceptable alternative,
1255 so we cannot delete. */
1256 if (EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1257 error ("Cannot delete window");
1260 /* If we need to change SWINDOW, do it. */
1261 if (! EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1263 /* If we're about to delete the selected window on the
1264 selected frame, then we should use Fselect_window to select
1265 the new window. On the other hand, if we're about to
1266 delete the selected window on any other frame, we shouldn't do
1267 anything but set the frame's selected_window slot. */
1268 if (EQ (FRAME_SELECTED_WINDOW (f
), selected_window
))
1269 Fselect_window (swindow
);
1271 FRAME_SELECTED_WINDOW (f
) = swindow
;
1276 /* tem is null for dummy parent windows
1277 (which have inferiors but not any contents themselves) */
1281 unchain_marker (p
->pointm
);
1282 unchain_marker (p
->start
);
1285 /* Free window glyph matrices. It is sure that they are allocated
1286 again when ADJUST_GLYPHS is called. Block input so that expose
1287 events and other events that access glyph matrices are not
1288 processed while we are changing them. */
1290 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1294 XWINDOW (tem
)->prev
= p
->prev
;
1298 XWINDOW (tem
)->next
= p
->next
;
1300 if (EQ (window
, par
->hchild
))
1301 par
->hchild
= p
->next
;
1302 if (EQ (window
, par
->vchild
))
1303 par
->vchild
= p
->next
;
1305 /* Find one of our siblings to give our space to. */
1309 /* If p gives its space to its next sibling, that sibling needs
1310 to have its top/left side pulled back to where p's is.
1311 set_window_{height,width} will re-position the sibling's
1314 XWINDOW (sib
)->top
= p
->top
;
1315 XWINDOW (sib
)->left
= p
->left
;
1318 /* Stretch that sibling. */
1319 if (!NILP (par
->vchild
))
1320 set_window_height (sib
,
1321 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
1323 if (!NILP (par
->hchild
))
1324 set_window_width (sib
,
1325 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
1328 /* If parent now has only one child,
1329 put the child into the parent's place. */
1333 if (NILP (XWINDOW (tem
)->next
))
1334 replace_window (parent
, tem
);
1336 /* Since we may be deleting combination windows, we must make sure that
1337 not only p but all its children have been marked as deleted. */
1338 if (! NILP (p
->hchild
))
1339 delete_all_subwindows (XWINDOW (p
->hchild
));
1340 else if (! NILP (p
->vchild
))
1341 delete_all_subwindows (XWINDOW (p
->vchild
));
1343 /* Mark this window as deleted. */
1344 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1346 /* Adjust glyph matrices. */
1353 /***********************************************************************
1355 ***********************************************************************/
1357 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1358 pointer. This is a callback function for foreach_window, used in
1359 function window_list. */
1362 add_window_to_list (w
, user_data
)
1366 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1368 XSETWINDOW (window
, w
);
1369 *list
= Fcons (window
, *list
);
1374 /* Return a list of all windows, for use by next_window. If
1375 Vwindow_list is a list, return that list. Otherwise, build a new
1376 list, cache it in Vwindow_list, and return that. */
1381 if (!CONSP (Vwindow_list
))
1385 Vwindow_list
= Qnil
;
1386 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1388 Lisp_Object args
[2];
1390 /* We are visiting windows in canonical order, and add
1391 new windows at the front of args[1], which means we
1392 have to reverse this list at the end. */
1394 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1395 args
[0] = Vwindow_list
;
1396 args
[1] = Fnreverse (args
[1]);
1397 Vwindow_list
= Fnconc (2, args
);
1401 return Vwindow_list
;
1405 /* Value is non-zero if WINDOW satisfies the constraints given by
1406 OWINDOW, MINIBUF and ALL_FRAMES.
1408 MINIBUF t means WINDOW may be minibuffer windows.
1409 `lambda' means WINDOW may not be a minibuffer window.
1410 a window means a specific minibuffer window
1412 ALL_FRAMES t means search all frames,
1413 nil means search just current frame,
1414 `visible' means search just visible frames,
1415 0 means search visible and iconified frames,
1416 a window means search the frame that window belongs to,
1417 a frame means consider windows on that frame, only. */
1420 candidate_window_p (window
, owindow
, minibuf
, all_frames
)
1421 Lisp_Object window
, owindow
, minibuf
, all_frames
;
1423 struct window
*w
= XWINDOW (window
);
1424 struct frame
*f
= XFRAME (w
->frame
);
1425 int candidate_p
= 1;
1427 if (!BUFFERP (w
->buffer
))
1429 else if (MINI_WINDOW_P (w
)
1430 && (EQ (minibuf
, Qlambda
)
1431 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1433 /* If MINIBUF is `lambda' don't consider any mini-windows.
1434 If it is a window, consider only that one. */
1437 else if (EQ (all_frames
, Qt
))
1439 else if (NILP (all_frames
))
1441 xassert (WINDOWP (owindow
));
1442 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1444 else if (EQ (all_frames
, Qvisible
))
1446 FRAME_SAMPLE_VISIBILITY (f
);
1447 candidate_p
= FRAME_VISIBLE_P (f
);
1449 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1451 FRAME_SAMPLE_VISIBILITY (f
);
1452 candidate_p
= FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
);
1454 else if (WINDOWP (all_frames
))
1455 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1456 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1457 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1458 else if (FRAMEP (all_frames
))
1459 candidate_p
= EQ (all_frames
, w
->frame
);
1465 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1466 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1470 decode_next_window_args (window
, minibuf
, all_frames
)
1471 Lisp_Object
*window
, *minibuf
, *all_frames
;
1474 *window
= selected_window
;
1476 CHECK_LIVE_WINDOW (*window
);
1478 /* MINIBUF nil may or may not include minibuffers. Decide if it
1480 if (NILP (*minibuf
))
1481 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1482 else if (!EQ (*minibuf
, Qt
))
1485 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1486 => count none of them, or a specific minibuffer window (the
1487 active one) to count. */
1489 /* ALL_FRAMES nil doesn't specify which frames to include. */
1490 if (NILP (*all_frames
))
1491 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1492 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1494 else if (EQ (*all_frames
, Qvisible
))
1496 else if (XFASTINT (*all_frames
) == 0)
1498 else if (FRAMEP (*all_frames
))
1500 else if (!EQ (*all_frames
, Qt
))
1503 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1504 search just current frame, `visible' meaning search just visible
1505 frames, 0 meaning search visible and iconified frames, or a
1506 window, meaning search the frame that window belongs to, or a
1507 frame, meaning consider windows on that frame, only. */
1511 /* Return the next or previous window of WINDOW in canonical ordering
1512 of windows. NEXT_P non-zero means return the next window. See the
1513 documentation string of next-window for the meaning of MINIBUF and
1517 next_window (window
, minibuf
, all_frames
, next_p
)
1518 Lisp_Object window
, minibuf
, all_frames
;
1521 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1523 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1524 return the first window on the frame. */
1525 if (FRAMEP (all_frames
)
1526 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1527 return Fframe_first_window (all_frames
);
1533 /* Find WINDOW in the list of all windows. */
1534 list
= Fmemq (window
, window_list ());
1536 /* Scan forward from WINDOW to the end of the window list. */
1538 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1539 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1542 /* Scan from the start of the window list up to WINDOW. */
1544 for (list
= Vwindow_list
;
1545 CONSP (list
) && !EQ (XCAR (list
), window
);
1547 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1551 window
= XCAR (list
);
1555 Lisp_Object candidate
, list
;
1557 /* Scan through the list of windows for candidates. If there are
1558 candidate windows in front of WINDOW, the last one of these
1559 is the one we want. If there are candidates following WINDOW
1560 in the list, again the last one of these is the one we want. */
1562 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
1564 if (EQ (XCAR (list
), window
))
1566 if (WINDOWP (candidate
))
1569 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
1571 candidate
= XCAR (list
);
1574 if (WINDOWP (candidate
))
1582 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
1583 doc
: /* Return next window after WINDOW in canonical ordering of windows.
1584 If omitted, WINDOW defaults to the selected window.
1586 Optional second arg MINIBUF t means count the minibuffer window even
1587 if not active. MINIBUF nil or omitted means count the minibuffer iff
1588 it is active. MINIBUF neither t nor nil means not to count the
1589 minibuffer even if it is active.
1591 Several frames may share a single minibuffer; if the minibuffer
1592 counts, all windows on all frames that share that minibuffer count
1593 too. Therefore, `next-window' can be used to iterate through the
1594 set of windows even when the minibuffer is on another frame. If the
1595 minibuffer does not count, only windows from WINDOW's frame count.
1597 Optional third arg ALL-FRAMES t means include windows on all frames.
1598 ALL-FRAMES nil or omitted means cycle within the frames as specified
1599 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1600 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1601 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1602 Anything else means restrict to WINDOW's frame.
1604 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1605 `next-window' to iterate through the entire cycle of acceptable
1606 windows, eventually ending up back at the window you started with.
1607 `previous-window' traverses the same cycle, in the reverse order. */)
1608 (window
, minibuf
, all_frames
)
1609 Lisp_Object window
, minibuf
, all_frames
;
1611 return next_window (window
, minibuf
, all_frames
, 1);
1615 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
1616 doc
: /* Return the window preceding WINDOW in canonical ordering of windows.
1617 If omitted, WINDOW defaults to the selected window.
1619 Optional second arg MINIBUF t means count the minibuffer window even
1620 if not active. MINIBUF nil or omitted means count the minibuffer iff
1621 it is active. MINIBUF neither t nor nil means not to count the
1622 minibuffer even if it is active.
1624 Several frames may share a single minibuffer; if the minibuffer
1625 counts, all windows on all frames that share that minibuffer count
1626 too. Therefore, `previous-window' can be used to iterate through
1627 the set of windows even when the minibuffer is on another frame. If
1628 the minibuffer does not count, only windows from WINDOW's frame count
1630 Optional third arg ALL-FRAMES t means include windows on all frames.
1631 ALL-FRAMES nil or omitted means cycle within the frames as specified
1632 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1633 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1634 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1635 Anything else means restrict to WINDOW's frame.
1637 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1638 `previous-window' to iterate through the entire cycle of acceptable
1639 windows, eventually ending up back at the window you started with.
1640 `next-window' traverses the same cycle, in the reverse order. */)
1641 (window
, minibuf
, all_frames
)
1642 Lisp_Object window
, minibuf
, all_frames
;
1644 return next_window (window
, minibuf
, all_frames
, 0);
1648 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
1649 doc
: /* Select the ARG'th different window on this frame.
1650 All windows on current frame are arranged in a cyclic order.
1651 This command selects the window ARG steps away in that order.
1652 A negative ARG moves in the opposite order. If the optional second
1653 argument ALL_FRAMES is non-nil, cycle through all frames. */)
1655 Lisp_Object arg
, all_frames
;
1661 window
= selected_window
;
1663 for (i
= XINT (arg
); i
> 0; --i
)
1664 window
= Fnext_window (window
, Qnil
, all_frames
);
1666 window
= Fprevious_window (window
, Qnil
, all_frames
);
1668 Fselect_window (window
);
1673 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
1674 doc
: /* Return a list of windows on FRAME, starting with WINDOW.
1675 FRAME nil or omitted means use the selected frame.
1676 WINDOW nil or omitted means use the selected window.
1677 MINIBUF t means include the minibuffer window, even if it isn't active.
1678 MINIBUF nil or omitted means include the minibuffer window only
1680 MINIBUF neither nil nor t means never include the minibuffer window. */)
1681 (frame
, minibuf
, window
)
1682 Lisp_Object frame
, minibuf
, window
;
1685 window
= selected_window
;
1687 frame
= selected_frame
;
1689 if (!EQ (frame
, XWINDOW (window
)->frame
))
1690 error ("Window is on a different frame");
1692 return window_list_1 (window
, minibuf
, frame
);
1696 /* Return a list of windows in canonical ordering. Arguments are like
1697 for `next-window'. */
1700 window_list_1 (window
, minibuf
, all_frames
)
1701 Lisp_Object window
, minibuf
, all_frames
;
1703 Lisp_Object tail
, list
;
1705 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1708 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
1709 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
1710 list
= Fcons (XCAR (tail
), list
);
1712 return Fnreverse (list
);
1717 /* Look at all windows, performing an operation specified by TYPE
1719 If FRAMES is Qt, look at all frames;
1720 Qnil, look at just the selected frame;
1721 Qvisible, look at visible frames;
1722 a frame, just look at windows on that frame.
1723 If MINI is non-zero, perform the operation on minibuffer windows too. */
1728 GET_BUFFER_WINDOW
, /* Arg is buffer */
1729 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
1730 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
1731 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
1733 UNSHOW_BUFFER
, /* Arg is buffer */
1738 window_loop (type
, obj
, mini
, frames
)
1739 enum window_loop type
;
1740 Lisp_Object obj
, frames
;
1743 Lisp_Object window
, windows
, best_window
, frame_arg
;
1745 struct gcpro gcpro1
;
1747 /* If we're only looping through windows on a particular frame,
1748 frame points to that frame. If we're looping through windows
1749 on all frames, frame is 0. */
1750 if (FRAMEP (frames
))
1751 f
= XFRAME (frames
);
1752 else if (NILP (frames
))
1753 f
= SELECTED_FRAME ();
1758 frame_arg
= Qlambda
;
1759 else if (XFASTINT (frames
) == 0)
1761 else if (EQ (frames
, Qvisible
))
1766 /* frame_arg is Qlambda to stick to one frame,
1767 Qvisible to consider all visible frames,
1770 /* Pick a window to start with. */
1774 window
= FRAME_SELECTED_WINDOW (f
);
1776 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1778 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
1782 for (; CONSP (windows
); windows
= CDR (windows
))
1786 window
= XCAR (windows
);
1787 w
= XWINDOW (window
);
1789 /* Note that we do not pay attention here to whether the frame
1790 is visible, since Fwindow_list skips non-visible frames if
1791 that is desired, under the control of frame_arg. */
1792 if (!MINI_WINDOW_P (w
)
1793 /* For UNSHOW_BUFFER, we must always consider all windows. */
1794 || type
== UNSHOW_BUFFER
1795 || (mini
&& minibuf_level
> 0))
1798 case GET_BUFFER_WINDOW
:
1799 if (EQ (w
->buffer
, obj
)
1800 /* Don't find any minibuffer window
1801 except the one that is currently in use. */
1802 && (MINI_WINDOW_P (w
)
1803 ? EQ (window
, minibuf_window
)
1806 if (NILP (best_window
))
1807 best_window
= window
;
1808 else if (EQ (window
, selected_window
))
1809 /* For compatibility with 20.x, prefer to return
1811 best_window
= window
;
1815 case GET_LRU_WINDOW
:
1816 /* t as arg means consider only full-width windows */
1817 if (!NILP (obj
) && !WINDOW_FULL_WIDTH_P (w
))
1819 /* Ignore dedicated windows and minibuffers. */
1820 if (MINI_WINDOW_P (w
) || !NILP (w
->dedicated
))
1822 if (NILP (best_window
)
1823 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1824 > XFASTINT (w
->use_time
)))
1825 best_window
= window
;
1828 case DELETE_OTHER_WINDOWS
:
1829 if (!EQ (window
, obj
))
1830 Fdelete_window (window
);
1833 case DELETE_BUFFER_WINDOWS
:
1834 if (EQ (w
->buffer
, obj
))
1836 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1838 /* If this window is dedicated, and in a frame of its own,
1840 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
1841 && !NILP (w
->dedicated
)
1842 && other_visible_frames (f
))
1844 /* Skip the other windows on this frame.
1845 There might be one, the minibuffer! */
1846 while (CONSP (XCDR (windows
))
1847 && EQ (XWINDOW (XCAR (windows
))->frame
,
1848 XWINDOW (XCAR (XCDR (windows
)))->frame
))
1849 windows
= XCDR (windows
);
1851 /* Now we can safely delete the frame. */
1852 Fdelete_frame (w
->frame
, Qnil
);
1854 else if (NILP (w
->parent
))
1856 /* If we're deleting the buffer displayed in the
1857 only window on the frame, find a new buffer to
1860 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
1861 Fset_window_buffer (window
, buffer
);
1862 if (EQ (window
, selected_window
))
1863 Fset_buffer (w
->buffer
);
1866 Fdelete_window (window
);
1870 case GET_LARGEST_WINDOW
:
1872 /* Ignore dedicated windows and minibuffers. */
1873 if (MINI_WINDOW_P (w
) || !NILP (w
->dedicated
))
1876 if (NILP (best_window
))
1877 best_window
= window
;
1880 struct window
*b
= XWINDOW (best_window
);
1881 if (XFASTINT (w
->height
) * XFASTINT (w
->width
)
1882 > XFASTINT (b
->height
) * XFASTINT (b
->width
))
1883 best_window
= window
;
1889 if (EQ (w
->buffer
, obj
))
1892 struct frame
*f
= XFRAME (w
->frame
);
1894 /* Find another buffer to show in this window. */
1895 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
1897 /* If this window is dedicated, and in a frame of its own,
1899 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
1900 && !NILP (w
->dedicated
)
1901 && other_visible_frames (f
))
1903 /* Skip the other windows on this frame.
1904 There might be one, the minibuffer! */
1905 while (CONSP (XCDR (windows
))
1906 && EQ (XWINDOW (XCAR (windows
))->frame
,
1907 XWINDOW (XCAR (XCDR (windows
)))->frame
))
1908 windows
= XCDR (windows
);
1910 /* Now we can safely delete the frame. */
1911 Fdelete_frame (w
->frame
, Qnil
);
1915 /* Otherwise show a different buffer in the window. */
1916 w
->dedicated
= Qnil
;
1917 Fset_window_buffer (window
, buffer
);
1918 if (EQ (window
, selected_window
))
1919 Fset_buffer (w
->buffer
);
1924 /* Check for a window that has a killed buffer. */
1925 case CHECK_ALL_WINDOWS
:
1926 if (! NILP (w
->buffer
)
1927 && NILP (XBUFFER (w
->buffer
)->name
))
1931 case WINDOW_LOOP_UNUSED
:
1940 /* Used for debugging. Abort if any window has a dead buffer. */
1943 check_all_windows ()
1945 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
1948 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1949 doc
: /* Return the window least recently selected or used for display.
1950 If optional argument FRAME is `visible', search all visible frames.
1951 If FRAME is 0, search all visible and iconified frames.
1952 If FRAME is t, search all frames.
1953 If FRAME is nil, search only the selected frame.
1954 If FRAME is a frame, search only that frame. */)
1958 register Lisp_Object w
;
1959 /* First try for a window that is full-width */
1960 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, frame
);
1961 if (!NILP (w
) && !EQ (w
, selected_window
))
1963 /* If none of them, try the rest */
1964 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, frame
);
1967 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1968 doc
: /* Return the largest window in area.
1969 If optional argument FRAME is `visible', search all visible frames.
1970 If FRAME is 0, search all visible and iconified frames.
1971 If FRAME is t, search all frames.
1972 If FRAME is nil, search only the selected frame.
1973 If FRAME is a frame, search only that frame. */)
1977 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1981 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1982 doc
: /* Return a window currently displaying BUFFER, or nil if none.
1983 If optional argument FRAME is `visible', search all visible frames.
1984 If optional argument FRAME is 0, search all visible and iconified frames.
1985 If FRAME is t, search all frames.
1986 If FRAME is nil, search only the selected frame.
1987 If FRAME is a frame, search only that frame. */)
1989 Lisp_Object buffer
, frame
;
1991 buffer
= Fget_buffer (buffer
);
1992 if (BUFFERP (buffer
))
1993 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
1998 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
2000 doc
: /* Make WINDOW (or the selected window) fill its frame.
2001 Only the frame WINDOW is on is affected.
2002 This function tries to reduce display jumps
2003 by keeping the text previously visible in WINDOW
2004 in the same place on the frame. Doing this depends on
2005 the value of (window-start WINDOW), so if calling this function
2006 in a program gives strange scrolling, make sure the window-start
2007 value is reasonable when this function is called. */)
2016 window
= selected_window
;
2018 CHECK_LIVE_WINDOW (window
);
2019 w
= XWINDOW (window
);
2021 startpos
= marker_position (w
->start
);
2022 top
= XFASTINT (w
->top
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2024 if (MINI_WINDOW_P (w
) && top
> 0)
2025 error ("Can't expand minibuffer to full frame");
2027 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2029 /* Try to minimize scrolling, by setting the window start to the point
2030 will cause the text at the old window start to be at the same place
2031 on the frame. But don't try to do this if the window start is
2032 outside the visible portion (as might happen when the display is
2033 not current, due to typeahead). */
2034 new_top
= XFASTINT (w
->top
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2036 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2037 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2039 struct position pos
;
2040 struct buffer
*obuf
= current_buffer
;
2042 Fset_buffer (w
->buffer
);
2043 /* This computation used to temporarily move point, but that can
2044 have unwanted side effects due to text properties. */
2045 pos
= *vmotion (startpos
, -top
, w
);
2047 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2048 w
->window_end_valid
= Qnil
;
2049 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2050 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2052 /* We need to do this, so that the window-scroll-functions
2054 w
->optional_new_start
= Qt
;
2056 set_buffer_internal (obuf
);
2062 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2063 1, 2, "bDelete windows on (buffer): ",
2064 doc
: /* Delete all windows showing BUFFER.
2065 Optional second argument FRAME controls which frames are affected.
2066 If optional argument FRAME is `visible', search all visible frames.
2067 If FRAME is 0, search all visible and iconified frames.
2068 If FRAME is nil, search all frames.
2069 If FRAME is t, search only the selected frame.
2070 If FRAME is a frame, search only that frame. */)
2072 Lisp_Object buffer
, frame
;
2074 /* FRAME uses t and nil to mean the opposite of what window_loop
2078 else if (EQ (frame
, Qt
))
2083 buffer
= Fget_buffer (buffer
);
2084 CHECK_BUFFER (buffer
);
2085 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2091 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2092 Sreplace_buffer_in_windows
,
2093 1, 1, "bReplace buffer in windows: ",
2094 doc
: /* Replace BUFFER with some other buffer in all windows showing it. */)
2100 buffer
= Fget_buffer (buffer
);
2101 CHECK_BUFFER (buffer
);
2102 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2107 /* Replace BUFFER with some other buffer in all windows
2108 of all frames, even those on other keyboards. */
2111 replace_buffer_in_all_windows (buffer
)
2115 Lisp_Object tail
, frame
;
2117 /* A single call to window_loop won't do the job
2118 because it only considers frames on the current keyboard.
2119 So loop manually over frames, and handle each one. */
2120 FOR_EACH_FRAME (tail
, frame
)
2121 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2123 window_loop (UNSHOW_BUFFER
, buffer
, 1, Qt
);
2127 /* Set the height of WINDOW and all its inferiors. */
2129 /* The smallest acceptable dimensions for a window. Anything smaller
2130 might crash Emacs. */
2132 #define MIN_SAFE_WINDOW_WIDTH (2)
2133 #define MIN_SAFE_WINDOW_HEIGHT (1)
2135 /* Make sure that window_min_height and window_min_width are
2136 not too small; if they are, set them to safe minima. */
2139 check_min_window_sizes ()
2141 /* Smaller values might permit a crash. */
2142 if (window_min_width
< MIN_SAFE_WINDOW_WIDTH
)
2143 window_min_width
= MIN_SAFE_WINDOW_WIDTH
;
2144 if (window_min_height
< MIN_SAFE_WINDOW_HEIGHT
)
2145 window_min_height
= MIN_SAFE_WINDOW_HEIGHT
;
2148 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2149 minimum allowable size. */
2152 check_frame_size (frame
, rows
, cols
)
2156 /* For height, we have to see:
2157 how many windows the frame has at minimum (one or two),
2158 and whether it has a menu bar or other special stuff at the top. */
2160 = ((FRAME_MINIBUF_ONLY_P (frame
) || ! FRAME_HAS_MINIBUF_P (frame
))
2161 ? MIN_SAFE_WINDOW_HEIGHT
2162 : 2 * MIN_SAFE_WINDOW_HEIGHT
);
2164 if (FRAME_TOP_MARGIN (frame
) > 0)
2165 min_height
+= FRAME_TOP_MARGIN (frame
);
2167 if (*rows
< min_height
)
2169 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2170 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2174 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2175 check if W's width can be changed, otherwise check W's height.
2176 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2177 siblings, too. If none of the siblings is resizable, WINDOW isn't
2181 window_fixed_size_p (w
, width_p
, check_siblings_p
)
2183 int width_p
, check_siblings_p
;
2188 if (!NILP (w
->hchild
))
2190 c
= XWINDOW (w
->hchild
);
2194 /* A horiz. combination is fixed-width if all of if its
2196 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2197 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2198 fixed_p
= c
== NULL
;
2202 /* A horiz. combination is fixed-height if one of if its
2204 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2205 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2206 fixed_p
= c
!= NULL
;
2209 else if (!NILP (w
->vchild
))
2211 c
= XWINDOW (w
->vchild
);
2215 /* A vert. combination is fixed-width if one of if its
2217 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2218 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2219 fixed_p
= c
!= NULL
;
2223 /* A vert. combination is fixed-height if all of if its
2225 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2226 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2227 fixed_p
= c
== NULL
;
2230 else if (BUFFERP (w
->buffer
))
2232 if (w
->height_fixed_p
&& !width_p
)
2236 struct buffer
*old
= current_buffer
;
2239 current_buffer
= XBUFFER (w
->buffer
);
2240 val
= find_symbol_value (Qwindow_size_fixed
);
2241 current_buffer
= old
;
2244 if (!EQ (val
, Qunbound
))
2246 fixed_p
= !NILP (val
);
2249 && ((EQ (val
, Qheight
) && width_p
)
2250 || (EQ (val
, Qwidth
) && !width_p
)))
2255 /* Can't tell if this one is resizable without looking at
2256 siblings. If all siblings are fixed-size this one is too. */
2257 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2261 for (child
= w
->prev
; !NILP (child
); child
= XWINDOW (child
)->prev
)
2262 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2266 for (child
= w
->next
; !NILP (child
); child
= XWINDOW (child
)->next
)
2267 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2281 /* Return the minimum size of window W, not taking fixed-width windows
2282 into account. WIDTH_P non-zero means return the minimum width,
2283 otherwise return the minimum height. If W is a combination window,
2284 compute the minimum size from the minimum sizes of W's children. */
2287 window_min_size_1 (w
, width_p
)
2294 if (!NILP (w
->hchild
))
2296 c
= XWINDOW (w
->hchild
);
2301 /* The min width of a horizontal combination is
2302 the sum of the min widths of its children. */
2305 size
+= window_min_size_1 (c
, width_p
);
2306 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2311 /* The min height a horizontal combination equals
2312 the maximum of all min height of its children. */
2315 int min_size
= window_min_size_1 (c
, width_p
);
2316 size
= max (min_size
, size
);
2317 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2321 else if (!NILP (w
->vchild
))
2323 c
= XWINDOW (w
->vchild
);
2328 /* The min width of a vertical combination is
2329 the maximum of the min widths of its children. */
2332 int min_size
= window_min_size_1 (c
, width_p
);
2333 size
= max (min_size
, size
);
2334 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2339 /* The min height of a vertical combination equals
2340 the sum of the min height of its children. */
2343 size
+= window_min_size_1 (c
, width_p
);
2344 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2351 size
= window_min_width
;
2354 if (MINI_WINDOW_P (w
)
2355 || (!WINDOW_WANTS_MODELINE_P (w
)
2356 && !WINDOW_WANTS_HEADER_LINE_P (w
)))
2359 size
= window_min_height
;
2367 /* Return the minimum size of window W, taking fixed-size windows into
2368 account. WIDTH_P non-zero means return the minimum width,
2369 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2370 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2371 unless FIXED is null. */
2374 window_min_size (w
, width_p
, ignore_fixed_p
, fixed
)
2376 int width_p
, ignore_fixed_p
, *fixed
;
2383 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2389 size
= width_p
? XFASTINT (w
->width
) : XFASTINT (w
->height
);
2391 size
= window_min_size_1 (w
, width_p
);
2397 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2398 WINDOW's width. Resize WINDOW's children, if any, so that they
2399 keep their proportionate size relative to WINDOW. Propagate
2400 WINDOW's top or left edge position to children. Delete windows
2401 that become too small unless NODELETE_P is non-zero.
2403 If NODELETE_P is 2, that means we do delete windows that are
2404 too small, even if they were too small before! */
2407 size_window (window
, size
, width_p
, nodelete_p
)
2409 int size
, width_p
, nodelete_p
;
2411 struct window
*w
= XWINDOW (window
);
2413 Lisp_Object child
, *forward
, *sideward
;
2414 int old_size
, min_size
;
2416 if (nodelete_p
== 2)
2419 check_min_window_sizes ();
2420 size
= max (0, size
);
2422 /* If the window has been "too small" at one point,
2423 don't delete it for being "too small" in the future.
2424 Preserve it as long as that is at all possible. */
2427 old_size
= XINT (w
->width
);
2428 min_size
= window_min_width
;
2432 old_size
= XINT (w
->height
);
2433 min_size
= window_min_height
;
2436 if (old_size
< min_size
&& nodelete_p
!= 2)
2437 w
->too_small_ok
= Qt
;
2439 /* Maybe delete WINDOW if it's too small. */
2440 if (nodelete_p
!= 1 && !NILP (w
->parent
))
2442 if (!MINI_WINDOW_P (w
) && !NILP (w
->too_small_ok
))
2443 min_size
= width_p
? MIN_SAFE_WINDOW_WIDTH
: MIN_SAFE_WINDOW_HEIGHT
;
2445 min_size
= width_p
? window_min_width
: window_min_height
;
2447 if (size
< min_size
)
2449 delete_window (window
);
2454 /* Set redisplay hints. */
2455 w
->last_modified
= make_number (0);
2456 w
->last_overlay_modified
= make_number (0);
2457 windows_or_buffers_changed
++;
2458 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
2462 sideward
= &w
->vchild
;
2463 forward
= &w
->hchild
;
2464 w
->width
= make_number (size
);
2468 sideward
= &w
->hchild
;
2469 forward
= &w
->vchild
;
2470 w
->height
= make_number (size
);
2471 w
->orig_height
= Qnil
;
2474 if (!NILP (*sideward
))
2476 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
2478 c
= XWINDOW (child
);
2483 size_window (child
, size
, width_p
, nodelete_p
);
2486 else if (!NILP (*forward
))
2488 int fixed_size
, each
, extra
, n
;
2489 int resize_fixed_p
, nfixed
;
2490 int last_pos
, first_pos
, nchildren
, total
;
2492 /* Determine the fixed-size portion of the this window, and the
2493 number of child windows. */
2494 fixed_size
= nchildren
= nfixed
= total
= 0;
2495 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
2499 c
= XWINDOW (child
);
2500 child_size
= width_p
? XINT (c
->width
) : XINT (c
->height
);
2501 total
+= child_size
;
2503 if (window_fixed_size_p (c
, width_p
, 0))
2505 fixed_size
+= child_size
;
2510 /* If the new size is smaller than fixed_size, or if there
2511 aren't any resizable windows, allow resizing fixed-size
2513 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
2515 /* Compute how many lines/columns to add to each child. The
2516 value of extra takes care of rounding errors. */
2517 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
2518 each
= (size
- total
) / n
;
2519 extra
= (size
- total
) - n
* each
;
2521 /* Compute new children heights and edge positions. */
2522 first_pos
= width_p
? XINT (w
->left
) : XINT (w
->top
);
2523 last_pos
= first_pos
;
2524 for (child
= *forward
; !NILP (child
); child
= c
->next
)
2526 int new_size
, old_size
;
2528 c
= XWINDOW (child
);
2529 old_size
= width_p
? XFASTINT (c
->width
) : XFASTINT (c
->height
);
2530 new_size
= old_size
;
2532 /* The top or left edge position of this child equals the
2533 bottom or right edge of its predecessor. */
2535 c
->left
= make_number (last_pos
);
2537 c
->top
= make_number (last_pos
);
2539 /* If this child can be resized, do it. */
2540 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
2542 new_size
= old_size
+ each
+ extra
;
2546 /* Set new height. Note that size_window also propagates
2547 edge positions to children, so it's not a no-op if we
2548 didn't change the child's size. */
2549 size_window (child
, new_size
, width_p
, 1);
2551 /* Remember the bottom/right edge position of this child; it
2552 will be used to set the top/left edge of the next child. */
2553 last_pos
+= new_size
;
2556 /* We should have covered the parent exactly with child windows. */
2557 xassert (size
== last_pos
- first_pos
);
2559 /* Now delete any children that became too small. */
2561 for (child
= *forward
; !NILP (child
); child
= c
->next
)
2564 c
= XWINDOW (child
);
2565 child_size
= width_p
? XINT (c
->width
) : XINT (c
->height
);
2566 size_window (child
, child_size
, width_p
, 2);
2571 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2572 WINDOW's children. NODELETE non-zero means don't delete windows
2573 that become too small in the process. (The caller should check
2574 later and do so if appropriate.) */
2577 set_window_height (window
, height
, nodelete
)
2582 size_window (window
, height
, 0, nodelete
);
2586 /* Set WINDOW's width to WIDTH, and recursively change the width of
2587 WINDOW's children. NODELETE non-zero means don't delete windows
2588 that become too small in the process. (The caller should check
2589 later and do so if appropriate.) */
2592 set_window_width (window
, width
, nodelete
)
2597 size_window (window
, width
, 1, nodelete
);
2601 int window_select_count
;
2604 Fset_window_buffer_unwind (obuf
)
2612 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2613 means it's allowed to run hooks. See make_frame for a case where
2614 it's not allowed. */
2617 set_window_buffer (window
, buffer
, run_hooks_p
)
2618 Lisp_Object window
, buffer
;
2621 struct window
*w
= XWINDOW (window
);
2622 struct buffer
*b
= XBUFFER (buffer
);
2623 int count
= specpdl_ptr
- specpdl
;
2627 if (EQ (window
, selected_window
))
2628 b
->last_selected_window
= window
;
2630 /* Update time stamps of buffer display. */
2631 if (INTEGERP (b
->display_count
))
2632 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
2633 b
->display_time
= Fcurrent_time ();
2635 XSETFASTINT (w
->window_end_pos
, 0);
2636 XSETFASTINT (w
->window_end_vpos
, 0);
2637 bzero (&w
->last_cursor
, sizeof w
->last_cursor
);
2638 w
->window_end_valid
= Qnil
;
2639 w
->hscroll
= w
->min_hscroll
= make_number (0);
2641 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
2642 set_marker_restricted (w
->start
,
2643 make_number (b
->last_window_start
),
2645 w
->start_at_line_beg
= Qnil
;
2646 w
->force_start
= Qnil
;
2647 XSETFASTINT (w
->last_modified
, 0);
2648 XSETFASTINT (w
->last_overlay_modified
, 0);
2649 windows_or_buffers_changed
++;
2651 /* We must select BUFFER for running the window-scroll-functions.
2652 If WINDOW is selected, switch permanently.
2653 Otherwise, switch but go back to the ambient buffer afterward. */
2654 if (EQ (window
, selected_window
))
2655 Fset_buffer (buffer
);
2656 /* We can't check ! NILP (Vwindow_scroll_functions) here
2657 because that might itself be a local variable. */
2658 else if (window_initialized
)
2660 record_unwind_protect (Fset_window_buffer_unwind
, Fcurrent_buffer ());
2661 Fset_buffer (buffer
);
2664 /* Set left and right marginal area width from buffer. */
2665 Fset_window_margins (window
, b
->left_margin_width
, b
->right_margin_width
);
2669 if (! NILP (Vwindow_scroll_functions
))
2670 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
2671 Fmarker_position (w
->start
));
2673 if (! NILP (Vwindow_configuration_change_hook
)
2674 && ! NILP (Vrun_hooks
))
2675 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
2678 unbind_to (count
, Qnil
);
2682 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
2683 doc
: /* Make WINDOW display BUFFER as its contents.
2684 BUFFER can be a buffer or buffer name. */)
2686 register Lisp_Object window
, buffer
;
2688 register Lisp_Object tem
;
2689 register struct window
*w
= decode_window (window
);
2691 XSETWINDOW (window
, w
);
2692 buffer
= Fget_buffer (buffer
);
2693 CHECK_BUFFER (buffer
);
2695 if (NILP (XBUFFER (buffer
)->name
))
2696 error ("Attempt to display deleted buffer");
2700 error ("Window is deleted");
2701 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
2702 is first being set up. */
2704 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
2705 error ("Window is dedicated to `%s'",
2706 XSTRING (XBUFFER (tem
)->name
)->data
);
2711 set_window_buffer (window
, buffer
, 1);
2715 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
2716 doc
: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
2717 If WINDOW is not already selected, also make WINDOW's buffer current.
2718 Note that the main editor command loop
2719 selects the buffer of the selected window before each command. */)
2721 register Lisp_Object window
;
2723 return select_window_1 (window
, 1);
2726 /* Note that selected_window can be nil
2727 when this is called from Fset_window_configuration. */
2730 select_window_1 (window
, recordflag
)
2731 register Lisp_Object window
;
2734 register struct window
*w
;
2735 register struct window
*ow
;
2738 CHECK_LIVE_WINDOW (window
);
2740 w
= XWINDOW (window
);
2741 w
->frozen_window_start_p
= 0;
2743 XSETFASTINT (w
->use_time
, ++window_select_count
);
2744 if (EQ (window
, selected_window
))
2747 if (!NILP (selected_window
))
2749 ow
= XWINDOW (selected_window
);
2750 if (! NILP (ow
->buffer
))
2751 set_marker_both (ow
->pointm
, ow
->buffer
,
2752 BUF_PT (XBUFFER (ow
->buffer
)),
2753 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
2756 selected_window
= window
;
2757 sf
= SELECTED_FRAME ();
2758 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
2760 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
2761 /* Use this rather than Fhandle_switch_frame
2762 so that FRAME_FOCUS_FRAME is moved appropriately as we
2763 move around in the state where a minibuffer in a separate
2765 Fselect_frame (WINDOW_FRAME (w
), Qnil
);
2768 sf
->selected_window
= window
;
2771 record_buffer (w
->buffer
);
2772 Fset_buffer (w
->buffer
);
2774 XBUFFER (w
->buffer
)->last_selected_window
= window
;
2776 /* Go to the point recorded in the window.
2777 This is important when the buffer is in more
2778 than one window. It also matters when
2779 redisplay_window has altered point after scrolling,
2780 because it makes the change only in the window. */
2782 register int new_point
= marker_position (w
->pointm
);
2783 if (new_point
< BEGV
)
2785 else if (new_point
> ZV
)
2791 windows_or_buffers_changed
++;
2795 /* Deiconify the frame containing the window WINDOW,
2796 unless it is the selected frame;
2799 The reason for the exception for the selected frame
2800 is that it seems better not to change the selected frames visibility
2801 merely because of displaying a different buffer in it.
2802 The deiconification is useful when a buffer gets shown in
2803 another frame that you were not using lately. */
2806 display_buffer_1 (window
)
2809 Lisp_Object frame
= XWINDOW (window
)->frame
;
2810 FRAME_PTR f
= XFRAME (frame
);
2812 FRAME_SAMPLE_VISIBILITY (f
);
2814 if (!EQ (frame
, selected_frame
))
2816 if (FRAME_ICONIFIED_P (f
))
2817 Fmake_frame_visible (frame
);
2818 else if (FRAME_VISIBLE_P (f
))
2819 Fraise_frame (frame
);
2825 DEFUN ("special-display-p", Fspecial_display_p
, Sspecial_display_p
, 1, 1, 0,
2826 doc
: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
2827 The value is actually t if the frame should be called with default frame
2828 parameters, and a list of frame parameters if they were specified.
2829 See `special-display-buffer-names', and `special-display-regexps'. */)
2831 Lisp_Object buffer_name
;
2835 CHECK_STRING (buffer_name
);
2837 tem
= Fmember (buffer_name
, Vspecial_display_buffer_names
);
2841 tem
= Fassoc (buffer_name
, Vspecial_display_buffer_names
);
2845 for (tem
= Vspecial_display_regexps
; CONSP (tem
); tem
= XCDR (tem
))
2847 Lisp_Object car
= XCAR (tem
);
2849 && fast_string_match (car
, buffer_name
) >= 0)
2851 else if (CONSP (car
)
2852 && STRINGP (XCAR (car
))
2853 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
2859 DEFUN ("same-window-p", Fsame_window_p
, Ssame_window_p
, 1, 1, 0,
2860 doc
: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
2861 See `same-window-buffer-names' and `same-window-regexps'. */)
2863 Lisp_Object buffer_name
;
2867 CHECK_STRING (buffer_name
);
2869 tem
= Fmember (buffer_name
, Vsame_window_buffer_names
);
2873 tem
= Fassoc (buffer_name
, Vsame_window_buffer_names
);
2877 for (tem
= Vsame_window_regexps
; CONSP (tem
); tem
= XCDR (tem
))
2879 Lisp_Object car
= XCAR (tem
);
2881 && fast_string_match (car
, buffer_name
) >= 0)
2883 else if (CONSP (car
)
2884 && STRINGP (XCAR (car
))
2885 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
2891 /* Use B so the default is (other-buffer). */
2892 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 3,
2893 "BDisplay buffer: \nP",
2894 doc
: /* Make BUFFER appear in some window but don't select it.
2895 BUFFER can be a buffer or a buffer name.
2896 If BUFFER is shown already in some window, just use that one,
2897 unless the window is the selected window and the optional second
2898 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
2899 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
2900 Returns the window displaying BUFFER.
2901 If `display-reuse-frames' is non-nil, and another frame is currently
2902 displaying BUFFER, then simply raise that frame.
2904 The variables `special-display-buffer-names', `special-display-regexps',
2905 `same-window-buffer-names', and `same-window-regexps' customize how certain
2906 buffer names are handled.
2908 If optional argument FRAME is `visible', search all visible frames.
2909 If FRAME is 0, search all visible and iconified frames.
2910 If FRAME is t, search all frames.
2911 If FRAME is a frame, search only that frame.
2912 If FRAME is nil, search only the selected frame
2913 (actually the last nonminibuffer frame),
2914 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
2915 which means search visible and iconified frames.
2917 If `even-window-heights' is non-nil, window heights will be evened out
2918 if displaying the buffer causes two vertically adjacent windows to be
2920 (buffer
, not_this_window
, frame
)
2921 register Lisp_Object buffer
, not_this_window
, frame
;
2923 register Lisp_Object window
, tem
, swp
;
2927 buffer
= Fget_buffer (buffer
);
2928 CHECK_BUFFER (buffer
);
2930 if (!NILP (Vdisplay_buffer_function
))
2931 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
2933 if (NILP (not_this_window
)
2934 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
2935 return display_buffer_1 (selected_window
);
2937 /* See if the user has specified this buffer should appear
2938 in the selected window. */
2939 if (NILP (not_this_window
))
2941 swp
= Fsame_window_p (XBUFFER (buffer
)->name
);
2942 if (!NILP (swp
) && !no_switch_window (selected_window
))
2944 Fswitch_to_buffer (buffer
, Qnil
);
2945 return display_buffer_1 (selected_window
);
2949 /* If the user wants pop-up-frames or display-reuse-frames, then
2950 look for a window showing BUFFER on any visible or iconified frame.
2951 Otherwise search only the current frame. */
2954 else if (pop_up_frames
2955 || display_buffer_reuse_frames
2956 || last_nonminibuf_frame
== 0)
2957 XSETFASTINT (tem
, 0);
2959 XSETFRAME (tem
, last_nonminibuf_frame
);
2961 window
= Fget_buffer_window (buffer
, tem
);
2963 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
2964 return display_buffer_1 (window
);
2966 /* Certain buffer names get special handling. */
2967 if (!NILP (Vspecial_display_function
) && NILP (swp
))
2969 tem
= Fspecial_display_p (XBUFFER (buffer
)->name
);
2971 return call1 (Vspecial_display_function
, buffer
);
2973 return call2 (Vspecial_display_function
, buffer
, tem
);
2976 /* If there are no frames open that have more than a minibuffer,
2977 we need to create a new frame. */
2978 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
2980 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
2981 Fset_window_buffer (window
, buffer
);
2982 return display_buffer_1 (window
);
2985 f
= SELECTED_FRAME ();
2987 || FRAME_MINIBUF_ONLY_P (f
)
2988 /* If the current frame is a special display frame,
2989 don't try to reuse its windows. */
2990 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f
))->dedicated
))
2995 if (FRAME_MINIBUF_ONLY_P (f
))
2996 XSETFRAME (frames
, last_nonminibuf_frame
);
2997 /* Don't try to create a window if would get an error */
2998 if (split_height_threshold
< window_min_height
<< 1)
2999 split_height_threshold
= window_min_height
<< 1;
3001 /* Note that both Fget_largest_window and Fget_lru_window
3002 ignore minibuffers and dedicated windows.
3003 This means they can return nil. */
3005 /* If the frame we would try to split cannot be split,
3006 try other frames. */
3007 if (FRAME_NO_SPLIT_P (NILP (frames
) ? f
: last_nonminibuf_frame
))
3009 /* Try visible frames first. */
3010 window
= Fget_largest_window (Qvisible
);
3011 /* If that didn't work, try iconified frames. */
3013 window
= Fget_largest_window (make_number (0));
3015 window
= Fget_largest_window (Qt
);
3018 window
= Fget_largest_window (frames
);
3020 /* If we got a tall enough full-width window that can be split,
3023 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3024 && window_height (window
) >= split_height_threshold
3025 && WINDOW_FULL_WIDTH_P (XWINDOW (window
)))
3026 window
= Fsplit_window (window
, Qnil
, Qnil
);
3029 Lisp_Object upper
, lower
, other
;
3031 window
= Fget_lru_window (frames
);
3032 /* If the LRU window is selected, and big enough,
3033 and can be split, split it. */
3035 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3036 && (EQ (window
, selected_window
)
3037 || EQ (XWINDOW (window
)->parent
, Qnil
))
3038 && window_height (window
) >= window_min_height
<< 1)
3039 window
= Fsplit_window (window
, Qnil
, Qnil
);
3040 /* If Fget_lru_window returned nil, try other approaches. */
3042 /* Try visible frames first. */
3044 window
= Fget_buffer_window (buffer
, Qvisible
);
3046 window
= Fget_largest_window (Qvisible
);
3047 /* If that didn't work, try iconified frames. */
3049 window
= Fget_buffer_window (buffer
, make_number (0));
3051 window
= Fget_largest_window (make_number (0));
3052 /* Try invisible frames. */
3054 window
= Fget_buffer_window (buffer
, Qt
);
3056 window
= Fget_largest_window (Qt
);
3057 /* As a last resort, make a new frame. */
3059 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
3060 /* If window appears above or below another,
3061 even out their heights. */
3062 other
= upper
= lower
= Qnil
;
3063 if (!NILP (XWINDOW (window
)->prev
))
3064 other
= upper
= XWINDOW (window
)->prev
, lower
= window
;
3065 if (!NILP (XWINDOW (window
)->next
))
3066 other
= lower
= XWINDOW (window
)->next
, upper
= window
;
3068 && !NILP (Veven_window_heights
)
3069 /* Check that OTHER and WINDOW are vertically arrayed. */
3070 && !EQ (XWINDOW (other
)->top
, XWINDOW (window
)->top
)
3071 && (XFASTINT (XWINDOW (other
)->height
)
3072 > XFASTINT (XWINDOW (window
)->height
)))
3074 int total
= (XFASTINT (XWINDOW (other
)->height
)
3075 + XFASTINT (XWINDOW (window
)->height
));
3076 enlarge_window (upper
,
3077 total
/ 2 - XFASTINT (XWINDOW (upper
)->height
),
3083 window
= Fget_lru_window (Qnil
);
3085 Fset_window_buffer (window
, buffer
);
3086 return display_buffer_1 (window
);
3090 temp_output_buffer_show (buf
)
3091 register Lisp_Object buf
;
3093 register struct buffer
*old
= current_buffer
;
3094 register Lisp_Object window
;
3095 register struct window
*w
;
3097 XBUFFER (buf
)->directory
= current_buffer
->directory
;
3100 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
3104 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
3105 set_buffer_internal (old
);
3107 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
3108 call1 (Vtemp_buffer_show_function
, buf
);
3111 window
= Fdisplay_buffer (buf
, Qnil
, Qnil
);
3113 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
3114 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
3115 Vminibuf_scroll_window
= window
;
3116 w
= XWINDOW (window
);
3117 XSETFASTINT (w
->hscroll
, 0);
3118 XSETFASTINT (w
->min_hscroll
, 0);
3119 set_marker_restricted_both (w
->start
, buf
, 1, 1);
3120 set_marker_restricted_both (w
->pointm
, buf
, 1, 1);
3122 /* Run temp-buffer-show-hook, with the chosen window selected
3123 and it sbuffer current. */
3124 if (!NILP (Vrun_hooks
))
3127 tem
= Fboundp (Qtemp_buffer_show_hook
);
3130 tem
= Fsymbol_value (Qtemp_buffer_show_hook
);
3133 int count
= specpdl_ptr
- specpdl
;
3134 Lisp_Object prev_window
;
3135 prev_window
= selected_window
;
3137 /* Select the window that was chosen, for running the hook. */
3138 record_unwind_protect (Fselect_window
, prev_window
);
3139 select_window_1 (window
, 0);
3140 Fset_buffer (w
->buffer
);
3141 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
3142 select_window_1 (prev_window
, 0);
3143 unbind_to (count
, Qnil
);
3151 make_dummy_parent (window
)
3155 register struct window
*o
, *p
;
3158 o
= XWINDOW (window
);
3159 p
= allocate_window ();
3160 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
3161 ((struct Lisp_Vector
*) p
)->contents
[i
]
3162 = ((struct Lisp_Vector
*)o
)->contents
[i
];
3163 XSETWINDOW (new, p
);
3165 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
3167 /* Put new into window structure in place of window */
3168 replace_window (window
, new);
3181 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
3182 doc
: /* Split WINDOW, putting SIZE lines in the first of the pair.
3183 WINDOW defaults to selected one and SIZE to half its size.
3184 If optional third arg HORFLAG is non-nil, split side by side
3185 and put SIZE columns in the first of the pair. In that case,
3186 SIZE includes that window's scroll bar, or the divider column to its right. */)
3187 (window
, size
, horflag
)
3188 Lisp_Object window
, size
, horflag
;
3190 register Lisp_Object
new;
3191 register struct window
*o
, *p
;
3193 register int size_int
;
3196 window
= selected_window
;
3198 CHECK_LIVE_WINDOW (window
);
3200 o
= XWINDOW (window
);
3201 fo
= XFRAME (WINDOW_FRAME (o
));
3205 if (!NILP (horflag
))
3206 /* Calculate the size of the left-hand window, by dividing
3207 the usable space in columns by two.
3208 We round up, since the left-hand window may include
3209 a dividing line, while the right-hand may not. */
3210 size_int
= (XFASTINT (o
->width
) + 1) >> 1;
3212 size_int
= XFASTINT (o
->height
) >> 1;
3216 CHECK_NUMBER (size
);
3217 size_int
= XINT (size
);
3220 if (MINI_WINDOW_P (o
))
3221 error ("Attempt to split minibuffer window");
3222 else if (window_fixed_size_p (o
, !NILP (horflag
), 0))
3223 error ("Attempt to split fixed-size window");
3225 check_min_window_sizes ();
3229 if (size_int
< window_min_height
)
3230 error ("Window height %d too small (after splitting)", size_int
);
3231 if (size_int
+ window_min_height
> XFASTINT (o
->height
))
3232 error ("Window height %d too small (after splitting)",
3233 XFASTINT (o
->height
) - size_int
);
3234 if (NILP (o
->parent
)
3235 || NILP (XWINDOW (o
->parent
)->vchild
))
3237 make_dummy_parent (window
);
3239 XWINDOW (new)->vchild
= window
;
3244 if (size_int
< window_min_width
)
3245 error ("Window width %d too small (after splitting)", size_int
);
3247 if (size_int
+ window_min_width
> XFASTINT (o
->width
))
3248 error ("Window width %d too small (after splitting)",
3249 XFASTINT (o
->width
) - size_int
);
3250 if (NILP (o
->parent
)
3251 || NILP (XWINDOW (o
->parent
)->hchild
))
3253 make_dummy_parent (window
);
3255 XWINDOW (new)->hchild
= window
;
3259 /* Now we know that window's parent is a vertical combination
3260 if we are dividing vertically, or a horizontal combination
3261 if we are making side-by-side windows */
3263 windows_or_buffers_changed
++;
3264 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
3265 new = make_window ();
3268 p
->frame
= o
->frame
;
3270 if (!NILP (p
->next
))
3271 XWINDOW (p
->next
)->prev
= new;
3274 p
->parent
= o
->parent
;
3276 p
->window_end_valid
= Qnil
;
3277 bzero (&p
->last_cursor
, sizeof p
->last_cursor
);
3279 /* Apportion the available frame space among the two new windows */
3281 if (!NILP (horflag
))
3283 p
->height
= o
->height
;
3285 XSETFASTINT (p
->width
, XFASTINT (o
->width
) - size_int
);
3286 XSETFASTINT (o
->width
, size_int
);
3287 XSETFASTINT (p
->left
, XFASTINT (o
->left
) + size_int
);
3292 p
->width
= o
->width
;
3293 XSETFASTINT (p
->height
, XFASTINT (o
->height
) - size_int
);
3294 XSETFASTINT (o
->height
, size_int
);
3295 XSETFASTINT (p
->top
, XFASTINT (o
->top
) + size_int
);
3298 /* Adjust glyph matrices. */
3300 Fset_window_buffer (new, o
->buffer
);
3304 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 3, "p",
3305 doc
: /* Make current window ARG lines bigger.
3306 From program, optional second arg non-nil means grow sideways ARG columns.
3307 Interactively, if an argument is not given, make the window one line bigger.
3309 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3310 of the siblings above or to the left of the selected window. Only
3311 siblings to the right or below are changed. */)
3312 (arg
, side
, preserve_before
)
3313 register Lisp_Object arg
, side
, preserve_before
;
3316 enlarge_window (selected_window
, XINT (arg
), !NILP (side
),
3317 !NILP (preserve_before
));
3319 if (! NILP (Vwindow_configuration_change_hook
))
3320 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
3325 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
3326 doc
: /* Make current window ARG lines smaller.
3327 From program, optional second arg non-nil means shrink sideways arg columns.
3328 Interactively, if an argument is not given, make the window one line smaller. */)
3330 register Lisp_Object arg
, side
;
3333 enlarge_window (selected_window
, -XINT (arg
), !NILP (side
), 0);
3335 if (! NILP (Vwindow_configuration_change_hook
))
3336 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
3342 window_height (window
)
3345 register struct window
*p
= XWINDOW (window
);
3346 return XFASTINT (p
->height
);
3350 window_width (window
)
3353 register struct window
*p
= XWINDOW (window
);
3354 return XFASTINT (p
->width
);
3359 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3361 #define CURSIZE(w) \
3362 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3365 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3366 increase its width. Siblings of the selected window are resized to
3367 fulfill the size request. If they become too small in the process,
3368 they will be deleted.
3370 If PRESERVE_BEFORE is nonzero, that means don't alter
3371 the siblings to the left or above WINDOW. */
3374 enlarge_window (window
, delta
, widthflag
, preserve_before
)
3376 int delta
, widthflag
, preserve_before
;
3378 Lisp_Object parent
, next
, prev
;
3382 int (*sizefun
) P_ ((Lisp_Object
))
3383 = widthflag
? window_width
: window_height
;
3384 void (*setsizefun
) P_ ((Lisp_Object
, int, int))
3385 = (widthflag
? set_window_width
: set_window_height
);
3387 /* Check values of window_min_width and window_min_height for
3389 check_min_window_sizes ();
3391 /* Give up if this window cannot be resized. */
3392 if (window_fixed_size_p (XWINDOW (window
), widthflag
, 1))
3393 error ("Window is not resizable");
3395 /* Find the parent of the selected window. */
3398 p
= XWINDOW (window
);
3404 error ("No other window to side of this one");
3409 ? !NILP (XWINDOW (parent
)->hchild
)
3410 : !NILP (XWINDOW (parent
)->vchild
))
3416 sizep
= &CURSIZE (window
);
3419 register int maxdelta
;
3421 /* Compute the maximum size increment this window can have. */
3423 if (preserve_before
)
3427 maxdelta
= (*sizefun
) (parent
) - XINT (*sizep
);
3428 /* Subtract size of siblings before, since we can't take that. */
3429 maxdelta
-= XINT (CURBEG (window
)) - XINT (CURBEG (parent
));
3432 maxdelta
= (!NILP (p
->next
) ? ((*sizefun
) (p
->next
)
3433 - window_min_size (XWINDOW (p
->next
),
3438 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
3439 /* This is a main window followed by a minibuffer. */
3440 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
3441 - window_min_size (XWINDOW (p
->next
),
3443 /* This is a minibuffer following a main window. */
3444 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
3445 - window_min_size (XWINDOW (p
->prev
),
3447 /* This is a frame with only one window, a minibuffer-only
3448 or a minibufferless frame. */
3451 if (delta
> maxdelta
)
3452 /* This case traps trying to make the minibuffer
3453 the full frame, or make the only window aside from the
3454 minibuffer the full frame. */
3458 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
), widthflag
, 0, 0))
3460 delete_window (window
);
3467 /* Find the total we can get from other siblings without deleting them. */
3469 for (next
= p
->next
; ! NILP (next
); next
= XWINDOW (next
)->next
)
3470 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
3472 if (! preserve_before
)
3473 for (prev
= p
->prev
; ! NILP (prev
); prev
= XWINDOW (prev
)->prev
)
3474 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
3477 /* If we can get it all from them without deleting them, do so. */
3478 if (delta
<= maximum
)
3480 Lisp_Object first_unaffected
;
3481 Lisp_Object first_affected
;
3486 first_affected
= window
;
3487 /* Look at one sibling at a time,
3488 moving away from this window in both directions alternately,
3489 and take as much as we can get without deleting that sibling. */
3491 && (!NILP (next
) || (!preserve_before
&& !NILP (prev
))))
3495 int this_one
= ((*sizefun
) (next
)
3496 - window_min_size (XWINDOW (next
),
3497 widthflag
, 0, &fixed_p
));
3500 if (this_one
> delta
)
3503 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
3504 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
3509 next
= XWINDOW (next
)->next
;
3515 if (!preserve_before
&& ! NILP (prev
))
3517 int this_one
= ((*sizefun
) (prev
)
3518 - window_min_size (XWINDOW (prev
),
3519 widthflag
, 0, &fixed_p
));
3522 if (this_one
> delta
)
3525 first_affected
= prev
;
3527 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
3528 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
3533 prev
= XWINDOW (prev
)->prev
;
3537 xassert (delta
== 0);
3539 /* Now recalculate the edge positions of all the windows affected,
3540 based on the new sizes. */
3541 first_unaffected
= next
;
3542 prev
= first_affected
;
3543 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
3544 prev
= next
, next
= XWINDOW (next
)->next
)
3546 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
3547 /* This does not change size of NEXT,
3548 but it propagates the new top edge to its children */
3549 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
3554 register int delta1
;
3555 register int opht
= (*sizefun
) (parent
);
3557 if (opht
<= XINT (*sizep
) + delta
)
3559 /* If trying to grow this window to or beyond size of the parent,
3560 just delete all the sibling windows. */
3561 Lisp_Object start
, tem
, next
;
3563 start
= XWINDOW (parent
)->vchild
;
3565 start
= XWINDOW (parent
)->hchild
;
3567 /* Delete any siblings that come after WINDOW. */
3568 tem
= XWINDOW (window
)->next
;
3569 while (! NILP (tem
))
3571 next
= XWINDOW (tem
)->next
;
3572 delete_window (tem
);
3576 /* Delete any siblings that come after WINDOW.
3577 Note that if START is not WINDOW, then WINDOW still
3578 Fhas siblings, so WINDOW has not yet replaced its parent. */
3580 while (! EQ (tem
, window
))
3582 next
= XWINDOW (tem
)->next
;
3583 delete_window (tem
);
3589 /* Otherwise, make delta1 just right so that if we add
3590 delta1 lines to this window and to the parent, and then
3591 shrink the parent back to its original size, the new
3592 proportional size of this window will increase by delta.
3594 The function size_window will compute the new height h'
3595 of the window from delta1 as:
3598 x = delta1 - delta1/n * n for the 1st resizable child
3601 where n is the number of children that can be resized.
3602 We can ignore x by choosing a delta1 that is a multiple of
3603 n. We want the height of this window to come out as
3613 The number of children n rquals the number of resizable
3614 children of this window + 1 because we know window itself
3615 is resizable (otherwise we would have signalled an error. */
3617 struct window
*w
= XWINDOW (window
);
3621 for (s
= w
->next
; !NILP (s
); s
= XWINDOW (s
)->next
)
3622 if (!window_fixed_size_p (XWINDOW (s
), widthflag
, 0))
3624 for (s
= w
->prev
; !NILP (s
); s
= XWINDOW (s
)->prev
)
3625 if (!window_fixed_size_p (XWINDOW (s
), widthflag
, 0))
3630 /* Add delta1 lines or columns to this window, and to the parent,
3631 keeping things consistent while not affecting siblings. */
3632 XSETINT (CURSIZE (parent
), opht
+ delta1
);
3633 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
3635 /* Squeeze out delta1 lines or columns from our parent,
3636 shriking this window and siblings proportionately.
3637 This brings parent back to correct size.
3638 Delta1 was calculated so this makes this window the desired size,
3639 taking it all out of the siblings. */
3640 (*setsizefun
) (parent
, opht
, 0);
3645 XSETFASTINT (p
->last_modified
, 0);
3646 XSETFASTINT (p
->last_overlay_modified
, 0);
3648 /* Adjust glyph matrices. */
3649 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
3657 /***********************************************************************
3658 Resizing Mini-Windows
3659 ***********************************************************************/
3661 static void shrink_window_lowest_first
P_ ((struct window
*, int));
3663 enum save_restore_action
3670 static int save_restore_orig_size
P_ ((struct window
*,
3671 enum save_restore_action
));
3673 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3674 from lowest windows first. */
3677 shrink_window_lowest_first (w
, height
)
3685 xassert (!MINI_WINDOW_P (w
));
3687 /* Set redisplay hints. */
3688 XSETFASTINT (w
->last_modified
, 0);
3689 XSETFASTINT (w
->last_overlay_modified
, 0);
3690 windows_or_buffers_changed
++;
3691 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
3693 old_height
= XFASTINT (w
->height
);
3694 XSETFASTINT (w
->height
, height
);
3696 if (!NILP (w
->hchild
))
3698 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
3700 c
= XWINDOW (child
);
3702 shrink_window_lowest_first (c
, height
);
3705 else if (!NILP (w
->vchild
))
3707 Lisp_Object last_child
;
3708 int delta
= old_height
- height
;
3713 /* Find the last child. We are taking space from lowest windows
3714 first, so we iterate over children from the last child
3716 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
3719 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3720 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
3724 c
= XWINDOW (child
);
3725 this_one
= XFASTINT (c
->height
) - MIN_SAFE_WINDOW_HEIGHT
;
3727 if (this_one
> delta
)
3730 shrink_window_lowest_first (c
, XFASTINT (c
->height
) - this_one
);
3734 /* Compute new positions. */
3735 last_top
= XINT (w
->top
);
3736 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
3738 c
= XWINDOW (child
);
3739 c
->top
= make_number (last_top
);
3740 shrink_window_lowest_first (c
, XFASTINT (c
->height
));
3741 last_top
+= XFASTINT (c
->height
);
3747 /* Save, restore, or check positions and sizes in the window tree
3748 rooted at W. ACTION says what to do.
3750 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3751 members are valid for all windows in the window tree. Value is
3752 non-zero if they are valid.
3754 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3755 orig_top and orig_height for all windows in the tree.
3757 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3758 values stored in orig_top and orig_height for all windows. */
3761 save_restore_orig_size (w
, action
)
3763 enum save_restore_action action
;
3769 if (!NILP (w
->hchild
))
3771 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
3774 else if (!NILP (w
->vchild
))
3776 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
3782 case CHECK_ORIG_SIZES
:
3783 if (!INTEGERP (w
->orig_top
) || !INTEGERP (w
->orig_height
))
3787 case SAVE_ORIG_SIZES
:
3788 w
->orig_top
= w
->top
;
3789 w
->orig_height
= w
->height
;
3790 XSETFASTINT (w
->last_modified
, 0);
3791 XSETFASTINT (w
->last_overlay_modified
, 0);
3794 case RESTORE_ORIG_SIZES
:
3795 xassert (INTEGERP (w
->orig_top
) && INTEGERP (w
->orig_height
));
3796 w
->top
= w
->orig_top
;
3797 w
->height
= w
->orig_height
;
3798 w
->orig_height
= w
->orig_top
= Qnil
;
3799 XSETFASTINT (w
->last_modified
, 0);
3800 XSETFASTINT (w
->last_overlay_modified
, 0);
3807 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
3814 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3815 without deleting other windows. */
3818 grow_mini_window (w
, delta
)
3822 struct frame
*f
= XFRAME (w
->frame
);
3823 struct window
*root
;
3825 xassert (MINI_WINDOW_P (w
));
3826 xassert (delta
>= 0);
3828 /* Check values of window_min_width and window_min_height for
3830 check_min_window_sizes ();
3832 /* Compute how much we can enlarge the mini-window without deleting
3834 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
3837 int min_height
= window_min_size (root
, 0, 0, 0);
3838 if (XFASTINT (root
->height
) - delta
< min_height
)
3839 /* Note that the root window may already be smaller than
3841 delta
= max (0, XFASTINT (root
->height
) - min_height
);
3846 /* Save original window sizes and positions, if not already done. */
3847 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
3848 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
3850 /* Shrink other windows. */
3851 shrink_window_lowest_first (root
, XFASTINT (root
->height
) - delta
);
3853 /* Grow the mini-window. */
3854 w
->top
= make_number (XFASTINT (root
->top
) + XFASTINT (root
->height
));
3855 w
->height
= make_number (XFASTINT (w
->height
) + delta
);
3856 XSETFASTINT (w
->last_modified
, 0);
3857 XSETFASTINT (w
->last_overlay_modified
, 0);
3864 /* Shrink mini-window W. If there is recorded info about window sizes
3865 before a call to grow_mini_window, restore recorded window sizes.
3866 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3870 shrink_mini_window (w
)
3873 struct frame
*f
= XFRAME (w
->frame
);
3874 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
3876 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
3878 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
3880 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
3881 windows_or_buffers_changed
= 1;
3883 else if (XFASTINT (w
->height
) > 1)
3885 /* Distribute the additional lines of the mini-window
3886 among the other windows. */
3888 XSETWINDOW (window
, w
);
3889 enlarge_window (window
, 1 - XFASTINT (w
->height
), 0, 0);
3895 /* Mark window cursors off for all windows in the window tree rooted
3896 at W by setting their phys_cursor_on_p flag to zero. Called from
3897 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3898 the frame are cleared. */
3901 mark_window_cursors_off (w
)
3906 if (!NILP (w
->hchild
))
3907 mark_window_cursors_off (XWINDOW (w
->hchild
));
3908 else if (!NILP (w
->vchild
))
3909 mark_window_cursors_off (XWINDOW (w
->vchild
));
3911 w
->phys_cursor_on_p
= 0;
3913 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
3918 /* Return number of lines of text (not counting mode lines) in W. */
3921 window_internal_height (w
)
3924 int ht
= XFASTINT (w
->height
);
3926 if (!MINI_WINDOW_P (w
))
3928 if (!NILP (w
->parent
)
3929 || !NILP (w
->vchild
)
3930 || !NILP (w
->hchild
)
3933 || WINDOW_WANTS_MODELINE_P (w
))
3936 if (WINDOW_WANTS_HEADER_LINE_P (w
))
3944 /* Return the number of columns in W.
3945 Don't count columns occupied by scroll bars or the vertical bar
3946 separating W from the sibling to its right. */
3949 window_internal_width (w
)
3952 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
3953 int width
= XINT (w
->width
);
3955 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3956 /* Scroll bars occupy a few columns. */
3957 width
-= FRAME_SCROLL_BAR_COLS (f
);
3958 else if (!WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
3959 /* The column of `|' characters separating side-by-side windows
3960 occupies one column only. */
3963 /* On window-systems, areas to the left and right of the window
3964 are used as fringes. */
3965 if (FRAME_WINDOW_P (f
))
3966 width
-= FRAME_FRINGE_COLS (f
);
3972 /************************************************************************
3974 ***********************************************************************/
3976 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3977 N screen-fulls, which is defined as the height of the window minus
3978 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3979 instead. Negative values of N mean scroll down. NOERROR non-zero
3980 means don't signal an error if we try to move over BEGV or ZV,
3984 window_scroll (window
, n
, whole
, noerror
)
3990 /* If we must, use the pixel-based version which is much slower than
3991 the line-based one but can handle varying line heights. */
3992 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
3993 window_scroll_pixel_based (window
, n
, whole
, noerror
);
3995 window_scroll_line_based (window
, n
, whole
, noerror
);
3999 /* Implementation of window_scroll that works based on pixel line
4000 heights. See the comment of window_scroll for parameter
4004 window_scroll_pixel_based (window
, n
, whole
, noerror
)
4011 struct window
*w
= XWINDOW (window
);
4012 struct text_pos start
;
4014 int this_scroll_margin
;
4016 /* True if we fiddled the window vscroll field without really scrolling. */
4019 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4021 /* If PT is not visible in WINDOW, move back one half of
4022 the screen. Allow PT to be partially visible, otherwise
4023 something like (scroll-down 1) with PT in the line before
4024 the partially visible one would recenter. */
4025 tem
= Fpos_visible_in_window_p (make_number (PT
), window
, Qt
);
4028 /* Move backward half the height of the window. Performance note:
4029 vmotion used here is about 10% faster, but would give wrong
4030 results for variable height lines. */
4031 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4032 it
.current_y
= it
.last_visible_y
;
4033 move_it_vertically (&it
, - window_box_height (w
) / 2);
4035 /* The function move_iterator_vertically may move over more than
4036 the specified y-distance. If it->w is small, e.g. a
4037 mini-buffer window, we may end up in front of the window's
4038 display area. This is the case when Start displaying at the
4039 start of the line containing PT in this case. */
4040 if (it
.current_y
<= 0)
4042 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4043 move_it_vertically (&it
, 0);
4047 start
= it
.current
.pos
;
4050 /* If scroll_preserve_screen_position is non-zero, we try to set
4051 point in the same window line as it is now, so get that line. */
4052 if (!NILP (Vscroll_preserve_screen_position
))
4054 start_display (&it
, w
, start
);
4055 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4056 preserve_y
= it
.current_y
;
4061 /* Move iterator it from start the specified distance forward or
4062 backward. The result is the new window start. */
4063 start_display (&it
, w
, start
);
4066 int screen_full
= (window_box_height (w
)
4067 - next_screen_context_lines
* CANON_Y_UNIT (it
.f
));
4068 int dy
= n
* screen_full
;
4070 /* Note that move_it_vertically always moves the iterator to the
4071 start of a line. So, if the last line doesn't have a newline,
4072 we would end up at the start of the line ending at ZV. */
4074 move_it_vertically_backward (&it
, -dy
);
4076 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
4077 MOVE_TO_POS
| MOVE_TO_Y
);
4080 move_it_by_lines (&it
, n
, 1);
4082 /* End if we end up at ZV or BEGV. */
4083 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
4084 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
4086 if (IT_CHARPOS (it
) == ZV
)
4088 if (it
.current_y
+ it
.max_ascent
+ it
.max_descent
4089 > it
.last_visible_y
)
4091 /* The last line was only partially visible, make it fully
4093 w
->vscroll
= (it
.last_visible_y
4094 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
4095 adjust_glyphs (it
.f
);
4100 Fsignal (Qend_of_buffer
, Qnil
);
4104 if (w
->vscroll
!= 0)
4105 /* The first line was only partially visible, make it fully
4111 Fsignal (Qbeginning_of_buffer
, Qnil
);
4114 /* If control gets here, then we vscrolled. */
4116 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
4118 /* Don't try to change the window start below. */
4124 /* Set the window start, and set up the window for redisplay. */
4125 set_marker_restricted (w
->start
, make_number (IT_CHARPOS (it
)),
4127 w
->start_at_line_beg
= Fbolp ();
4128 w
->update_mode_line
= Qt
;
4129 XSETFASTINT (w
->last_modified
, 0);
4130 XSETFASTINT (w
->last_overlay_modified
, 0);
4131 /* Set force_start so that redisplay_window will run the
4132 window-scroll-functions. */
4133 w
->force_start
= Qt
;
4136 it
.current_y
= it
.vpos
= 0;
4138 /* Preserve the screen position if we must. */
4139 if (preserve_y
>= 0)
4141 move_it_to (&it
, -1, -1, preserve_y
, -1, MOVE_TO_Y
);
4142 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4146 /* Move PT out of scroll margins. */
4147 this_scroll_margin
= max (0, scroll_margin
);
4148 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->height
) / 4);
4149 this_scroll_margin
*= CANON_Y_UNIT (it
.f
);
4153 /* We moved the window start towards ZV, so PT may be now
4154 in the scroll margin at the top. */
4155 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4156 while (it
.current_y
< this_scroll_margin
)
4157 move_it_by_lines (&it
, 1, 1);
4158 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4162 int charpos
, bytepos
;
4164 /* We moved the window start towards BEGV, so PT may be now
4165 in the scroll margin at the bottom. */
4166 move_it_to (&it
, PT
, -1,
4167 it
.last_visible_y
- this_scroll_margin
- 1, -1,
4168 MOVE_TO_POS
| MOVE_TO_Y
);
4170 /* Save our position, in case it's correct. */
4171 charpos
= IT_CHARPOS (it
);
4172 bytepos
= IT_BYTEPOS (it
);
4174 /* See if point is on a partially visible line at the end. */
4175 move_it_by_lines (&it
, 1, 1);
4176 if (it
.current_y
> it
.last_visible_y
)
4177 /* The last line was only partially visible, so back up two
4178 lines to make sure we're on a fully visible line. */
4180 move_it_by_lines (&it
, -2, 0);
4181 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4184 /* No, the position we saved is OK, so use it. */
4185 SET_PT_BOTH (charpos
, bytepos
);
4191 /* Implementation of window_scroll that works based on screen lines.
4192 See the comment of window_scroll for parameter descriptions. */
4195 window_scroll_line_based (window
, n
, whole
, noerror
)
4201 register struct window
*w
= XWINDOW (window
);
4202 register int opoint
= PT
, opoint_byte
= PT_BYTE
;
4203 register int pos
, pos_byte
;
4204 register int ht
= window_internal_height (w
);
4205 register Lisp_Object tem
;
4209 struct position posit
;
4212 /* If scrolling screen-fulls, compute the number of lines to
4213 scroll from the window's height. */
4215 n
*= max (1, ht
- next_screen_context_lines
);
4217 startpos
= marker_position (w
->start
);
4219 posit
= *compute_motion (startpos
, 0, 0, 0,
4221 window_internal_width (w
), XINT (w
->hscroll
),
4223 original_vpos
= posit
.vpos
;
4225 XSETFASTINT (tem
, PT
);
4226 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
4230 Fvertical_motion (make_number (- (ht
/ 2)), window
);
4235 lose
= n
< 0 && PT
== BEGV
;
4236 Fvertical_motion (make_number (n
), window
);
4240 SET_PT_BOTH (opoint
, opoint_byte
);
4247 Fsignal (Qbeginning_of_buffer
, Qnil
);
4252 int this_scroll_margin
= scroll_margin
;
4254 /* Don't use a scroll margin that is negative or too large. */
4255 if (this_scroll_margin
< 0)
4256 this_scroll_margin
= 0;
4258 if (XINT (w
->height
) < 4 * scroll_margin
)
4259 this_scroll_margin
= XINT (w
->height
) / 4;
4261 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
4262 w
->start_at_line_beg
= bolp
;
4263 w
->update_mode_line
= Qt
;
4264 XSETFASTINT (w
->last_modified
, 0);
4265 XSETFASTINT (w
->last_overlay_modified
, 0);
4266 /* Set force_start so that redisplay_window will run
4267 the window-scroll-functions. */
4268 w
->force_start
= Qt
;
4270 if (whole
&& !NILP (Vscroll_preserve_screen_position
))
4272 SET_PT_BOTH (pos
, pos_byte
);
4273 Fvertical_motion (make_number (original_vpos
), window
);
4275 /* If we scrolled forward, put point enough lines down
4276 that it is outside the scroll margin. */
4281 if (this_scroll_margin
> 0)
4283 SET_PT_BOTH (pos
, pos_byte
);
4284 Fvertical_motion (make_number (this_scroll_margin
), window
);
4290 if (top_margin
<= opoint
)
4291 SET_PT_BOTH (opoint
, opoint_byte
);
4292 else if (!NILP (Vscroll_preserve_screen_position
))
4294 SET_PT_BOTH (pos
, pos_byte
);
4295 Fvertical_motion (make_number (original_vpos
), window
);
4298 SET_PT (top_margin
);
4304 /* If we scrolled backward, put point near the end of the window
4305 but not within the scroll margin. */
4306 SET_PT_BOTH (pos
, pos_byte
);
4307 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
4308 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
4311 bottom_margin
= PT
+ 1;
4313 if (bottom_margin
> opoint
)
4314 SET_PT_BOTH (opoint
, opoint_byte
);
4317 if (!NILP (Vscroll_preserve_screen_position
))
4319 SET_PT_BOTH (pos
, pos_byte
);
4320 Fvertical_motion (make_number (original_vpos
), window
);
4323 Fvertical_motion (make_number (-1), window
);
4332 Fsignal (Qend_of_buffer
, Qnil
);
4337 /* Scroll selected_window up or down. If N is nil, scroll a
4338 screen-full which is defined as the height of the window minus
4339 next_screen_context_lines. If N is the symbol `-', scroll.
4340 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4341 up. This is the guts of Fscroll_up and Fscroll_down. */
4344 scroll_command (n
, direction
)
4348 int count
= BINDING_STACK_SIZE ();
4350 xassert (abs (direction
) == 1);
4352 /* If selected window's buffer isn't current, make it current for
4353 the moment. But don't screw up if window_scroll gets an error. */
4354 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
4356 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
4357 Fset_buffer (XWINDOW (selected_window
)->buffer
);
4359 /* Make redisplay consider other windows than just selected_window. */
4360 ++windows_or_buffers_changed
;
4364 window_scroll (selected_window
, direction
, 1, 0);
4365 else if (EQ (n
, Qminus
))
4366 window_scroll (selected_window
, -direction
, 1, 0);
4369 n
= Fprefix_numeric_value (n
);
4370 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
4373 unbind_to (count
, Qnil
);
4376 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
4377 doc
: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4378 A near full screen is `next-screen-context-lines' less than a full screen.
4379 Negative ARG means scroll downward.
4380 If ARG is the atom `-', scroll downward by nearly full screen.
4381 When calling from a program, supply as argument a number, nil, or `-'. */)
4385 scroll_command (arg
, 1);
4389 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
4390 doc
: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4391 A near full screen is `next-screen-context-lines' less than a full screen.
4392 Negative ARG means scroll upward.
4393 If ARG is the atom `-', scroll upward by nearly full screen.
4394 When calling from a program, supply as argument a number, nil, or `-'. */)
4398 scroll_command (arg
, -1);
4402 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
4403 doc
: /* Return the other window for \"other window scroll\" commands.
4404 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4405 specifies the window.
4406 If `other-window-scroll-buffer' is non-nil, a window
4407 showing that buffer is used. */)
4412 if (MINI_WINDOW_P (XWINDOW (selected_window
))
4413 && !NILP (Vminibuf_scroll_window
))
4414 window
= Vminibuf_scroll_window
;
4415 /* If buffer is specified, scroll that buffer. */
4416 else if (!NILP (Vother_window_scroll_buffer
))
4418 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
4420 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
4424 /* Nothing specified; look for a neighboring window on the same
4426 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
4428 if (EQ (window
, selected_window
))
4429 /* That didn't get us anywhere; look for a window on another
4432 window
= Fnext_window (window
, Qnil
, Qt
);
4433 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
4434 && ! EQ (window
, selected_window
));
4437 CHECK_LIVE_WINDOW (window
);
4439 if (EQ (window
, selected_window
))
4440 error ("There is no other window");
4445 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
4446 doc
: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4447 A near full screen is `next-screen-context-lines' less than a full screen.
4448 The next window is the one below the current one; or the one at the top
4449 if the current one is at the bottom. Negative ARG means scroll downward.
4450 If ARG is the atom `-', scroll downward by nearly full screen.
4451 When calling from a program, supply as argument a number, nil, or `-'.
4453 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4454 specifies the window to scroll.
4455 If `other-window-scroll-buffer' is non-nil, scroll the window
4456 showing that buffer, popping the buffer up if necessary. */)
4462 int count
= BINDING_STACK_SIZE ();
4464 window
= Fother_window_for_scrolling ();
4465 w
= XWINDOW (window
);
4467 /* Don't screw up if window_scroll gets an error. */
4468 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
4469 ++windows_or_buffers_changed
;
4471 Fset_buffer (w
->buffer
);
4472 SET_PT (marker_position (w
->pointm
));
4475 window_scroll (window
, 1, 1, 1);
4476 else if (EQ (arg
, Qminus
))
4477 window_scroll (window
, -1, 1, 1);
4483 window_scroll (window
, XINT (arg
), 0, 1);
4486 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
4487 unbind_to (count
, Qnil
);
4492 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 1, "P",
4493 doc
: /* Scroll selected window display ARG columns left.
4494 Default for ARG is window width minus 2.
4495 Value is the total amount of leftward horizontal scrolling in
4496 effect after the change.
4497 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4498 a lower bound for automatic scrolling, i.e. automatic scrolling
4499 will not scroll a window to a column less than the value returned
4500 by this function. */)
4502 register Lisp_Object arg
;
4506 struct window
*w
= XWINDOW (selected_window
);
4509 XSETFASTINT (arg
, window_internal_width (w
) - 2);
4511 arg
= Fprefix_numeric_value (arg
);
4513 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
4514 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
4516 if (interactive_p (0))
4517 w
->min_hscroll
= w
->hscroll
;
4522 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 1, "P",
4523 doc
: /* Scroll selected window display ARG columns right.
4524 Default for ARG is window width minus 2.
4525 Value is the total amount of leftward horizontal scrolling in
4526 effect after the change.
4527 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4528 a lower bound for automatic scrolling, i.e. automatic scrolling
4529 will not scroll a window to a column less than the value returned
4530 by this function. */)
4532 register Lisp_Object arg
;
4536 struct window
*w
= XWINDOW (selected_window
);
4539 XSETFASTINT (arg
, window_internal_width (w
) - 2);
4541 arg
= Fprefix_numeric_value (arg
);
4543 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
4544 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
4546 if (interactive_p (0))
4547 w
->min_hscroll
= w
->hscroll
;
4552 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window
, Sminibuffer_selected_window
, 0, 0, 0,
4553 doc
: /* Return the window which was selected when entering the minibuffer.
4554 Returns nil, if current window is not a minibuffer window. */)
4557 if (minibuf_level
> 0
4558 && MINI_WINDOW_P (XWINDOW (selected_window
))
4559 && !NILP (minibuf_selected_window
)
4560 && WINDOW_LIVE_P (minibuf_selected_window
))
4561 return minibuf_selected_window
;
4566 /* Value is the number of lines actually displayed in window W,
4567 as opposed to its height. */
4570 displayed_window_lines (w
)
4574 struct text_pos start
;
4575 int height
= window_box_height (w
);
4576 struct buffer
*old_buffer
;
4579 if (XBUFFER (w
->buffer
) != current_buffer
)
4581 old_buffer
= current_buffer
;
4582 set_buffer_internal (XBUFFER (w
->buffer
));
4587 /* In case W->start is out of the accessible range, do something
4588 reasonable. This happens in Info mode when Info-scroll-down
4589 calls (recenter -1) while W->start is 1. */
4590 if (XMARKER (w
->start
)->charpos
< BEGV
)
4591 SET_TEXT_POS (start
, BEGV
, BEGV_BYTE
);
4592 else if (XMARKER (w
->start
)->charpos
> ZV
)
4593 SET_TEXT_POS (start
, ZV
, ZV_BYTE
);
4595 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4597 start_display (&it
, w
, start
);
4598 move_it_vertically (&it
, height
);
4599 bottom_y
= line_bottom_y (&it
);
4601 /* Add in empty lines at the bottom of the window. */
4602 if (bottom_y
< height
)
4604 int uy
= CANON_Y_UNIT (it
.f
);
4605 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
4609 set_buffer_internal (old_buffer
);
4615 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
4616 doc
: /* Center point in window and redisplay frame.
4617 With prefix argument ARG, recenter putting point on screen line ARG
4618 relative to the current window. If ARG is negative, it counts up from the
4619 bottom of the window. (ARG should be less than the height of the window.)
4621 If ARG is omitted or nil, erase the entire frame and then
4622 redraw with point in the center of the current window.
4623 Just C-u as prefix means put point in the center of the window
4624 and redisplay normally--don't erase and redraw the frame. */)
4626 register Lisp_Object arg
;
4628 struct window
*w
= XWINDOW (selected_window
);
4629 struct buffer
*buf
= XBUFFER (w
->buffer
);
4630 struct buffer
*obuf
= current_buffer
;
4632 int charpos
, bytepos
;
4634 /* If redisplay is suppressed due to an error, try again. */
4635 obuf
->display_error_modiff
= 0;
4641 /* Invalidate pixel data calculated for all compositions. */
4642 for (i
= 0; i
< n_compositions
; i
++)
4643 composition_table
[i
]->font
= NULL
;
4645 Fredraw_frame (w
->frame
);
4646 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
4649 else if (CONSP (arg
)) /* Just C-u. */
4653 arg
= Fprefix_numeric_value (arg
);
4657 set_buffer_internal (buf
);
4659 /* Handle centering on a graphical frame specially. Such frames can
4660 have variable-height lines and centering point on the basis of
4661 line counts would lead to strange effects. */
4662 if (FRAME_WINDOW_P (XFRAME (w
->frame
)))
4669 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
4670 start_display (&it
, w
, pt
);
4671 move_it_vertically (&it
, - window_box_height (w
) / 2);
4672 charpos
= IT_CHARPOS (it
);
4673 bytepos
= IT_BYTEPOS (it
);
4675 else if (XINT (arg
) < 0)
4679 int y0
, y1
, h
, nlines
;
4681 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
4682 start_display (&it
, w
, pt
);
4685 /* The amount of pixels we have to move back is the window
4686 height minus what's displayed in the line containing PT,
4687 and the lines below. */
4688 nlines
= - XINT (arg
) - 1;
4689 move_it_by_lines (&it
, nlines
, 1);
4691 y1
= line_bottom_y (&it
);
4693 /* If we can't move down NLINES lines because we hit
4694 the end of the buffer, count in some empty lines. */
4695 if (it
.vpos
< nlines
)
4696 y1
+= (nlines
- it
.vpos
) * CANON_Y_UNIT (it
.f
);
4698 h
= window_box_height (w
) - (y1
- y0
);
4700 start_display (&it
, w
, pt
);
4701 move_it_vertically (&it
, - h
);
4702 charpos
= IT_CHARPOS (it
);
4703 bytepos
= IT_BYTEPOS (it
);
4707 struct position pos
;
4708 pos
= *vmotion (PT
, - XINT (arg
), w
);
4709 charpos
= pos
.bufpos
;
4710 bytepos
= pos
.bytepos
;
4715 struct position pos
;
4716 int ht
= window_internal_height (w
);
4719 arg
= make_number (ht
/ 2);
4720 else if (XINT (arg
) < 0)
4721 arg
= make_number (XINT (arg
) + ht
);
4723 pos
= *vmotion (PT
, - XINT (arg
), w
);
4724 charpos
= pos
.bufpos
;
4725 bytepos
= pos
.bytepos
;
4728 /* Set the new window start. */
4729 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
4730 w
->window_end_valid
= Qnil
;
4731 w
->force_start
= Qt
;
4732 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
4733 w
->start_at_line_beg
= Qt
;
4735 w
->start_at_line_beg
= Qnil
;
4737 set_buffer_internal (obuf
);
4742 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
4744 doc
: /* Return the height in lines of the text display area of WINDOW.
4745 This doesn't include the mode-line (or header-line if any) or any
4746 partial-height lines in the text display area. */)
4750 struct window
*w
= decode_window (window
);
4751 int pixel_height
= window_box_height (w
);
4752 int line_height
= pixel_height
/ CANON_Y_UNIT (XFRAME (w
->frame
));
4753 return make_number (line_height
);
4758 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
4760 doc
: /* Position point relative to window.
4761 With no argument, position point at center of window.
4762 An argument specifies vertical position within the window;
4763 zero means top of window, negative means relative to bottom of window. */)
4767 struct window
*w
= XWINDOW (selected_window
);
4771 window
= selected_window
;
4772 start
= marker_position (w
->start
);
4773 if (start
< BEGV
|| start
> ZV
)
4775 int height
= window_internal_height (w
);
4776 Fvertical_motion (make_number (- (height
/ 2)), window
);
4777 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
4778 w
->start_at_line_beg
= Fbolp ();
4779 w
->force_start
= Qt
;
4782 Fgoto_char (w
->start
);
4784 lines
= displayed_window_lines (w
);
4786 XSETFASTINT (arg
, lines
/ 2);
4789 arg
= Fprefix_numeric_value (arg
);
4791 XSETINT (arg
, XINT (arg
) + lines
);
4794 /* Skip past a partially visible first line. */
4796 XSETINT (arg
, XINT (arg
) + 1);
4798 return Fvertical_motion (arg
, window
);
4803 /***********************************************************************
4804 Window Configuration
4805 ***********************************************************************/
4807 struct save_window_data
4809 EMACS_INT size_from_Lisp_Vector_struct
;
4810 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4811 Lisp_Object frame_width
, frame_height
, frame_menu_bar_lines
;
4812 Lisp_Object frame_tool_bar_lines
;
4813 Lisp_Object selected_frame
;
4814 Lisp_Object current_window
;
4815 Lisp_Object current_buffer
;
4816 Lisp_Object minibuf_scroll_window
;
4817 Lisp_Object minibuf_selected_window
;
4818 Lisp_Object root_window
;
4819 Lisp_Object focus_frame
;
4820 /* Record the values of window-min-width and window-min-height
4821 so that window sizes remain consistent with them. */
4822 Lisp_Object min_width
, min_height
;
4823 /* A vector, each of whose elements is a struct saved_window
4825 Lisp_Object saved_windows
;
4828 /* This is saved as a Lisp_Vector */
4831 /* these first two must agree with struct Lisp_Vector in lisp.h */
4832 EMACS_INT size_from_Lisp_Vector_struct
;
4833 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4836 Lisp_Object buffer
, start
, pointm
, mark
;
4837 Lisp_Object left
, top
, width
, height
, hscroll
, min_hscroll
;
4838 Lisp_Object parent
, prev
;
4839 Lisp_Object start_at_line_beg
;
4840 Lisp_Object display_table
;
4841 Lisp_Object orig_top
, orig_height
;
4844 #define SAVED_WINDOW_VECTOR_SIZE 17 /* Arg to Fmake_vector */
4846 #define SAVED_WINDOW_N(swv,n) \
4847 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4849 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
4850 doc
: /* Return t if OBJECT is a window-configuration object. */)
4854 if (WINDOW_CONFIGURATIONP (object
))
4859 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
4860 doc
: /* Return the frame that CONFIG, a window-configuration object, is about. */)
4864 register struct save_window_data
*data
;
4865 struct Lisp_Vector
*saved_windows
;
4867 if (! WINDOW_CONFIGURATIONP (config
))
4868 wrong_type_argument (Qwindow_configuration_p
, config
);
4870 data
= (struct save_window_data
*) XVECTOR (config
);
4871 saved_windows
= XVECTOR (data
->saved_windows
);
4872 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4875 DEFUN ("set-window-configuration", Fset_window_configuration
,
4876 Sset_window_configuration
, 1, 1, 0,
4877 doc
: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
4878 CONFIGURATION must be a value previously returned
4879 by `current-window-configuration' (which see).
4880 If CONFIGURATION was made from a frame that is now deleted,
4881 only frame-independent values can be restored. In this case,
4882 the return value is nil. Otherwise the value is t. */)
4884 Lisp_Object configuration
;
4886 register struct save_window_data
*data
;
4887 struct Lisp_Vector
*saved_windows
;
4888 Lisp_Object new_current_buffer
;
4893 while (!WINDOW_CONFIGURATIONP (configuration
))
4894 wrong_type_argument (Qwindow_configuration_p
, configuration
);
4896 data
= (struct save_window_data
*) XVECTOR (configuration
);
4897 saved_windows
= XVECTOR (data
->saved_windows
);
4899 new_current_buffer
= data
->current_buffer
;
4900 if (NILP (XBUFFER (new_current_buffer
)->name
))
4901 new_current_buffer
= Qnil
;
4904 if (XBUFFER (new_current_buffer
) == current_buffer
)
4908 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4911 /* If f is a dead frame, don't bother rebuilding its window tree.
4912 However, there is other stuff we should still try to do below. */
4913 if (FRAME_LIVE_P (f
))
4915 register struct window
*w
;
4916 register struct saved_window
*p
;
4917 struct window
*root_window
;
4918 struct window
**leaf_windows
;
4922 /* If the frame has been resized since this window configuration was
4923 made, we change the frame to the size specified in the
4924 configuration, restore the configuration, and then resize it
4925 back. We keep track of the prevailing height in these variables. */
4926 int previous_frame_height
= FRAME_HEIGHT (f
);
4927 int previous_frame_width
= FRAME_WIDTH (f
);
4928 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
4929 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
4931 /* The mouse highlighting code could get screwed up
4932 if it runs during this. */
4935 if (XFASTINT (data
->frame_height
) != previous_frame_height
4936 || XFASTINT (data
->frame_width
) != previous_frame_width
)
4937 change_frame_size (f
, XFASTINT (data
->frame_height
),
4938 XFASTINT (data
->frame_width
), 0, 0, 0);
4939 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4940 if (XFASTINT (data
->frame_menu_bar_lines
)
4941 != previous_frame_menu_bar_lines
)
4942 x_set_menu_bar_lines (f
, data
->frame_menu_bar_lines
, make_number (0));
4943 #ifdef HAVE_WINDOW_SYSTEM
4944 if (XFASTINT (data
->frame_tool_bar_lines
)
4945 != previous_frame_tool_bar_lines
)
4946 x_set_tool_bar_lines (f
, data
->frame_tool_bar_lines
, make_number (0));
4950 /* "Swap out" point from the selected window
4951 into its buffer. We do this now, before
4952 restoring the window contents, and prevent it from
4953 being done later on when we select a new window. */
4954 if (! NILP (XWINDOW (selected_window
)->buffer
))
4956 w
= XWINDOW (selected_window
);
4957 set_marker_both (w
->pointm
,
4959 BUF_PT (XBUFFER (w
->buffer
)),
4960 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
4963 windows_or_buffers_changed
++;
4964 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4966 /* Problem: Freeing all matrices and later allocating them again
4967 is a serious redisplay flickering problem. What we would
4968 really like to do is to free only those matrices not reused
4970 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4972 = (struct window
**) alloca (count_windows (root_window
)
4973 * sizeof (struct window
*));
4974 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
4976 /* Temporarily avoid any problems with windows that are smaller
4977 than they are supposed to be. */
4978 window_min_height
= 1;
4979 window_min_width
= 1;
4982 Mark all windows now on frame as "deleted".
4983 Restoring the new configuration "undeletes" any that are in it.
4985 Save their current buffers in their height fields, since we may
4986 need it later, if a buffer saved in the configuration is now
4988 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4990 for (k
= 0; k
< saved_windows
->size
; k
++)
4992 p
= SAVED_WINDOW_N (saved_windows
, k
);
4993 w
= XWINDOW (p
->window
);
4996 if (!NILP (p
->parent
))
4997 w
->parent
= SAVED_WINDOW_N (saved_windows
,
4998 XFASTINT (p
->parent
))->window
;
5002 if (!NILP (p
->prev
))
5004 w
->prev
= SAVED_WINDOW_N (saved_windows
,
5005 XFASTINT (p
->prev
))->window
;
5006 XWINDOW (w
->prev
)->next
= p
->window
;
5011 if (!NILP (w
->parent
))
5013 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
5015 XWINDOW (w
->parent
)->vchild
= p
->window
;
5016 XWINDOW (w
->parent
)->hchild
= Qnil
;
5020 XWINDOW (w
->parent
)->hchild
= p
->window
;
5021 XWINDOW (w
->parent
)->vchild
= Qnil
;
5026 /* If we squirreled away the buffer in the window's height,
5028 if (BUFFERP (w
->height
))
5029 w
->buffer
= w
->height
;
5032 w
->width
= p
->width
;
5033 w
->height
= p
->height
;
5034 w
->hscroll
= p
->hscroll
;
5035 w
->min_hscroll
= p
->min_hscroll
;
5036 w
->display_table
= p
->display_table
;
5037 w
->orig_top
= p
->orig_top
;
5038 w
->orig_height
= p
->orig_height
;
5039 XSETFASTINT (w
->last_modified
, 0);
5040 XSETFASTINT (w
->last_overlay_modified
, 0);
5042 /* Reinstall the saved buffer and pointers into it. */
5043 if (NILP (p
->buffer
))
5044 w
->buffer
= p
->buffer
;
5047 if (!NILP (XBUFFER (p
->buffer
)->name
))
5048 /* If saved buffer is alive, install it. */
5050 w
->buffer
= p
->buffer
;
5051 w
->start_at_line_beg
= p
->start_at_line_beg
;
5052 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
5053 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
5054 Fset_marker (XBUFFER (w
->buffer
)->mark
,
5055 p
->mark
, w
->buffer
);
5057 /* As documented in Fcurrent_window_configuration, don't
5058 save the location of point in the buffer which was current
5059 when the window configuration was recorded. */
5060 if (!EQ (p
->buffer
, new_current_buffer
)
5061 && XBUFFER (p
->buffer
) == current_buffer
)
5062 Fgoto_char (w
->pointm
);
5064 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
5065 /* Else unless window has a live buffer, get one. */
5067 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
5068 /* This will set the markers to beginning of visible
5070 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
5071 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
5072 w
->start_at_line_beg
= Qt
;
5075 /* Keeping window's old buffer; make sure the markers
5078 /* Set window markers at start of visible range. */
5079 if (XMARKER (w
->start
)->buffer
== 0)
5080 set_marker_restricted (w
->start
, make_number (0),
5082 if (XMARKER (w
->pointm
)->buffer
== 0)
5083 set_marker_restricted_both (w
->pointm
, w
->buffer
,
5084 BUF_PT (XBUFFER (w
->buffer
)),
5085 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
5086 w
->start_at_line_beg
= Qt
;
5091 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
5092 /* Prevent "swapping out point" in the old selected window
5093 using the buffer that has been restored into it.
5094 That swapping out has already been done,
5095 near the beginning of this function. */
5096 selected_window
= Qnil
;
5097 Fselect_window (data
->current_window
);
5098 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
5101 if (NILP (data
->focus_frame
)
5102 || (FRAMEP (data
->focus_frame
)
5103 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
5104 Fredirect_frame_focus (frame
, data
->focus_frame
);
5106 #if 0 /* I don't understand why this is needed, and it causes problems
5107 when the frame's old selected window has been deleted. */
5108 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
5109 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
5113 /* Set the screen height to the value it had before this function. */
5114 if (previous_frame_height
!= FRAME_HEIGHT (f
)
5115 || previous_frame_width
!= FRAME_WIDTH (f
))
5116 change_frame_size (f
, previous_frame_height
, previous_frame_width
,
5118 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5119 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
5120 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
5122 #ifdef HAVE_WINDOW_SYSTEM
5123 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
5124 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
5129 /* Now, free glyph matrices in windows that were not reused. */
5130 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
5132 if (NILP (leaf_windows
[i
]->buffer
))
5134 /* Assert it's not reused as a combination. */
5135 xassert (NILP (leaf_windows
[i
]->hchild
)
5136 && NILP (leaf_windows
[i
]->vchild
));
5137 free_window_matrices (leaf_windows
[i
]);
5139 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
5143 /* If more than one window shows the new and old current buffer,
5144 don't try to preserve point in that buffer. */
5145 if (old_point
> 0 && n
> 1)
5152 /* Fselect_window will have made f the selected frame, so we
5153 reselect the proper frame here. Fhandle_switch_frame will change the
5154 selected window too, but that doesn't make the call to
5155 Fselect_window above totally superfluous; it still sets f's
5157 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
5158 do_switch_frame (data
->selected_frame
, 0, 0);
5160 if (! NILP (Vwindow_configuration_change_hook
)
5161 && ! NILP (Vrun_hooks
))
5162 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
5165 if (!NILP (new_current_buffer
))
5167 Fset_buffer (new_current_buffer
);
5169 /* If the buffer that is current now is the same
5170 that was current before setting the window configuration,
5171 don't alter its PT. */
5176 /* Restore the minimum heights recorded in the configuration. */
5177 window_min_height
= XINT (data
->min_height
);
5178 window_min_width
= XINT (data
->min_width
);
5180 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
5181 minibuf_selected_window
= data
->minibuf_selected_window
;
5183 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
5186 /* Mark all windows now on frame as deleted
5187 by setting their buffers to nil. */
5190 delete_all_subwindows (w
)
5191 register struct window
*w
;
5193 if (!NILP (w
->next
))
5194 delete_all_subwindows (XWINDOW (w
->next
));
5195 if (!NILP (w
->vchild
))
5196 delete_all_subwindows (XWINDOW (w
->vchild
));
5197 if (!NILP (w
->hchild
))
5198 delete_all_subwindows (XWINDOW (w
->hchild
));
5200 w
->height
= w
->buffer
; /* See Fset_window_configuration for excuse. */
5202 if (!NILP (w
->buffer
))
5205 /* We set all three of these fields to nil, to make sure that we can
5206 distinguish this dead window from any live window. Live leaf
5207 windows will have buffer set, and combination windows will have
5208 vchild or hchild set. */
5213 Vwindow_list
= Qnil
;
5217 count_windows (window
)
5218 register struct window
*window
;
5220 register int count
= 1;
5221 if (!NILP (window
->next
))
5222 count
+= count_windows (XWINDOW (window
->next
));
5223 if (!NILP (window
->vchild
))
5224 count
+= count_windows (XWINDOW (window
->vchild
));
5225 if (!NILP (window
->hchild
))
5226 count
+= count_windows (XWINDOW (window
->hchild
));
5231 /* Fill vector FLAT with leaf windows under W, starting at index I.
5232 Value is last index + 1. */
5235 get_leaf_windows (w
, flat
, i
)
5237 struct window
**flat
;
5242 if (!NILP (w
->hchild
))
5243 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
5244 else if (!NILP (w
->vchild
))
5245 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
5249 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5256 /* Return a pointer to the glyph W's physical cursor is on. Value is
5257 null if W's current matrix is invalid, so that no meaningfull glyph
5261 get_phys_cursor_glyph (w
)
5264 struct glyph_row
*row
;
5265 struct glyph
*glyph
;
5267 if (w
->phys_cursor
.vpos
>= 0
5268 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
5269 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
5271 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
5272 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
5281 save_window_save (window
, vector
, i
)
5283 struct Lisp_Vector
*vector
;
5286 register struct saved_window
*p
;
5287 register struct window
*w
;
5288 register Lisp_Object tem
;
5290 for (;!NILP (window
); window
= w
->next
)
5292 p
= SAVED_WINDOW_N (vector
, i
);
5293 w
= XWINDOW (window
);
5295 XSETFASTINT (w
->temslot
, i
++);
5297 p
->buffer
= w
->buffer
;
5300 p
->width
= w
->width
;
5301 p
->height
= w
->height
;
5302 p
->hscroll
= w
->hscroll
;
5303 p
->min_hscroll
= w
->min_hscroll
;
5304 p
->display_table
= w
->display_table
;
5305 p
->orig_top
= w
->orig_top
;
5306 p
->orig_height
= w
->orig_height
;
5307 if (!NILP (w
->buffer
))
5309 /* Save w's value of point in the window configuration.
5310 If w is the selected window, then get the value of point
5311 from the buffer; pointm is garbage in the selected window. */
5312 if (EQ (window
, selected_window
))
5314 p
->pointm
= Fmake_marker ();
5315 set_marker_both (p
->pointm
, w
->buffer
,
5316 BUF_PT (XBUFFER (w
->buffer
)),
5317 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
5320 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
5322 p
->start
= Fcopy_marker (w
->start
, Qnil
);
5323 p
->start_at_line_beg
= w
->start_at_line_beg
;
5325 tem
= XBUFFER (w
->buffer
)->mark
;
5326 p
->mark
= Fcopy_marker (tem
, Qnil
);
5333 p
->start_at_line_beg
= Qnil
;
5336 if (NILP (w
->parent
))
5339 p
->parent
= XWINDOW (w
->parent
)->temslot
;
5344 p
->prev
= XWINDOW (w
->prev
)->temslot
;
5346 if (!NILP (w
->vchild
))
5347 i
= save_window_save (w
->vchild
, vector
, i
);
5348 if (!NILP (w
->hchild
))
5349 i
= save_window_save (w
->hchild
, vector
, i
);
5355 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
5356 Scurrent_window_configuration
, 0, 1, 0,
5357 doc
: /* Return an object representing the current window configuration of FRAME.
5358 If FRAME is nil or omitted, use the selected frame.
5359 This describes the number of windows, their sizes and current buffers,
5360 and for each displayed buffer, where display starts, and the positions of
5361 point and mark. An exception is made for point in the current buffer:
5362 its value is -not- saved.
5363 This also records the currently selected frame, and FRAME's focus
5364 redirection (see `redirect-frame-focus'). */)
5368 register Lisp_Object tem
;
5369 register int n_windows
;
5370 register struct save_window_data
*data
;
5371 register struct Lisp_Vector
*vec
;
5376 frame
= selected_frame
;
5377 CHECK_LIVE_FRAME (frame
);
5380 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5381 vec
= allocate_other_vector (VECSIZE (struct save_window_data
));
5382 data
= (struct save_window_data
*)vec
;
5384 XSETFASTINT (data
->frame_width
, FRAME_WIDTH (f
));
5385 XSETFASTINT (data
->frame_height
, FRAME_HEIGHT (f
));
5386 XSETFASTINT (data
->frame_menu_bar_lines
, FRAME_MENU_BAR_LINES (f
));
5387 XSETFASTINT (data
->frame_tool_bar_lines
, FRAME_TOOL_BAR_LINES (f
));
5388 data
->selected_frame
= selected_frame
;
5389 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
5390 XSETBUFFER (data
->current_buffer
, current_buffer
);
5391 data
->minibuf_scroll_window
= minibuf_level
> 0 ? Vminibuf_scroll_window
: Qnil
;
5392 data
->minibuf_selected_window
= minibuf_level
> 0 ? minibuf_selected_window
: Qnil
;
5393 data
->root_window
= FRAME_ROOT_WINDOW (f
);
5394 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
5395 XSETINT (data
->min_height
, window_min_height
);
5396 XSETINT (data
->min_width
, window_min_width
);
5397 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
5398 data
->saved_windows
= tem
;
5399 for (i
= 0; i
< n_windows
; i
++)
5400 XVECTOR (tem
)->contents
[i
]
5401 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
5402 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
5403 XSETWINDOW_CONFIGURATION (tem
, data
);
5407 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
5409 doc
: /* Execute body, preserving window sizes and contents.
5410 Restore which buffer appears in which window, where display starts,
5411 and the value of point and mark for each window.
5412 Also restore the choice of selected window.
5413 Also restore which buffer is current.
5414 Does not restore the value of point in current buffer.
5415 usage: (save-window-excursion BODY ...) */)
5419 register Lisp_Object val
;
5420 register int count
= specpdl_ptr
- specpdl
;
5422 record_unwind_protect (Fset_window_configuration
,
5423 Fcurrent_window_configuration (Qnil
));
5424 val
= Fprogn (args
);
5425 return unbind_to (count
, val
);
5429 /***********************************************************************
5431 ***********************************************************************/
5433 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
5435 doc
: /* Set width of marginal areas of window WINDOW.
5436 If window is nil, set margins of the currently selected window.
5437 First parameter LEFT-WIDTH specifies the number of character
5438 cells to reserve for the left marginal area. Second parameter
5439 RIGHT-WIDTH does the same for the right marginal area.
5440 A nil width parameter means no margin. */)
5441 (window
, left
, right
)
5442 Lisp_Object window
, left
, right
;
5444 struct window
*w
= decode_window (window
);
5447 CHECK_NUMBER_OR_FLOAT (left
);
5449 CHECK_NUMBER_OR_FLOAT (right
);
5451 /* Check widths < 0 and translate a zero width to nil.
5452 Margins that are too wide have to be checked elsewhere. */
5453 if ((INTEGERP (left
) && XINT (left
) < 0)
5454 || (FLOATP (left
) && XFLOAT_DATA (left
) <= 0))
5455 XSETFASTINT (left
, 0);
5456 if (INTEGERP (left
) && XFASTINT (left
) == 0)
5459 if ((INTEGERP (right
) && XINT (right
) < 0)
5460 || (FLOATP (right
) && XFLOAT_DATA (right
) <= 0))
5461 XSETFASTINT (right
, 0);
5462 if (INTEGERP (right
) && XFASTINT (right
) == 0)
5465 w
->left_margin_width
= left
;
5466 w
->right_margin_width
= right
;
5468 ++windows_or_buffers_changed
;
5469 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
5474 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
5476 doc
: /* Get width of marginal areas of window WINDOW.
5477 If WINDOW is omitted or nil, use the currently selected window.
5478 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5479 If a marginal area does not exist, its width will be returned
5484 struct window
*w
= decode_window (window
);
5485 return Fcons (w
->left_margin_width
, w
->right_margin_width
);
5490 /***********************************************************************
5492 ***********************************************************************/
5494 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 1, 0,
5495 doc
: /* Return the amount by which WINDOW is scrolled vertically.
5496 Use the selected window if WINDOW is nil or omitted.
5497 Value is a multiple of the canonical character height of WINDOW. */)
5506 window
= selected_window
;
5508 CHECK_WINDOW (window
);
5509 w
= XWINDOW (window
);
5510 f
= XFRAME (w
->frame
);
5512 if (FRAME_WINDOW_P (f
))
5513 result
= CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
);
5515 result
= make_number (0);
5520 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
5522 doc
: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
5523 WINDOW nil means use the selected window. VSCROLL is a non-negative
5524 multiple of the canonical character height of WINDOW. */)
5526 Lisp_Object window
, vscroll
;
5532 window
= selected_window
;
5534 CHECK_WINDOW (window
);
5535 CHECK_NUMBER_OR_FLOAT (vscroll
);
5537 w
= XWINDOW (window
);
5538 f
= XFRAME (w
->frame
);
5540 if (FRAME_WINDOW_P (f
))
5542 int old_dy
= w
->vscroll
;
5544 w
->vscroll
= - CANON_Y_UNIT (f
) * XFLOATINT (vscroll
);
5545 w
->vscroll
= min (w
->vscroll
, 0);
5547 /* Adjust glyph matrix of the frame if the virtual display
5548 area becomes larger than before. */
5549 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
5552 /* Prevent redisplay shortcuts. */
5553 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
5556 return Fwindow_vscroll (window
);
5560 /* Call FN for all leaf windows on frame F. FN is called with the
5561 first argument being a pointer to the leaf window, and with
5562 additional argument USER_DATA. Stops when FN returns 0. */
5565 foreach_window (f
, fn
, user_data
)
5567 int (* fn
) P_ ((struct window
*, void *));
5570 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
5574 /* Helper function for foreach_window. Call FN for all leaf windows
5575 reachable from W. FN is called with the first argument being a
5576 pointer to the leaf window, and with additional argument USER_DATA.
5577 Stop when FN returns 0. Value is 0 if stopped by FN. */
5580 foreach_window_1 (w
, fn
, user_data
)
5582 int (* fn
) P_ ((struct window
*, void *));
5587 for (cont
= 1; w
&& cont
;)
5589 if (!NILP (w
->hchild
))
5590 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
5591 else if (!NILP (w
->vchild
))
5592 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
5594 cont
= fn (w
, user_data
);
5596 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5603 /* Freeze or unfreeze the window start of W unless it is a
5604 mini-window or the selected window. FREEZE_P non-null means freeze
5605 the window start. */
5608 freeze_window_start (w
, freeze_p
)
5612 if (w
== XWINDOW (selected_window
)
5613 || MINI_WINDOW_P (w
)
5614 || (MINI_WINDOW_P (XWINDOW (selected_window
))
5615 && ! NILP (Vminibuf_scroll_window
)
5616 && w
== XWINDOW (Vminibuf_scroll_window
)))
5619 w
->frozen_window_start_p
= freeze_p
!= NULL
;
5624 /* Freeze or unfreeze the window starts of all leaf windows on frame
5625 F, except the selected window and a mini-window. FREEZE_P non-zero
5626 means freeze the window start. */
5629 freeze_window_starts (f
, freeze_p
)
5633 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
5637 /***********************************************************************
5639 ***********************************************************************/
5641 /* Return 1 if window configurations C1 and C2
5642 describe the same state of affairs. This is used by Fequal. */
5645 compare_window_configurations (c1
, c2
, ignore_positions
)
5647 int ignore_positions
;
5649 register struct save_window_data
*d1
, *d2
;
5650 struct Lisp_Vector
*sw1
, *sw2
;
5653 if (!WINDOW_CONFIGURATIONP (c1
))
5654 wrong_type_argument (Qwindow_configuration_p
, c1
);
5655 if (!WINDOW_CONFIGURATIONP (c2
))
5656 wrong_type_argument (Qwindow_configuration_p
, c2
);
5658 d1
= (struct save_window_data
*) XVECTOR (c1
);
5659 d2
= (struct save_window_data
*) XVECTOR (c2
);
5660 sw1
= XVECTOR (d1
->saved_windows
);
5661 sw2
= XVECTOR (d2
->saved_windows
);
5663 if (! EQ (d1
->frame_width
, d2
->frame_width
))
5665 if (! EQ (d1
->frame_height
, d2
->frame_height
))
5667 if (! EQ (d1
->frame_menu_bar_lines
, d2
->frame_menu_bar_lines
))
5669 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
5671 /* Don't compare the current_window field directly.
5672 Instead see w1_is_current and w2_is_current, below. */
5673 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
5675 if (! ignore_positions
)
5677 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
5679 if (! EQ (d1
->minibuf_selected_window
, d2
->minibuf_selected_window
))
5682 /* Don't compare the root_window field.
5683 We don't require the two configurations
5684 to use the same window object,
5685 and the two root windows must be equivalent
5686 if everything else compares equal. */
5687 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
5689 if (! EQ (d1
->min_width
, d2
->min_width
))
5691 if (! EQ (d1
->min_height
, d2
->min_height
))
5694 /* Verify that the two confis have the same number of windows. */
5695 if (sw1
->size
!= sw2
->size
)
5698 for (i
= 0; i
< sw1
->size
; i
++)
5700 struct saved_window
*p1
, *p2
;
5701 int w1_is_current
, w2_is_current
;
5703 p1
= SAVED_WINDOW_N (sw1
, i
);
5704 p2
= SAVED_WINDOW_N (sw2
, i
);
5706 /* Verify that the current windows in the two
5707 configurations correspond to each other. */
5708 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
5709 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
5711 if (w1_is_current
!= w2_is_current
)
5714 /* Verify that the corresponding windows do match. */
5715 if (! EQ (p1
->buffer
, p2
->buffer
))
5717 if (! EQ (p1
->left
, p2
->left
))
5719 if (! EQ (p1
->top
, p2
->top
))
5721 if (! EQ (p1
->width
, p2
->width
))
5723 if (! EQ (p1
->height
, p2
->height
))
5725 if (! EQ (p1
->display_table
, p2
->display_table
))
5727 if (! EQ (p1
->parent
, p2
->parent
))
5729 if (! EQ (p1
->prev
, p2
->prev
))
5731 if (! ignore_positions
)
5733 if (! EQ (p1
->hscroll
, p2
->hscroll
))
5735 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
5737 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
5739 if (NILP (Fequal (p1
->start
, p2
->start
)))
5741 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
5743 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
5751 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
5752 Scompare_window_configurations
, 2, 2, 0,
5753 doc
: /* Compare two window configurations as regards the structure of windows.
5754 This function ignores details such as the values of point and mark
5755 and scrolling positions. */)
5759 if (compare_window_configurations (x
, y
, 1))
5767 struct frame
*f
= make_terminal_frame ();
5768 XSETFRAME (selected_frame
, f
);
5769 Vterminal_frame
= selected_frame
;
5770 minibuf_window
= f
->minibuffer_window
;
5771 selected_window
= f
->selected_window
;
5772 last_nonminibuf_frame
= f
;
5774 window_initialized
= 1;
5780 Vwindow_list
= Qnil
;
5786 Qwindow_size_fixed
= intern ("window-size-fixed");
5787 staticpro (&Qwindow_size_fixed
);
5789 staticpro (&Qwindow_configuration_change_hook
);
5790 Qwindow_configuration_change_hook
5791 = intern ("window-configuration-change-hook");
5793 Qwindowp
= intern ("windowp");
5794 staticpro (&Qwindowp
);
5796 Qwindow_configuration_p
= intern ("window-configuration-p");
5797 staticpro (&Qwindow_configuration_p
);
5799 Qwindow_live_p
= intern ("window-live-p");
5800 staticpro (&Qwindow_live_p
);
5802 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
5803 staticpro (&Qtemp_buffer_show_hook
);
5805 staticpro (&Vwindow_list
);
5807 minibuf_selected_window
= Qnil
;
5808 staticpro (&minibuf_selected_window
);
5810 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
5811 doc
: /* Non-nil means call as function to display a help buffer.
5812 The function is called with one argument, the buffer to be displayed.
5813 Used by `with-output-to-temp-buffer'.
5814 If this function is used, then it must do the entire job of showing
5815 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
5816 Vtemp_buffer_show_function
= Qnil
;
5818 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
5819 doc
: /* If non-nil, function to call to handle `display-buffer'.
5820 It will receive two args, the buffer and a flag which if non-nil means
5821 that the currently selected window is not acceptable.
5822 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
5823 work using this function. */);
5824 Vdisplay_buffer_function
= Qnil
;
5826 DEFVAR_LISP ("even-window-heights", &Veven_window_heights
,
5827 doc
: /* *If non-nil, `display-buffer' should even the window heights.
5828 If nil, `display-buffer' will leave the window configuration alone. */);
5829 Veven_window_heights
= Qt
;
5831 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
5832 doc
: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
5833 Vminibuf_scroll_window
= Qnil
;
5835 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows
,
5836 doc
: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
5837 If the minibuffer is active, the `minibuffer-scroll-window' mode line
5838 is displayed in the `mode-line' face. */);
5839 mode_line_in_non_selected_windows
= 1;
5841 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
5842 doc
: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
5843 Vother_window_scroll_buffer
= Qnil
;
5845 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
5846 doc
: /* *Non-nil means `display-buffer' should make a separate frame. */);
5849 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames
,
5850 doc
: /* *Non-nil means `display-buffer' should reuse frames.
5851 If the buffer in question is already displayed in a frame, raise that frame. */);
5852 display_buffer_reuse_frames
= 0;
5854 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
5855 doc
: /* Function to call to handle automatic new frame creation.
5856 It is called with no arguments and should return a newly created frame.
5858 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
5859 where `pop-up-frame-alist' would hold the default frame parameters. */);
5860 Vpop_up_frame_function
= Qnil
;
5862 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
5863 doc
: /* *List of buffer names that should have their own special frames.
5864 Displaying a buffer whose name is in this list makes a special frame for it
5865 using `special-display-function'. See also `special-display-regexps'.
5867 An element of the list can be a list instead of just a string.
5868 There are two ways to use a list as an element:
5869 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
5870 In the first case, FRAME-PARAMETERS are used to create the frame.
5871 In the latter case, FUNCTION is called with BUFFER as the first argument,
5872 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
5873 All this is done by the function found in `special-display-function'.
5875 If this variable appears \"not to work\", because you add a name to it
5876 but that buffer still appears in the selected window, look at the
5877 values of `same-window-buffer-names' and `same-window-regexps'.
5878 Those variables take precedence over this one. */);
5879 Vspecial_display_buffer_names
= Qnil
;
5881 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
5882 doc
: /* *List of regexps saying which buffers should have their own special frames.
5883 If a buffer name matches one of these regexps, it gets its own frame.
5884 Displaying a buffer whose name is in this list makes a special frame for it
5885 using `special-display-function'.
5887 An element of the list can be a list instead of just a string.
5888 There are two ways to use a list as an element:
5889 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
5890 In the first case, FRAME-PARAMETERS are used to create the frame.
5891 In the latter case, FUNCTION is called with the buffer as first argument,
5892 followed by OTHER-ARGS--it can display the buffer in any way it likes.
5893 All this is done by the function found in `special-display-function'.
5895 If this variable appears \"not to work\", because you add a regexp to it
5896 but the matching buffers still appear in the selected window, look at the
5897 values of `same-window-buffer-names' and `same-window-regexps'.
5898 Those variables take precedence over this one. */);
5899 Vspecial_display_regexps
= Qnil
;
5901 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
5902 doc
: /* Function to call to make a new frame for a special buffer.
5903 It is called with two arguments, the buffer and optional buffer specific
5904 data, and should return a window displaying that buffer.
5905 The default value makes a separate frame for the buffer,
5906 using `special-display-frame-alist' to specify the frame parameters.
5908 A buffer is special if its is listed in `special-display-buffer-names'
5909 or matches a regexp in `special-display-regexps'. */);
5910 Vspecial_display_function
= Qnil
;
5912 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
5913 doc
: /* *List of buffer names that should appear in the selected window.
5914 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
5915 switches to it in the selected window, rather than making it appear
5916 in some other window.
5918 An element of the list can be a cons cell instead of just a string.
5919 Then the car must be a string, which specifies the buffer name.
5920 This is for compatibility with `special-display-buffer-names';
5921 the cdr of the cons cell is ignored.
5923 See also `same-window-regexps'. */);
5924 Vsame_window_buffer_names
= Qnil
;
5926 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
5927 doc
: /* *List of regexps saying which buffers should appear in the selected window.
5928 If a buffer name matches one of these regexps, then displaying it
5929 using `display-buffer' or `pop-to-buffer' switches to it
5930 in the selected window, rather than making it appear in some other window.
5932 An element of the list can be a cons cell instead of just a string.
5933 Then the car must be a string, which specifies the buffer name.
5934 This is for compatibility with `special-display-buffer-names';
5935 the cdr of the cons cell is ignored.
5937 See also `same-window-buffer-names'. */);
5938 Vsame_window_regexps
= Qnil
;
5940 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
5941 doc
: /* *Non-nil means display-buffer should make new windows. */);
5944 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
5945 doc
: /* *Number of lines of continuity when scrolling by screenfuls. */);
5946 next_screen_context_lines
= 2;
5948 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
5949 doc
: /* *display-buffer would prefer to split the largest window if this large.
5950 If there is only one window, it is split regardless of this value. */);
5951 split_height_threshold
= 500;
5953 DEFVAR_INT ("window-min-height", &window_min_height
,
5954 doc
: /* *Delete any window less than this tall (including its mode line). */);
5955 window_min_height
= 4;
5957 DEFVAR_INT ("window-min-width", &window_min_width
,
5958 doc
: /* *Delete any window less than this wide. */);
5959 window_min_width
= 10;
5961 DEFVAR_LISP ("scroll-preserve-screen-position",
5962 &Vscroll_preserve_screen_position
,
5963 doc
: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
5964 Vscroll_preserve_screen_position
= Qnil
;
5966 DEFVAR_LISP ("window-configuration-change-hook",
5967 &Vwindow_configuration_change_hook
,
5968 doc
: /* Functions to call when window configuration changes.
5969 The selected frame is the one whose configuration has changed. */);
5970 Vwindow_configuration_change_hook
= Qnil
;
5972 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed
,
5973 doc
: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
5974 Emacs won't change the size of any window displaying that buffer,
5975 unless you explicitly change the size, or Emacs has no other choice.
5976 This variable automatically becomes buffer-local when set. */);
5977 Fmake_variable_buffer_local (Qwindow_size_fixed
);
5978 window_size_fixed
= 0;
5980 defsubr (&Sselected_window
);
5981 defsubr (&Sminibuffer_window
);
5982 defsubr (&Swindow_minibuffer_p
);
5983 defsubr (&Swindowp
);
5984 defsubr (&Swindow_live_p
);
5985 defsubr (&Spos_visible_in_window_p
);
5986 defsubr (&Swindow_buffer
);
5987 defsubr (&Swindow_height
);
5988 defsubr (&Swindow_width
);
5989 defsubr (&Swindow_hscroll
);
5990 defsubr (&Sset_window_hscroll
);
5991 defsubr (&Swindow_redisplay_end_trigger
);
5992 defsubr (&Sset_window_redisplay_end_trigger
);
5993 defsubr (&Swindow_edges
);
5994 defsubr (&Scoordinates_in_window_p
);
5995 defsubr (&Swindow_at
);
5996 defsubr (&Swindow_point
);
5997 defsubr (&Swindow_start
);
5998 defsubr (&Swindow_end
);
5999 defsubr (&Sset_window_point
);
6000 defsubr (&Sset_window_start
);
6001 defsubr (&Swindow_dedicated_p
);
6002 defsubr (&Sset_window_dedicated_p
);
6003 defsubr (&Swindow_display_table
);
6004 defsubr (&Sset_window_display_table
);
6005 defsubr (&Snext_window
);
6006 defsubr (&Sprevious_window
);
6007 defsubr (&Sother_window
);
6008 defsubr (&Sget_lru_window
);
6009 defsubr (&Sget_largest_window
);
6010 defsubr (&Sget_buffer_window
);
6011 defsubr (&Sdelete_other_windows
);
6012 defsubr (&Sdelete_windows_on
);
6013 defsubr (&Sreplace_buffer_in_windows
);
6014 defsubr (&Sdelete_window
);
6015 defsubr (&Sset_window_buffer
);
6016 defsubr (&Sselect_window
);
6017 defsubr (&Sspecial_display_p
);
6018 defsubr (&Ssame_window_p
);
6019 defsubr (&Sdisplay_buffer
);
6020 defsubr (&Ssplit_window
);
6021 defsubr (&Senlarge_window
);
6022 defsubr (&Sshrink_window
);
6023 defsubr (&Sscroll_up
);
6024 defsubr (&Sscroll_down
);
6025 defsubr (&Sscroll_left
);
6026 defsubr (&Sscroll_right
);
6027 defsubr (&Sother_window_for_scrolling
);
6028 defsubr (&Sscroll_other_window
);
6029 defsubr (&Sminibuffer_selected_window
);
6030 defsubr (&Srecenter
);
6031 defsubr (&Swindow_text_height
);
6032 defsubr (&Smove_to_window_line
);
6033 defsubr (&Swindow_configuration_p
);
6034 defsubr (&Swindow_configuration_frame
);
6035 defsubr (&Sset_window_configuration
);
6036 defsubr (&Scurrent_window_configuration
);
6037 defsubr (&Ssave_window_excursion
);
6038 defsubr (&Sset_window_margins
);
6039 defsubr (&Swindow_margins
);
6040 defsubr (&Swindow_vscroll
);
6041 defsubr (&Sset_window_vscroll
);
6042 defsubr (&Scompare_window_configurations
);
6043 defsubr (&Swindow_list
);
6049 initial_define_key (control_x_map
, '1', "delete-other-windows");
6050 initial_define_key (control_x_map
, '2', "split-window");
6051 initial_define_key (control_x_map
, '0', "delete-window");
6052 initial_define_key (control_x_map
, 'o', "other-window");
6053 initial_define_key (control_x_map
, '^', "enlarge-window");
6054 initial_define_key (control_x_map
, '<', "scroll-left");
6055 initial_define_key (control_x_map
, '>', "scroll-right");
6057 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
6058 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
6059 initial_define_key (meta_map
, 'v', "scroll-down");
6061 initial_define_key (global_map
, Ctl('L'), "recenter");
6062 initial_define_key (meta_map
, 'r', "move-to-window-line");