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. */
33 #include "dispextern.h"
34 #include "blockinput.h"
35 #include "intervals.h"
39 #endif /* HAVE_X_WINDOWS */
51 #define max(a, b) ((a) < (b) ? (b) : (a))
54 /* Values returned from coordinates_in_window. */
68 Lisp_Object Qwindowp
, Qwindow_live_p
, Qwindow_configuration_p
;
69 Lisp_Object Qwindow_size_fixed
, Qleft_fringe
, Qright_fringe
;
70 extern Lisp_Object Qheight
, Qwidth
;
72 static struct window
*decode_window
P_ ((Lisp_Object
));
73 static Lisp_Object select_window_1
P_ ((Lisp_Object
, int));
74 static int count_windows
P_ ((struct window
*));
75 static int get_leaf_windows
P_ ((struct window
*, struct window
**, int));
76 static void window_scroll
P_ ((Lisp_Object
, int, int, int));
77 static void window_scroll_pixel_based
P_ ((Lisp_Object
, int, int, int));
78 static void window_scroll_line_based
P_ ((Lisp_Object
, int, int, int));
79 static int window_min_size_1
P_ ((struct window
*, int));
80 static int window_min_size
P_ ((struct window
*, int, int, int *));
81 static void size_window
P_ ((Lisp_Object
, int, int, int));
82 static int freeze_window_start
P_ ((struct window
*, void *));
83 static int window_fixed_size_p
P_ ((struct window
*, int, int));
84 static void enlarge_window
P_ ((Lisp_Object
, int, int));
85 static Lisp_Object window_list
P_ ((void));
86 static int add_window_to_list
P_ ((struct window
*, void *));
87 static int candidate_window_p
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
89 static Lisp_Object next_window
P_ ((Lisp_Object
, Lisp_Object
,
91 static void decode_next_window_args
P_ ((Lisp_Object
*, Lisp_Object
*,
93 static int foreach_window_1
P_ ((struct window
*,
94 int (* fn
) (struct window
*, void *),
96 static Lisp_Object window_list_1
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
));
98 /* The value of `window-size-fixed'. */
100 int window_size_fixed
;
102 /* This is the window in which the terminal's cursor should
103 be left when nothing is being done with it. This must
104 always be a leaf window, and its buffer is selected by
105 the top level editing loop at the end of each command.
107 This value is always the same as
108 FRAME_SELECTED_WINDOW (selected_frame). */
110 Lisp_Object selected_window
;
112 /* A list of all windows for use by next_window and Fwindow_list.
113 Functions creating or deleting windows should invalidate this cache
114 by setting it to nil. */
116 Lisp_Object Vwindow_list
;
118 /* The mini-buffer window of the selected frame.
119 Note that you cannot test for mini-bufferness of an arbitrary window
120 by comparing against this; but you can test for mini-bufferness of
121 the selected window. */
123 Lisp_Object minibuf_window
;
125 /* Non-nil means it is the window for C-M-v to scroll
126 when the mini-buffer is selected. */
128 Lisp_Object Vminibuf_scroll_window
;
130 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
132 Lisp_Object Vother_window_scroll_buffer
;
134 /* Non-nil means it's function to call to display temp buffers. */
136 Lisp_Object Vtemp_buffer_show_function
;
138 /* If a window gets smaller than either of these, it is removed. */
140 int window_min_height
;
141 int window_min_width
;
143 /* Nonzero implies Fdisplay_buffer should create windows. */
147 /* Nonzero implies make new frames for Fdisplay_buffer. */
151 /* Nonzero means reuse existing frames for displaying buffers. */
153 int display_buffer_reuse_frames
;
155 /* Non-nil means use this function instead of default */
157 Lisp_Object Vpop_up_frame_function
;
159 /* Function to call to handle Fdisplay_buffer. */
161 Lisp_Object Vdisplay_buffer_function
;
163 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
165 Lisp_Object Veven_window_heights
;
167 /* List of buffer *names* for buffers that should have their own frames. */
169 Lisp_Object Vspecial_display_buffer_names
;
171 /* List of regexps for buffer names that should have their own frames. */
173 Lisp_Object Vspecial_display_regexps
;
175 /* Function to pop up a special frame. */
177 Lisp_Object Vspecial_display_function
;
179 /* List of buffer *names* for buffers to appear in selected window. */
181 Lisp_Object Vsame_window_buffer_names
;
183 /* List of regexps for buffer names to appear in selected window. */
185 Lisp_Object Vsame_window_regexps
;
187 /* Hook run at end of temp_output_buffer_show. */
189 Lisp_Object Qtemp_buffer_show_hook
;
191 /* Fdisplay_buffer always splits the largest window
192 if that window is more than this high. */
194 int split_height_threshold
;
196 /* Number of lines of continuity in scrolling by screenfuls. */
198 int next_screen_context_lines
;
200 /* Incremented for each window created. */
202 static int sequence_number
;
204 /* Nonzero after init_window_once has finished. */
206 static int window_initialized
;
208 /* Hook to run when window config changes. */
210 Lisp_Object Qwindow_configuration_change_hook
;
211 Lisp_Object Vwindow_configuration_change_hook
;
213 /* Nonzero means scroll commands try to put point
214 at the same screen height as previously. */
216 Lisp_Object Vscroll_preserve_screen_position
;
218 #if 0 /* This isn't used anywhere. */
219 /* Nonzero means we can split a frame even if it is "unsplittable". */
220 static int inhibit_frame_unsplittable
;
223 #define min(a, b) ((a) < (b) ? (a) : (b))
225 extern int scroll_margin
;
227 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
229 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
230 "Returns t if OBJECT is a window.")
234 return WINDOWP (object
) ? Qt
: Qnil
;
237 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
238 "Returns t if OBJECT is a window which is currently visible.")
242 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
249 register struct window
*p
;
250 register struct Lisp_Vector
*vec
;
253 vec
= allocate_vectorlike ((EMACS_INT
) VECSIZE (struct window
));
254 for (i
= 0; i
< VECSIZE (struct window
); i
++)
255 vec
->contents
[i
] = Qnil
;
256 vec
->size
= VECSIZE (struct window
);
257 p
= (struct window
*) vec
;
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
->must_be_updated_p
= 0;
279 XSETFASTINT (p
->window_end_vpos
, 0);
280 XSETFASTINT (p
->window_end_pos
, 0);
281 p
->window_end_valid
= Qnil
;
284 XSETFASTINT (p
->last_point
, 0);
285 p
->frozen_window_start_p
= 0;
291 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
292 "Return the window that the cursor now appears in and commands apply to.")
295 return selected_window
;
298 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
299 "Return the window used now for minibuffers.\n\
300 If the optional argument FRAME is specified, return the minibuffer window\n\
301 used by that frame.")
306 frame
= selected_frame
;
307 CHECK_LIVE_FRAME (frame
, 0);
308 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
311 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
312 "Returns non-nil if WINDOW is a minibuffer window.")
316 struct window
*w
= decode_window (window
);
317 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
321 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
322 Spos_visible_in_window_p
, 0, 3, 0,
323 "Return t if position POS is currently on the frame in WINDOW.\n\
324 Return nil if that position is scrolled vertically out of view.\n\
325 If a character is only partially visible, nil is returned, unless the\n\
326 optional argument PARTIALLY is non-nil.\n\
327 POS defaults to point in WINDOW; WINDOW defaults to the selected window.")
328 (pos
, window
, partially
)
329 Lisp_Object pos
, window
, partially
;
331 register struct window
*w
;
333 register struct buffer
*buf
;
335 Lisp_Object in_window
;
338 w
= decode_window (window
);
339 buf
= XBUFFER (w
->buffer
);
340 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
344 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
347 else if (w
== XWINDOW (selected_window
))
350 posint
= XMARKER (w
->pointm
)->charpos
;
352 /* If position is above window start, it's not visible. */
353 if (posint
< CHARPOS (top
))
355 else if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
)
356 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (buf
)
357 && posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
))
359 /* If frame is up-to-date, and POSINT is < window end pos, use
360 that info. This doesn't work for POSINT == end pos, because
361 the window end pos is actually the position _after_ the last
362 char in the window. */
363 if (NILP (partially
))
365 pos_visible_p (w
, posint
, &fully_p
, NILP (partially
));
366 in_window
= fully_p
? Qt
: Qnil
;
371 else if (posint
> BUF_ZV (buf
))
373 else if (CHARPOS (top
) < BUF_BEGV (buf
) || CHARPOS (top
) > BUF_ZV (buf
))
374 /* If window start is out of range, do something reasonable. */
378 if (pos_visible_p (w
, posint
, &fully_p
, NILP (partially
)))
379 in_window
= !NILP (partially
) || fully_p
? Qt
: Qnil
;
388 static struct window
*
389 decode_window (window
)
390 register Lisp_Object window
;
393 return XWINDOW (selected_window
);
395 CHECK_LIVE_WINDOW (window
, 0);
396 return XWINDOW (window
);
399 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
400 "Return the buffer that WINDOW is displaying.")
404 return decode_window (window
)->buffer
;
407 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
408 "Return the number of lines in WINDOW (including its mode line).")
412 return decode_window (window
)->height
;
415 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
416 "Return the number of display columns in WINDOW.\n\
417 This is the width that is usable columns available for text in WINDOW.\n\
418 If you want to find out how many columns WINDOW takes up,\n\
419 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
423 return make_number (window_internal_width (decode_window (window
)));
426 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
427 "Return the number of columns by which WINDOW is scrolled from left margin.")
431 return decode_window (window
)->hscroll
;
434 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
435 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
436 NCOL should be zero or positive.")
438 Lisp_Object window
, ncol
;
440 struct window
*w
= decode_window (window
);
443 CHECK_NUMBER (ncol
, 1);
444 hscroll
= max (0, XINT (ncol
));
446 /* Prevent redisplay shortcuts when changing the hscroll. */
447 if (XINT (w
->hscroll
) != hscroll
)
448 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
450 w
->hscroll
= make_number (hscroll
);
454 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
455 Swindow_redisplay_end_trigger
, 0, 1, 0,
456 "Return WINDOW's redisplay end trigger value.\n\
457 See `set-window-redisplay-end-trigger' for more information.")
461 return decode_window (window
)->redisplay_end_trigger
;
464 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
465 Sset_window_redisplay_end_trigger
, 2, 2, 0,
466 "Set WINDOW's redisplay end trigger value to VALUE.\n\
467 VALUE should be a buffer position (typically a marker) or nil.\n\
468 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
469 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
470 with two arguments: WINDOW, and the end trigger value.\n\
471 Afterwards the end-trigger value is reset to nil.")
473 register Lisp_Object window
, value
;
475 register struct window
*w
;
477 w
= decode_window (window
);
478 w
->redisplay_end_trigger
= value
;
482 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
483 "Return a list of the edge coordinates of WINDOW.\n\
484 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
485 RIGHT is one more than the rightmost column used by WINDOW,\n\
486 and BOTTOM is one more than the bottommost row used by WINDOW\n\
491 register struct window
*w
= decode_window (window
);
493 return Fcons (w
->left
, Fcons (w
->top
,
494 Fcons (make_number (WINDOW_RIGHT_EDGE (w
)),
495 Fcons (make_number (XFASTINT (w
->top
)
496 + XFASTINT (w
->height
)),
500 /* Test if the character at column *X, row *Y is within window W.
501 If it is not, return 0;
502 if it is in the window's text area,
503 set *x and *y to its location relative to the upper left corner
506 if it is on the window's modeline, return 2;
507 if it is on the border between the window and its right sibling,
509 if it is on the window's top line, return 4;
510 if it is in the bitmap area to the left/right of the window,
511 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
513 X and Y are frame relative pixel coordinates. */
515 static enum window_part
516 coordinates_in_window (w
, x
, y
)
517 register struct window
*w
;
520 /* Let's make this a global enum later, instead of using numbers
522 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
523 int left_x
, right_x
, top_y
, bottom_y
;
524 int flags_area_width
= FRAME_LEFT_FLAGS_AREA_WIDTH (f
);
525 enum window_part part
;
526 int ux
= CANON_X_UNIT (f
), uy
= CANON_Y_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? */
598 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * ux
)
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
- flags_area_width
) < 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 flags areas 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 flags areas 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 "Return non-nil if COORDINATES are in WINDOW.\n\
670 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
671 measured in characters from the upper-left corner of the frame.\n\
672 \(0 . 0) denotes the character in the upper left corner of the\n\
674 If COORDINATES are in the text portion of WINDOW,\n\
675 the coordinates relative to the window are returned.\n\
676 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
677 If they are in the top mode line of WINDOW, `header-line' is returned.\n\
678 If they are in the fringe to the left of the window,\n\
679 `left-fringe' is returned, if they are in the area on the right of\n\
680 the window, `right-fringe' is returned.\n\
681 If they are on the border between WINDOW and its right sibling,\n\
682 `vertical-line' is returned.")
683 (coordinates
, window
)
684 register Lisp_Object coordinates
, window
;
691 CHECK_LIVE_WINDOW (window
, 0);
692 w
= XWINDOW (window
);
693 f
= XFRAME (w
->frame
);
694 CHECK_CONS (coordinates
, 1);
695 lx
= Fcar (coordinates
);
696 ly
= Fcdr (coordinates
);
697 CHECK_NUMBER_OR_FLOAT (lx
, 1);
698 CHECK_NUMBER_OR_FLOAT (ly
, 1);
699 x
= PIXEL_X_FROM_CANON_X (f
, lx
);
700 y
= PIXEL_Y_FROM_CANON_Y (f
, ly
);
702 switch (coordinates_in_window (w
, &x
, &y
))
708 /* X and Y are now window relative pixel coordinates. Convert
709 them to canonical char units before returning them. */
710 return Fcons (CANON_X_FROM_PIXEL_X (f
, x
),
711 CANON_Y_FROM_PIXEL_Y (f
, y
));
716 case ON_VERTICAL_BORDER
:
717 return Qvertical_line
;
725 case ON_RIGHT_FRINGE
:
726 return Qright_fringe
;
734 /* Callback for foreach_window, used in window_from_coordinates.
735 Check if window W contains coordinates specified by USER_DATA which
736 is actually a pointer to a struct check_window_data CW.
738 Check if window W contains coordinates *CW->x and *CW->y. If it
739 does, return W in *CW->window, as Lisp_Object, and return in
740 *CW->part the part of the window under coordinates *X,*Y. Return
741 zero from this function to stop iterating over windows. */
743 struct check_window_data
750 check_window_containing (w
, user_data
)
754 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
755 enum window_part found
;
758 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
759 if (found
!= ON_NOTHING
)
761 *cw
->part
= found
- 1;
762 XSETWINDOW (*cw
->window
, w
);
770 /* Find the window containing frame-relative pixel position X/Y and
771 return it as a Lisp_Object. If X, Y is on the window's modeline,
772 set *PART to 1; if it is on the separating line between the window
773 and its right sibling, set it to 2; otherwise set it to 0. If
774 there is no window under X, Y return nil and leave *PART
775 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
777 This function was previously implemented with a loop cycling over
778 windows with Fnext_window, and starting with the frame's selected
779 window. It turned out that this doesn't work with an
780 implementation of next_window using Vwindow_list, because
781 FRAME_SELECTED_WINDOW (F) is not always contained in the window
782 tree of F when this function is called asynchronously from
783 note_mouse_highlight. The original loop didn't terminate in this
787 window_from_coordinates (f
, x
, y
, part
, tool_bar_p
)
794 struct check_window_data cw
;
797 cw
.window
= &window
, cw
.x
= &x
, cw
.y
= &y
; cw
.part
= part
;
798 foreach_window (f
, check_window_containing
, &cw
);
800 /* If not found above, see if it's in the tool bar window, if a tool
804 && WINDOWP (f
->tool_bar_window
)
805 && XINT (XWINDOW (f
->tool_bar_window
)->height
) > 0
806 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), &x
, &y
)
810 window
= f
->tool_bar_window
;
816 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
817 "Return window containing coordinates X and Y on FRAME.\n\
818 If omitted, FRAME defaults to the currently selected frame.\n\
819 The top left corner of the frame is considered to be row 0,\n\
822 Lisp_Object x
, y
, frame
;
828 frame
= selected_frame
;
829 CHECK_LIVE_FRAME (frame
, 2);
832 /* Check that arguments are integers or floats. */
833 CHECK_NUMBER_OR_FLOAT (x
, 0);
834 CHECK_NUMBER_OR_FLOAT (y
, 1);
836 return window_from_coordinates (f
,
837 PIXEL_X_FROM_CANON_X (f
, x
),
838 PIXEL_Y_FROM_CANON_Y (f
, y
),
842 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
843 "Return current value of point in WINDOW.\n\
844 For a nonselected window, this is the value point would have\n\
845 if that window were selected.\n\
847 Note that, when WINDOW is the selected window and its buffer\n\
848 is also currently selected, the value returned is the same as (point).\n\
849 It would be more strictly correct to return the `top-level' value\n\
850 of point, outside of any save-excursion forms.\n\
851 But that is hard to define.")
855 register struct window
*w
= decode_window (window
);
857 if (w
== XWINDOW (selected_window
)
858 && current_buffer
== XBUFFER (w
->buffer
))
860 return Fmarker_position (w
->pointm
);
863 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
864 "Return position at which display currently starts in WINDOW.\n\
865 This is updated by redisplay or by calling `set-window-start'.")
869 return Fmarker_position (decode_window (window
)->start
);
872 /* This is text temporarily removed from the doc string below.
874 This function returns nil if the position is not currently known.\n\
875 That happens when redisplay is preempted and doesn't finish.\n\
876 If in that case you want to compute where the end of the window would\n\
877 have been if redisplay had finished, do this:\n\
879 (goto-char (window-start window))\n\
880 (vertical-motion (1- (window-height window)) window)\n\
883 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
884 "Return position at which display currently ends in WINDOW.\n\
885 This is updated by redisplay, when it runs to completion.\n\
886 Simply changing the buffer text or setting `window-start'\n\
887 does not update this value.\n\
888 If UPDATE is non-nil, compute the up-to-date position\n\
889 if it isn't already recorded.")
891 Lisp_Object window
, update
;
894 struct window
*w
= decode_window (window
);
898 CHECK_BUFFER (buf
, 0);
900 #if 0 /* This change broke some things. We should make it later. */
901 /* If we don't know the end position, return nil.
902 The user can compute it with vertical-motion if he wants to.
903 It would be nicer to do it automatically,
904 but that's so slow that it would probably bother people. */
905 if (NILP (w
->window_end_valid
))
910 && ! (! NILP (w
->window_end_valid
)
911 && XFASTINT (w
->last_modified
) >= MODIFF
))
913 struct text_pos startp
;
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 start_display (&it
, w
, startp
);
931 move_it_vertically (&it
, window_box_height (w
));
932 move_it_past_eol (&it
);
933 value
= make_number (IT_CHARPOS (it
));
936 XSETINT (value
, BUF_Z (XBUFFER (buf
)) - XFASTINT (w
->window_end_pos
));
941 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
942 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
944 Lisp_Object window
, pos
;
946 register struct window
*w
= decode_window (window
);
948 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
949 if (w
== XWINDOW (selected_window
)
950 && XBUFFER (w
->buffer
) == current_buffer
)
953 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
955 /* We have to make sure that redisplay updates the window to show
956 the new value of point. */
957 if (!EQ (window
, selected_window
))
958 ++windows_or_buffers_changed
;
963 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
964 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
965 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
966 from overriding motion of point in order to display at this exact start.")
967 (window
, pos
, noforce
)
968 Lisp_Object window
, pos
, noforce
;
970 register struct window
*w
= decode_window (window
);
972 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
973 set_marker_restricted (w
->start
, pos
, w
->buffer
);
974 /* this is not right, but much easier than doing what is right. */
975 w
->start_at_line_beg
= Qnil
;
978 w
->update_mode_line
= Qt
;
979 XSETFASTINT (w
->last_modified
, 0);
980 XSETFASTINT (w
->last_overlay_modified
, 0);
981 if (!EQ (window
, selected_window
))
982 windows_or_buffers_changed
++;
987 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
989 "Return WINDOW's dedicated object, usually t or nil.\n\
990 See also `set-window-dedicated-p'.")
994 return decode_window (window
)->dedicated
;
997 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
998 Sset_window_dedicated_p
, 2, 2, 0,
999 "Control whether WINDOW is dedicated to the buffer it displays.\n\
1000 If it is dedicated, Emacs will not automatically change\n\
1001 which buffer appears in it.\n\
1002 The second argument is the new value for the dedication flag;\n\
1003 non-nil means yes.")
1005 Lisp_Object window
, arg
;
1007 register struct window
*w
= decode_window (window
);
1010 w
->dedicated
= Qnil
;
1014 return w
->dedicated
;
1017 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1019 "Return the display-table that WINDOW is using.")
1023 return decode_window (window
)->display_table
;
1026 /* Get the display table for use on window W. This is either W's
1027 display table or W's buffer's display table. Ignore the specified
1028 tables if they are not valid; if no valid table is specified,
1031 struct Lisp_Char_Table
*
1032 window_display_table (w
)
1035 struct Lisp_Char_Table
*dp
= NULL
;
1037 if (DISP_TABLE_P (w
->display_table
))
1038 dp
= XCHAR_TABLE (w
->display_table
);
1039 else if (BUFFERP (w
->buffer
))
1041 struct buffer
*b
= XBUFFER (w
->buffer
);
1043 if (DISP_TABLE_P (b
->display_table
))
1044 dp
= XCHAR_TABLE (b
->display_table
);
1045 else if (DISP_TABLE_P (Vstandard_display_table
))
1046 dp
= XCHAR_TABLE (Vstandard_display_table
);
1052 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1053 "Set WINDOW's display-table to TABLE.")
1055 register Lisp_Object window
, table
;
1057 register struct window
*w
;
1059 w
= decode_window (window
);
1060 w
->display_table
= table
;
1064 /* Record info on buffer window w is displaying
1065 when it is about to cease to display that buffer. */
1068 register struct window
*w
;
1075 if (b
!= XMARKER (w
->pointm
)->buffer
)
1079 if (w
== XWINDOW (selected_window
)
1080 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1081 /* Do this except when the selected window's buffer
1082 is being removed from some other window. */
1084 /* last_window_start records the start position that this buffer
1085 had in the last window to be disconnected from it.
1086 Now that this statement is unconditional,
1087 it is possible for the buffer to be displayed in the
1088 selected window, while last_window_start reflects another
1089 window which was recently showing the same buffer.
1090 Some people might say that might be a good thing. Let's see. */
1091 b
->last_window_start
= marker_position (w
->start
);
1093 /* Point in the selected window's buffer
1094 is actually stored in that buffer, and the window's pointm isn't used.
1095 So don't clobber point in that buffer. */
1096 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1097 /* This line helps to fix Horsley's testbug.el bug. */
1098 && !(WINDOWP (b
->last_selected_window
)
1099 && w
!= XWINDOW (b
->last_selected_window
)
1100 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1101 temp_set_point_both (b
,
1102 clip_to_bounds (BUF_BEGV (b
),
1103 XMARKER (w
->pointm
)->charpos
,
1105 clip_to_bounds (BUF_BEGV_BYTE (b
),
1106 marker_byte_position (w
->pointm
),
1109 if (WINDOWP (b
->last_selected_window
)
1110 && w
== XWINDOW (b
->last_selected_window
))
1111 b
->last_selected_window
= Qnil
;
1114 /* Put replacement into the window structure in place of old. */
1116 replace_window (old
, replacement
)
1117 Lisp_Object old
, replacement
;
1119 register Lisp_Object tem
;
1120 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1122 /* If OLD is its frame's root_window, then replacement is the new
1123 root_window for that frame. */
1125 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1126 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1130 p
->width
= o
->width
;
1131 p
->height
= o
->height
;
1132 p
->desired_matrix
= p
->current_matrix
= 0;
1134 bzero (&p
->cursor
, sizeof (p
->cursor
));
1135 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
1136 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
1137 p
->phys_cursor_type
= -1;
1138 p
->must_be_updated_p
= 0;
1139 p
->pseudo_window_p
= 0;
1140 XSETFASTINT (p
->window_end_vpos
, 0);
1141 XSETFASTINT (p
->window_end_pos
, 0);
1142 p
->window_end_valid
= Qnil
;
1143 p
->frozen_window_start_p
= 0;
1144 p
->orig_top
= p
->orig_height
= Qnil
;
1146 p
->next
= tem
= o
->next
;
1148 XWINDOW (tem
)->prev
= replacement
;
1150 p
->prev
= tem
= o
->prev
;
1152 XWINDOW (tem
)->next
= replacement
;
1154 p
->parent
= tem
= o
->parent
;
1157 if (EQ (XWINDOW (tem
)->vchild
, old
))
1158 XWINDOW (tem
)->vchild
= replacement
;
1159 if (EQ (XWINDOW (tem
)->hchild
, old
))
1160 XWINDOW (tem
)->hchild
= replacement
;
1163 /*** Here, if replacement is a vertical combination
1164 and so is its new parent, we should make replacement's
1165 children be children of that parent instead. ***/
1168 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1169 "Remove WINDOW from the display. Default is selected window.")
1171 register Lisp_Object window
;
1173 delete_window (window
);
1175 if (! NILP (Vwindow_configuration_change_hook
)
1176 && ! NILP (Vrun_hooks
))
1177 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
1183 delete_window (window
)
1184 register Lisp_Object window
;
1186 register Lisp_Object tem
, parent
, sib
;
1187 register struct window
*p
;
1188 register struct window
*par
;
1191 /* Because this function is called by other C code on non-leaf
1192 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1193 so we can't decode_window here. */
1195 window
= selected_window
;
1197 CHECK_WINDOW (window
, 0);
1198 p
= XWINDOW (window
);
1200 /* It's okay to delete an already-deleted window. */
1201 if (NILP (p
->buffer
)
1203 && NILP (p
->vchild
))
1208 error ("Attempt to delete minibuffer or sole ordinary window");
1209 par
= XWINDOW (parent
);
1211 windows_or_buffers_changed
++;
1212 Vwindow_list
= Qnil
;
1213 f
= XFRAME (WINDOW_FRAME (p
));
1214 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1216 /* Are we trying to delete any frame's selected window? */
1218 Lisp_Object pwindow
;
1220 /* See if the frame's selected window is either WINDOW
1221 or any subwindow of it, by finding all that window's parents
1222 and comparing each one with WINDOW. */
1223 pwindow
= FRAME_SELECTED_WINDOW (f
);
1225 while (!NILP (pwindow
))
1227 if (EQ (window
, pwindow
))
1229 pwindow
= XWINDOW (pwindow
)->parent
;
1232 if (EQ (window
, pwindow
))
1234 Lisp_Object alternative
;
1235 alternative
= Fnext_window (window
, Qlambda
, Qnil
);
1237 /* If we're about to delete the selected window on the
1238 selected frame, then we should use Fselect_window to select
1239 the new window. On the other hand, if we're about to
1240 delete the selected window on any other frame, we shouldn't do
1241 anything but set the frame's selected_window slot. */
1242 if (EQ (window
, selected_window
))
1243 Fselect_window (alternative
);
1245 FRAME_SELECTED_WINDOW (f
) = alternative
;
1250 /* tem is null for dummy parent windows
1251 (which have inferiors but not any contents themselves) */
1255 unchain_marker (p
->pointm
);
1256 unchain_marker (p
->start
);
1259 /* Free window glyph matrices. It is sure that they are allocated
1260 again when ADJUST_GLYPHS is called. Block input so that expose
1261 events and other events that access glyph matrices are not
1262 processed while we are changing them. */
1264 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1268 XWINDOW (tem
)->prev
= p
->prev
;
1272 XWINDOW (tem
)->next
= p
->next
;
1274 if (EQ (window
, par
->hchild
))
1275 par
->hchild
= p
->next
;
1276 if (EQ (window
, par
->vchild
))
1277 par
->vchild
= p
->next
;
1279 /* Find one of our siblings to give our space to. */
1283 /* If p gives its space to its next sibling, that sibling needs
1284 to have its top/left side pulled back to where p's is.
1285 set_window_{height,width} will re-position the sibling's
1288 XWINDOW (sib
)->top
= p
->top
;
1289 XWINDOW (sib
)->left
= p
->left
;
1292 /* Stretch that sibling. */
1293 if (!NILP (par
->vchild
))
1294 set_window_height (sib
,
1295 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
1297 if (!NILP (par
->hchild
))
1298 set_window_width (sib
,
1299 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
1302 /* If parent now has only one child,
1303 put the child into the parent's place. */
1307 if (NILP (XWINDOW (tem
)->next
))
1308 replace_window (parent
, tem
);
1310 /* Since we may be deleting combination windows, we must make sure that
1311 not only p but all its children have been marked as deleted. */
1312 if (! NILP (p
->hchild
))
1313 delete_all_subwindows (XWINDOW (p
->hchild
));
1314 else if (! NILP (p
->vchild
))
1315 delete_all_subwindows (XWINDOW (p
->vchild
));
1317 /* Mark this window as deleted. */
1318 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1320 /* Adjust glyph matrices. */
1327 /***********************************************************************
1329 ***********************************************************************/
1331 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1332 pointer. This is a callback function for foreach_window, used in
1333 function window_list. */
1336 add_window_to_list (w
, user_data
)
1340 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1342 XSETWINDOW (window
, w
);
1343 *list
= Fcons (window
, *list
);
1348 /* Return a list of all windows, for use by next_window. If
1349 Vwindow_list is a list, return that list. Otherwise, build a new
1350 list, cache it in Vwindow_list, and return that. */
1355 if (!CONSP (Vwindow_list
))
1359 Vwindow_list
= Qnil
;
1360 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1362 Lisp_Object args
[2];
1364 /* We are visiting windows in canonical order, and add
1365 new windows at the front of args[1], which means we
1366 have to reverse this list at the end. */
1368 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1369 args
[0] = Vwindow_list
;
1370 args
[1] = Fnreverse (args
[1]);
1371 Vwindow_list
= Fnconc (2, args
);
1375 return Vwindow_list
;
1379 /* Value is non-zero if WINDOW satisfies the constraints given by
1380 OWINDOW, MINIBUF and ALL_FRAMES.
1382 MINIBUF t means WINDOW may be minibuffer windows.
1383 `lambda' means WINDOW may not be a minibuffer window.
1384 a window means a specific minibuffer window
1386 ALL_FRAMES t means search all frames,
1387 nil means search just current frame,
1388 `visible' means search just visible frames,
1389 0 means search visible and iconified frames,
1390 a window means search the frame that window belongs to,
1391 a frame means consider windows on that frame, only. */
1394 candidate_window_p (window
, owindow
, minibuf
, all_frames
)
1395 Lisp_Object window
, owindow
, minibuf
, all_frames
;
1397 struct window
*w
= XWINDOW (window
);
1398 struct frame
*f
= XFRAME (w
->frame
);
1399 int candidate_p
= 1;
1401 if (!BUFFERP (w
->buffer
))
1403 else if (MINI_WINDOW_P (w
)
1404 && (EQ (minibuf
, Qlambda
)
1405 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1407 /* If MINIBUF is `lambda' don't consider any mini-windows.
1408 If it is a window, consider only that one. */
1411 else if (EQ (all_frames
, Qt
))
1413 else if (NILP (all_frames
))
1415 xassert (WINDOWP (owindow
));
1416 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1418 else if (EQ (all_frames
, Qvisible
))
1420 FRAME_SAMPLE_VISIBILITY (f
);
1421 candidate_p
= FRAME_VISIBLE_P (f
);
1423 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1425 FRAME_SAMPLE_VISIBILITY (f
);
1426 candidate_p
= FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
);
1428 else if (WINDOWP (all_frames
))
1429 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1430 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1431 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1432 else if (FRAMEP (all_frames
))
1433 candidate_p
= EQ (all_frames
, w
->frame
);
1439 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1440 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1444 decode_next_window_args (window
, minibuf
, all_frames
)
1445 Lisp_Object
*window
, *minibuf
, *all_frames
;
1448 *window
= selected_window
;
1450 CHECK_LIVE_WINDOW (*window
, 0);
1452 /* MINIBUF nil may or may not include minibuffers. Decide if it
1454 if (NILP (*minibuf
))
1455 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1456 else if (!EQ (*minibuf
, Qt
))
1459 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1460 => count none of them, or a specific minibuffer window (the
1461 active one) to count. */
1463 /* ALL_FRAMES nil doesn't specify which frames to include. */
1464 if (NILP (*all_frames
))
1465 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1466 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1468 else if (EQ (*all_frames
, Qvisible
))
1470 else if (XFASTINT (*all_frames
) == 0)
1472 else if (FRAMEP (*all_frames
))
1474 else if (!EQ (*all_frames
, Qt
))
1477 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1478 search just current frame, `visible' meaning search just visible
1479 frames, 0 meaning search visible and iconified frames, or a
1480 window, meaning search the frame that window belongs to, or a
1481 frame, meaning consider windows on that frame, only. */
1485 /* Return the next or previous window of WINDOW in canonical ordering
1486 of windows. NEXT_P non-zero means return the next window. See the
1487 documentation string of next-window for the meaning of MINIBUF and
1491 next_window (window
, minibuf
, all_frames
, next_p
)
1492 Lisp_Object window
, minibuf
, all_frames
;
1495 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1497 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1498 return the first window on the frame. */
1499 if (FRAMEP (all_frames
)
1500 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1501 return Fframe_first_window (all_frames
);
1507 /* Find WINDOW in the list of all windows. */
1508 list
= Fmemq (window
, window_list ());
1510 /* Scan forward from WINDOW to the end of the window list. */
1512 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1513 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1516 /* Scan from the start of the window list up to WINDOW. */
1518 for (list
= Vwindow_list
;
1519 CONSP (list
) && !EQ (XCAR (list
), window
);
1521 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1525 window
= XCAR (list
);
1529 Lisp_Object candidate
, list
;
1531 /* Scan through the list of windows for candidates. If there are
1532 candidate windows in front of WINDOW, the last one of these
1533 is the one we want. If there are candidates following WINDOW
1534 in the list, again the last one of these is the one we want. */
1536 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
1538 if (EQ (XCAR (list
), window
))
1540 if (WINDOWP (candidate
))
1543 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
1545 candidate
= XCAR (list
);
1548 if (WINDOWP (candidate
))
1556 /* This comment supplies the doc string for `next-window',
1557 for make-docfile to see. We cannot put this in the real DEFUN
1558 due to limits in the Unix cpp.
1560 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
1561 "Return next window after WINDOW in canonical ordering of windows.\n\
1562 If omitted, WINDOW defaults to the selected window.\n\
1564 Optional second arg MINIBUF t means count the minibuffer window even\n\
1565 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1566 it is active. MINIBUF neither t nor nil means not to count the\n\
1567 minibuffer even if it is active.\n\
1569 Several frames may share a single minibuffer; if the minibuffer\n\
1570 counts, all windows on all frames that share that minibuffer count\n\
1571 too. Therefore, `next-window' can be used to iterate through the\n\
1572 set of windows even when the minibuffer is on another frame. If the\n\
1573 minibuffer does not count, only windows from WINDOW's frame count.\n\
1575 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1576 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1577 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1578 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1579 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1580 Anything else means restrict to WINDOW's frame.\n\
1582 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1583 `next-window' to iterate through the entire cycle of acceptable\n\
1584 windows, eventually ending up back at the window you started with.\n\
1585 `previous-window' traverses the same cycle, in the reverse order.")
1586 (window, minibuf, all_frames) */
1588 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
1590 (window
, minibuf
, all_frames
)
1591 Lisp_Object window
, minibuf
, all_frames
;
1593 return next_window (window
, minibuf
, all_frames
, 1);
1597 /* This comment supplies the doc string for `previous-window',
1598 for make-docfile to see. We cannot put this in the real DEFUN
1599 due to limits in the Unix cpp.
1601 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1602 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1603 If omitted, WINDOW defaults to the selected window.\n\
1605 Optional second arg MINIBUF t means count the minibuffer window even\n\
1606 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1607 it is active. MINIBUF neither t nor nil means not to count the\n\
1608 minibuffer even if it is active.\n\
1610 Several frames may share a single minibuffer; if the minibuffer\n\
1611 counts, all windows on all frames that share that minibuffer count\n\
1612 too. Therefore, `previous-window' can be used to iterate through\n\
1613 the set of windows even when the minibuffer is on another frame. If\n\
1614 the minibuffer does not count, only windows from WINDOW's frame count\n\
1616 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1617 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1618 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1619 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1620 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1621 Anything else means restrict to WINDOW's frame.\n\
1623 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1624 `previous-window' to iterate through the entire cycle of acceptable\n\
1625 windows, eventually ending up back at the window you started with.\n\
1626 `next-window' traverses the same cycle, in the reverse order.")
1627 (window, minibuf, all_frames) */
1630 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
1632 (window
, minibuf
, all_frames
)
1633 Lisp_Object window
, minibuf
, all_frames
;
1635 return next_window (window
, minibuf
, all_frames
, 0);
1639 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
1640 "Select the ARG'th different window on this frame.\n\
1641 All windows on current frame are arranged in a cyclic order.\n\
1642 This command selects the window ARG steps away in that order.\n\
1643 A negative ARG moves in the opposite order. If the optional second\n\
1644 argument ALL_FRAMES is non-nil, cycle through all frames.")
1646 Lisp_Object arg
, all_frames
;
1651 CHECK_NUMBER (arg
, 0);
1652 window
= selected_window
;
1654 for (i
= XINT (arg
); i
> 0; --i
)
1655 window
= Fnext_window (window
, Qnil
, all_frames
);
1657 window
= Fprevious_window (window
, Qnil
, all_frames
);
1659 Fselect_window (window
);
1664 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
1665 "Return a list of windows on FRAME, starting with WINDOW.\n\
1666 FRAME nil or omitted means use the selected frame.\n\
1667 WINDOW nil or omitted means use the selected window.\n\
1668 MINIBUF t means include the minibuffer window, even if it isn't active.\n\
1669 MINIBUF nil or omitted means include the minibuffer window only\n\
1671 MINIBUF neither nil nor t means never include the minibuffer window.")
1672 (frame
, minibuf
, window
)
1673 Lisp_Object frame
, minibuf
, window
;
1676 window
= selected_window
;
1678 frame
= selected_frame
;
1680 if (!EQ (frame
, XWINDOW (window
)->frame
))
1681 error ("Window is on a different frame");
1683 return window_list_1 (window
, minibuf
, frame
);
1687 /* Return a list of windows in canonical ordering. Arguments are like
1688 for `next-window'. */
1691 window_list_1 (window
, minibuf
, all_frames
)
1692 Lisp_Object window
, minibuf
, all_frames
;
1694 Lisp_Object tail
, list
;
1696 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1699 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
1700 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
1701 list
= Fcons (XCAR (tail
), list
);
1703 return Fnreverse (list
);
1708 /* Look at all windows, performing an operation specified by TYPE
1710 If FRAMES is Qt, look at all frames;
1711 Qnil, look at just the selected frame;
1712 Qvisible, look at visible frames;
1713 a frame, just look at windows on that frame.
1714 If MINI is non-zero, perform the operation on minibuffer windows too. */
1719 GET_BUFFER_WINDOW
, /* Arg is buffer */
1720 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
1721 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
1722 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
1724 UNSHOW_BUFFER
, /* Arg is buffer */
1729 window_loop (type
, obj
, mini
, frames
)
1730 enum window_loop type
;
1731 Lisp_Object obj
, frames
;
1734 Lisp_Object window
, windows
, best_window
, frame_arg
;
1736 struct gcpro gcpro1
;
1738 /* If we're only looping through windows on a particular frame,
1739 frame points to that frame. If we're looping through windows
1740 on all frames, frame is 0. */
1741 if (FRAMEP (frames
))
1742 f
= XFRAME (frames
);
1743 else if (NILP (frames
))
1744 f
= SELECTED_FRAME ();
1749 frame_arg
= Qlambda
;
1750 else if (XFASTINT (frames
) == 0)
1752 else if (EQ (frames
, Qvisible
))
1757 /* frame_arg is Qlambda to stick to one frame,
1758 Qvisible to consider all visible frames,
1761 /* Pick a window to start with. */
1765 window
= FRAME_SELECTED_WINDOW (f
);
1767 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1769 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
1773 for (; CONSP (windows
); windows
= CDR (windows
))
1777 window
= XCAR (windows
);
1778 w
= XWINDOW (window
);
1780 /* Note that we do not pay attention here to whether the frame
1781 is visible, since Fwindow_list skips non-visible frames if
1782 that is desired, under the control of frame_arg. */
1783 if (!MINI_WINDOW_P (w
)
1784 /* For UNSHOW_BUFFER, we must always consider all windows. */
1785 || type
== UNSHOW_BUFFER
1786 || (mini
&& minibuf_level
> 0))
1789 case GET_BUFFER_WINDOW
:
1790 if (EQ (w
->buffer
, obj
)
1791 /* Don't find any minibuffer window
1792 except the one that is currently in use. */
1793 && (MINI_WINDOW_P (w
)
1794 ? EQ (window
, minibuf_window
)
1797 if (NILP (best_window
))
1798 best_window
= window
;
1799 else if (EQ (window
, selected_window
))
1800 /* For compatibility with 20.x, prefer to return
1802 best_window
= window
;
1806 case GET_LRU_WINDOW
:
1807 /* t as arg means consider only full-width windows */
1808 if (!NILP (obj
) && !WINDOW_FULL_WIDTH_P (w
))
1810 /* Ignore dedicated windows and minibuffers. */
1811 if (MINI_WINDOW_P (w
) || !NILP (w
->dedicated
))
1813 if (NILP (best_window
)
1814 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1815 > XFASTINT (w
->use_time
)))
1816 best_window
= window
;
1819 case DELETE_OTHER_WINDOWS
:
1820 if (!EQ (window
, obj
))
1821 Fdelete_window (window
);
1824 case DELETE_BUFFER_WINDOWS
:
1825 if (EQ (w
->buffer
, obj
))
1827 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1829 /* If this window is dedicated, and in a frame of its own,
1831 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
1832 && !NILP (w
->dedicated
)
1833 && other_visible_frames (f
))
1835 /* Skip the other windows on this frame.
1836 There might be one, the minibuffer! */
1837 while (CONSP (XCDR (windows
))
1838 && EQ (XWINDOW (XCAR (windows
))->frame
,
1839 XWINDOW (XCAR (XCDR (windows
)))->frame
))
1840 windows
= XCDR (windows
);
1842 /* Now we can safely delete the frame. */
1843 Fdelete_frame (w
->frame
, Qnil
);
1845 else if (NILP (w
->parent
))
1847 /* If we're deleting the buffer displayed in the
1848 only window on the frame, find a new buffer to
1851 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
1853 buffer
= Fget_buffer_create (build_string ("*scratch*"));
1854 Fset_window_buffer (window
, buffer
);
1855 if (EQ (window
, selected_window
))
1856 Fset_buffer (w
->buffer
);
1859 Fdelete_window (window
);
1863 case GET_LARGEST_WINDOW
:
1865 /* Ignore dedicated windows and minibuffers. */
1866 if (MINI_WINDOW_P (w
) || !NILP (w
->dedicated
))
1869 if (NILP (best_window
))
1870 best_window
= window
;
1873 struct window
*b
= XWINDOW (best_window
);
1874 if (XFASTINT (w
->height
) * XFASTINT (w
->width
)
1875 > XFASTINT (b
->height
) * XFASTINT (b
->width
))
1876 best_window
= window
;
1882 if (EQ (w
->buffer
, obj
))
1885 struct frame
*f
= XFRAME (w
->frame
);
1887 /* Find another buffer to show in this window. */
1888 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
1890 buffer
= Fget_buffer_create (build_string ("*scratch*"));
1892 /* If this window is dedicated, and in a frame of its own,
1894 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
1895 && !NILP (w
->dedicated
)
1896 && other_visible_frames (f
))
1898 /* Skip the other windows on this frame.
1899 There might be one, the minibuffer! */
1900 while (CONSP (XCDR (windows
))
1901 && EQ (XWINDOW (XCAR (windows
))->frame
,
1902 XWINDOW (XCAR (XCDR (windows
)))->frame
))
1903 windows
= XCDR (windows
);
1905 /* Now we can safely delete the frame. */
1906 Fdelete_frame (w
->frame
, Qnil
);
1910 /* Otherwise show a different buffer in the window. */
1911 w
->dedicated
= Qnil
;
1912 Fset_window_buffer (window
, buffer
);
1913 if (EQ (window
, selected_window
))
1914 Fset_buffer (w
->buffer
);
1919 /* Check for a window that has a killed buffer. */
1920 case CHECK_ALL_WINDOWS
:
1921 if (! NILP (w
->buffer
)
1922 && NILP (XBUFFER (w
->buffer
)->name
))
1926 case WINDOW_LOOP_UNUSED
:
1935 /* Used for debugging. Abort if any window has a dead buffer. */
1938 check_all_windows ()
1940 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
1943 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1944 "Return the window least recently selected or used for display.\n\
1945 If optional argument FRAME is `visible', search all visible frames.\n\
1946 If FRAME is 0, search all visible and iconified frames.\n\
1947 If FRAME is t, search all frames.\n\
1948 If FRAME is nil, search only the selected frame.\n\
1949 If FRAME is a frame, search only that frame.")
1953 register Lisp_Object w
;
1954 /* First try for a window that is full-width */
1955 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, frame
);
1956 if (!NILP (w
) && !EQ (w
, selected_window
))
1958 /* If none of them, try the rest */
1959 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, frame
);
1962 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1963 "Return the largest window in area.\n\
1964 If optional argument FRAME is `visible', search all visible frames.\n\
1965 If FRAME is 0, search all visible and iconified frames.\n\
1966 If FRAME is t, search all frames.\n\
1967 If FRAME is nil, search only the selected frame.\n\
1968 If FRAME is a frame, search only that frame.")
1972 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1976 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1977 "Return a window currently displaying BUFFER, or nil if none.\n\
1978 If optional argument FRAME is `visible', search all visible frames.\n\
1979 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1980 If FRAME is t, search all frames.\n\
1981 If FRAME is nil, search only the selected frame.\n\
1982 If FRAME is a frame, search only that frame.")
1984 Lisp_Object buffer
, frame
;
1986 buffer
= Fget_buffer (buffer
);
1987 if (BUFFERP (buffer
))
1988 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
1993 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
1995 "Make WINDOW (or the selected window) fill its frame.\n\
1996 Only the frame WINDOW is on is affected.\n\
1997 This function tries to reduce display jumps\n\
1998 by keeping the text previously visible in WINDOW\n\
1999 in the same place on the frame. Doing this depends on\n\
2000 the value of (window-start WINDOW), so if calling this function\n\
2001 in a program gives strange scrolling, make sure the window-start\n\
2002 value is reasonable when this function is called.")
2011 window
= selected_window
;
2013 CHECK_LIVE_WINDOW (window
, 0);
2014 w
= XWINDOW (window
);
2016 startpos
= marker_position (w
->start
);
2017 top
= XFASTINT (w
->top
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2019 if (MINI_WINDOW_P (w
) && top
> 0)
2020 error ("Can't expand minibuffer to full frame");
2022 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2024 /* Try to minimize scrolling, by setting the window start to the point
2025 will cause the text at the old window start to be at the same place
2026 on the frame. But don't try to do this if the window start is
2027 outside the visible portion (as might happen when the display is
2028 not current, due to typeahead). */
2029 new_top
= XFASTINT (w
->top
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2031 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2032 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2034 struct position pos
;
2035 struct buffer
*obuf
= current_buffer
;
2037 Fset_buffer (w
->buffer
);
2038 /* This computation used to temporarily move point, but that can
2039 have unwanted side effects due to text properties. */
2040 pos
= *vmotion (startpos
, -top
, w
);
2042 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2043 w
->window_end_valid
= Qnil
;
2044 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2045 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2047 /* We need to do this, so that the window-scroll-functions
2049 w
->optional_new_start
= Qt
;
2051 set_buffer_internal (obuf
);
2057 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2058 1, 2, "bDelete windows on (buffer): ",
2059 "Delete all windows showing BUFFER.\n\
2060 Optional second argument FRAME controls which frames are affected.\n\
2061 If optional argument FRAME is `visible', search all visible frames.\n\
2062 If FRAME is 0, search all visible and iconified frames.\n\
2063 If FRAME is nil, search all frames.\n\
2064 If FRAME is t, search only the selected frame.\n\
2065 If FRAME is a frame, search only that frame.")
2067 Lisp_Object buffer
, frame
;
2069 /* FRAME uses t and nil to mean the opposite of what window_loop
2073 else if (EQ (frame
, Qt
))
2078 buffer
= Fget_buffer (buffer
);
2079 CHECK_BUFFER (buffer
, 0);
2080 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2086 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2087 Sreplace_buffer_in_windows
,
2088 1, 1, "bReplace buffer in windows: ",
2089 "Replace BUFFER with some other buffer in all windows showing it.")
2095 buffer
= Fget_buffer (buffer
);
2096 CHECK_BUFFER (buffer
, 0);
2097 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2102 /* Replace BUFFER with some other buffer in all windows
2103 of all frames, even those on other keyboards. */
2106 replace_buffer_in_all_windows (buffer
)
2110 Lisp_Object tail
, frame
;
2112 /* A single call to window_loop won't do the job
2113 because it only considers frames on the current keyboard.
2114 So loop manually over frames, and handle each one. */
2115 FOR_EACH_FRAME (tail
, frame
)
2116 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2118 window_loop (UNSHOW_BUFFER
, buffer
, 1, Qt
);
2122 /* Set the height of WINDOW and all its inferiors. */
2124 /* The smallest acceptable dimensions for a window. Anything smaller
2125 might crash Emacs. */
2127 #define MIN_SAFE_WINDOW_WIDTH (2)
2128 #define MIN_SAFE_WINDOW_HEIGHT (2)
2130 /* Make sure that window_min_height and window_min_width are
2131 not too small; if they are, set them to safe minima. */
2134 check_min_window_sizes ()
2136 /* Smaller values might permit a crash. */
2137 if (window_min_width
< MIN_SAFE_WINDOW_WIDTH
)
2138 window_min_width
= MIN_SAFE_WINDOW_WIDTH
;
2139 if (window_min_height
< MIN_SAFE_WINDOW_HEIGHT
)
2140 window_min_height
= MIN_SAFE_WINDOW_HEIGHT
;
2143 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2144 minimum allowable size. */
2147 check_frame_size (frame
, rows
, cols
)
2151 /* For height, we have to see:
2152 whether the frame has a minibuffer,
2153 whether it wants a mode line, and
2154 whether it has a menu bar. */
2156 (FRAME_MINIBUF_ONLY_P (frame
) ? MIN_SAFE_WINDOW_HEIGHT
- 1
2157 : (! FRAME_HAS_MINIBUF_P (frame
)) ? MIN_SAFE_WINDOW_HEIGHT
2158 : 2 * MIN_SAFE_WINDOW_HEIGHT
- 1);
2160 if (FRAME_TOP_MARGIN (frame
) > 0)
2161 min_height
+= FRAME_TOP_MARGIN (frame
);
2163 if (*rows
< min_height
)
2165 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2166 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2170 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2171 check if W's width can be changed, otherwise check W's height.
2172 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2173 siblings, too. If none of the siblings is resizable, WINDOW isn't
2177 window_fixed_size_p (w
, width_p
, check_siblings_p
)
2179 int width_p
, check_siblings_p
;
2184 if (!NILP (w
->hchild
))
2186 c
= XWINDOW (w
->hchild
);
2190 /* A horiz. combination is fixed-width if all of if its
2192 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2193 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2194 fixed_p
= c
== NULL
;
2198 /* A horiz. combination is fixed-height if one of if its
2200 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2201 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2202 fixed_p
= c
!= NULL
;
2205 else if (!NILP (w
->vchild
))
2207 c
= XWINDOW (w
->vchild
);
2211 /* A vert. combination is fixed-width if one of if its
2213 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2214 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2215 fixed_p
= c
!= NULL
;
2219 /* A vert. combination is fixed-height if all of if its
2221 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2222 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2223 fixed_p
= c
== NULL
;
2226 else if (BUFFERP (w
->buffer
))
2228 if (w
->height_fixed_p
&& !width_p
)
2232 struct buffer
*old
= current_buffer
;
2235 current_buffer
= XBUFFER (w
->buffer
);
2236 val
= find_symbol_value (Qwindow_size_fixed
);
2237 current_buffer
= old
;
2240 if (!EQ (val
, Qunbound
))
2242 fixed_p
= !NILP (val
);
2245 && ((EQ (val
, Qheight
) && width_p
)
2246 || (EQ (val
, Qwidth
) && !width_p
)))
2251 /* Can't tell if this one is resizable without looking at
2252 siblings. If all siblings are fixed-size this one is too. */
2253 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2257 for (child
= w
->prev
; !NILP (child
); child
= XWINDOW (child
)->prev
)
2258 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2262 for (child
= w
->next
; !NILP (child
); child
= XWINDOW (child
)->next
)
2263 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2277 /* Return the minimum size of window W, not taking fixed-width windows
2278 into account. WIDTH_P non-zero means return the minimum width,
2279 otherwise return the minimum height. If W is a combination window,
2280 compute the minimum size from the minimum sizes of W's children. */
2283 window_min_size_1 (w
, width_p
)
2290 if (!NILP (w
->hchild
))
2292 c
= XWINDOW (w
->hchild
);
2297 /* The min width of a horizontal combination is
2298 the sum of the min widths of its children. */
2301 size
+= window_min_size_1 (c
, width_p
);
2302 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2307 /* The min height a horizontal combination equals
2308 the maximum of all min height of its children. */
2311 int min_size
= window_min_size_1 (c
, width_p
);
2312 size
= max (min_size
, size
);
2313 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2317 else if (!NILP (w
->vchild
))
2319 c
= XWINDOW (w
->vchild
);
2324 /* The min width of a vertical combination is
2325 the maximum of the min widths of its children. */
2328 int min_size
= window_min_size_1 (c
, width_p
);
2329 size
= max (min_size
, size
);
2330 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2335 /* The min height of a vertical combination equals
2336 the sum of the min height of its children. */
2339 size
+= window_min_size_1 (c
, width_p
);
2340 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2347 size
= window_min_width
;
2350 if (MINI_WINDOW_P (w
)
2351 || (!WINDOW_WANTS_MODELINE_P (w
)
2352 && !WINDOW_WANTS_HEADER_LINE_P (w
)))
2355 size
= window_min_height
;
2363 /* Return the minimum size of window W, taking fixed-size windows into
2364 account. WIDTH_P non-zero means return the minimum width,
2365 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2366 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2367 unless FIXED is null. */
2370 window_min_size (w
, width_p
, ignore_fixed_p
, fixed
)
2372 int width_p
, ignore_fixed_p
, *fixed
;
2379 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2385 size
= width_p
? XFASTINT (w
->width
) : XFASTINT (w
->height
);
2387 size
= window_min_size_1 (w
, width_p
);
2393 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2394 WINDOW's width. Resize WINDOW's children, if any, so that they
2395 keep their proportionate size relative to WINDOW. Propagate
2396 WINDOW's top or left edge position to children. Delete windows
2397 that become too small unless NODELETE_P is non-zero. */
2400 size_window (window
, size
, width_p
, nodelete_p
)
2402 int size
, width_p
, nodelete_p
;
2404 struct window
*w
= XWINDOW (window
);
2406 Lisp_Object child
, *forward
, *sideward
;
2407 int old_size
, min_size
;
2409 check_min_window_sizes ();
2410 size
= max (0, size
);
2412 /* If the window has been "too small" at one point,
2413 don't delete it for being "too small" in the future.
2414 Preserve it as long as that is at all possible. */
2417 old_size
= XINT (w
->width
);
2418 min_size
= window_min_width
;
2422 old_size
= XINT (w
->height
);
2423 min_size
= window_min_height
;
2426 if (old_size
< min_size
)
2427 w
->too_small_ok
= Qt
;
2429 /* Maybe delete WINDOW if it's too small. */
2430 if (!nodelete_p
&& !NILP (w
->parent
))
2432 if (!MINI_WINDOW_P (w
) && !NILP (w
->too_small_ok
))
2433 min_size
= width_p
? MIN_SAFE_WINDOW_WIDTH
: MIN_SAFE_WINDOW_HEIGHT
;
2435 min_size
= width_p
? window_min_width
: window_min_height
;
2437 if (size
< min_size
)
2439 delete_window (window
);
2444 /* Set redisplay hints. */
2445 w
->last_modified
= make_number (0);
2446 w
->last_overlay_modified
= make_number (0);
2447 windows_or_buffers_changed
++;
2448 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
2452 sideward
= &w
->vchild
;
2453 forward
= &w
->hchild
;
2454 w
->width
= make_number (size
);
2458 sideward
= &w
->hchild
;
2459 forward
= &w
->vchild
;
2460 w
->height
= make_number (size
);
2461 w
->orig_height
= Qnil
;
2464 if (!NILP (*sideward
))
2466 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
2468 c
= XWINDOW (child
);
2473 size_window (child
, size
, width_p
, nodelete_p
);
2476 else if (!NILP (*forward
))
2478 int fixed_size
, each
, extra
, n
;
2479 int resize_fixed_p
, nfixed
;
2480 int last_pos
, first_pos
, nchildren
, total
;
2482 /* Determine the fixed-size portion of the this window, and the
2483 number of child windows. */
2484 fixed_size
= nchildren
= nfixed
= total
= 0;
2485 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
2489 c
= XWINDOW (child
);
2490 child_size
= width_p
? XINT (c
->width
) : XINT (c
->height
);
2491 total
+= child_size
;
2493 if (window_fixed_size_p (c
, width_p
, 0))
2495 fixed_size
+= child_size
;
2500 /* If the new size is smaller than fixed_size, or if there
2501 aren't any resizable windows, allow resizing fixed-size
2503 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
2505 /* Compute how many lines/columns to add to each child. The
2506 value of extra takes care of rounding errors. */
2507 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
2508 each
= (size
- total
) / n
;
2509 extra
= (size
- total
) - n
* each
;
2511 /* Compute new children heights and edge positions. */
2512 first_pos
= width_p
? XINT (w
->left
) : XINT (w
->top
);
2513 last_pos
= first_pos
;
2514 for (child
= *forward
; !NILP (child
); child
= c
->next
)
2516 int new_size
, old_size
;
2518 c
= XWINDOW (child
);
2519 old_size
= width_p
? XFASTINT (c
->width
) : XFASTINT (c
->height
);
2520 new_size
= old_size
;
2522 /* The top or left edge position of this child equals the
2523 bottom or right edge of its predecessor. */
2525 c
->left
= make_number (last_pos
);
2527 c
->top
= make_number (last_pos
);
2529 /* If this child can be resized, do it. */
2530 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
2532 new_size
= old_size
+ each
+ extra
;
2536 /* Set new height. Note that size_window also propagates
2537 edge positions to children, so it's not a no-op if we
2538 didn't change the child's size. */
2539 size_window (child
, new_size
, width_p
, 1);
2541 /* Remember the bottom/right edge position of this child; it
2542 will be used to set the top/left edge of the next child. */
2543 last_pos
+= new_size
;
2546 /* We should have covered the parent exactly with child windows. */
2547 xassert (size
== last_pos
- first_pos
);
2549 /* Now delete any children that became too small. */
2551 for (child
= *forward
; !NILP (child
); child
= c
->next
)
2554 c
= XWINDOW (child
);
2555 child_size
= width_p
? XINT (c
->width
) : XINT (c
->height
);
2556 size_window (child
, child_size
, width_p
, 0);
2561 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2562 WINDOW's children. NODELETE non-zero means don't delete windows
2563 that become too small in the process. (The caller should check
2564 later and do so if appropriate.) */
2567 set_window_height (window
, height
, nodelete
)
2572 size_window (window
, height
, 0, nodelete
);
2576 /* Set WINDOW's width to WIDTH, and recursively change the width of
2577 WINDOW's children. NODELETE non-zero means don't delete windows
2578 that become too small in the process. (The caller should check
2579 later and do so if appropriate.) */
2582 set_window_width (window
, width
, nodelete
)
2587 size_window (window
, width
, 1, nodelete
);
2591 int window_select_count
;
2594 Fset_window_buffer_unwind (obuf
)
2602 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2603 means it's allowed to run hooks. See make_frame for a case where
2604 it's not allowed. */
2607 set_window_buffer (window
, buffer
, run_hooks_p
)
2608 Lisp_Object window
, buffer
;
2611 struct window
*w
= XWINDOW (window
);
2612 struct buffer
*b
= XBUFFER (buffer
);
2613 int count
= specpdl_ptr
- specpdl
;
2617 if (EQ (window
, selected_window
))
2618 b
->last_selected_window
= window
;
2620 /* Update time stamps of buffer display. */
2621 if (INTEGERP (b
->display_count
))
2622 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
2623 b
->display_time
= Fcurrent_time ();
2625 XSETFASTINT (w
->window_end_pos
, 0);
2626 XSETFASTINT (w
->window_end_vpos
, 0);
2627 bzero (&w
->last_cursor
, sizeof w
->last_cursor
);
2628 w
->window_end_valid
= Qnil
;
2629 w
->hscroll
= w
->min_hscroll
= make_number (0);
2630 w
->vscroll
= make_number (0);
2631 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
2632 set_marker_restricted (w
->start
,
2633 make_number (b
->last_window_start
),
2635 w
->start_at_line_beg
= Qnil
;
2636 w
->force_start
= Qnil
;
2637 XSETFASTINT (w
->last_modified
, 0);
2638 XSETFASTINT (w
->last_overlay_modified
, 0);
2639 windows_or_buffers_changed
++;
2641 /* We must select BUFFER for running the window-scroll-functions.
2642 If WINDOW is selected, switch permanently.
2643 Otherwise, switch but go back to the ambient buffer afterward. */
2644 if (EQ (window
, selected_window
))
2645 Fset_buffer (buffer
);
2646 /* We can't check ! NILP (Vwindow_scroll_functions) here
2647 because that might itself be a local variable. */
2648 else if (window_initialized
)
2650 record_unwind_protect (Fset_window_buffer_unwind
, Fcurrent_buffer ());
2651 Fset_buffer (buffer
);
2654 /* Set left and right marginal area width from buffer. */
2655 Fset_window_margins (window
, b
->left_margin_width
, b
->right_margin_width
);
2659 if (! NILP (Vwindow_scroll_functions
))
2660 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
2661 Fmarker_position (w
->start
));
2663 if (! NILP (Vwindow_configuration_change_hook
)
2664 && ! NILP (Vrun_hooks
))
2665 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
2668 unbind_to (count
, Qnil
);
2672 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
2673 "Make WINDOW display BUFFER as its contents.\n\
2674 BUFFER can be a buffer or buffer name.")
2676 register Lisp_Object window
, buffer
;
2678 register Lisp_Object tem
;
2679 register struct window
*w
= decode_window (window
);
2681 XSETWINDOW (window
, w
);
2682 buffer
= Fget_buffer (buffer
);
2683 CHECK_BUFFER (buffer
, 1);
2685 if (NILP (XBUFFER (buffer
)->name
))
2686 error ("Attempt to display deleted buffer");
2690 error ("Window is deleted");
2691 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
2692 is first being set up. */
2694 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
2695 error ("Window is dedicated to `%s'",
2696 XSTRING (XBUFFER (tem
)->name
)->data
);
2701 set_window_buffer (window
, buffer
, 1);
2705 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
2706 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
2707 If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2708 Note that the main editor command loop\n\
2709 selects the buffer of the selected window before each command.")
2711 register Lisp_Object window
;
2713 return select_window_1 (window
, 1);
2716 /* Note that selected_window can be nil
2717 when this is called from Fset_window_configuration. */
2720 select_window_1 (window
, recordflag
)
2721 register Lisp_Object window
;
2724 register struct window
*w
;
2725 register struct window
*ow
;
2728 CHECK_LIVE_WINDOW (window
, 0);
2730 w
= XWINDOW (window
);
2732 if (NILP (w
->buffer
))
2733 error ("Trying to select deleted window or non-leaf window");
2735 XSETFASTINT (w
->use_time
, ++window_select_count
);
2736 if (EQ (window
, selected_window
))
2739 if (!NILP (selected_window
))
2741 ow
= XWINDOW (selected_window
);
2742 if (! NILP (ow
->buffer
))
2743 set_marker_both (ow
->pointm
, ow
->buffer
,
2744 BUF_PT (XBUFFER (ow
->buffer
)),
2745 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
2748 selected_window
= window
;
2749 sf
= SELECTED_FRAME ();
2750 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
2752 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
2753 /* Use this rather than Fhandle_switch_frame
2754 so that FRAME_FOCUS_FRAME is moved appropriately as we
2755 move around in the state where a minibuffer in a separate
2757 Fselect_frame (WINDOW_FRAME (w
), Qnil
);
2760 sf
->selected_window
= window
;
2763 record_buffer (w
->buffer
);
2764 Fset_buffer (w
->buffer
);
2766 XBUFFER (w
->buffer
)->last_selected_window
= window
;
2768 /* Go to the point recorded in the window.
2769 This is important when the buffer is in more
2770 than one window. It also matters when
2771 redisplay_window has altered point after scrolling,
2772 because it makes the change only in the window. */
2774 register int new_point
= marker_position (w
->pointm
);
2775 if (new_point
< BEGV
)
2777 else if (new_point
> ZV
)
2783 windows_or_buffers_changed
++;
2787 /* Deiconify the frame containing the window WINDOW,
2788 unless it is the selected frame;
2791 The reason for the exception for the selected frame
2792 is that it seems better not to change the selected frames visibility
2793 merely because of displaying a different buffer in it.
2794 The deiconification is useful when a buffer gets shown in
2795 another frame that you were not using lately. */
2798 display_buffer_1 (window
)
2801 Lisp_Object frame
= XWINDOW (window
)->frame
;
2802 FRAME_PTR f
= XFRAME (frame
);
2804 FRAME_SAMPLE_VISIBILITY (f
);
2806 if (!EQ (frame
, selected_frame
))
2808 if (FRAME_ICONIFIED_P (f
))
2809 Fmake_frame_visible (frame
);
2810 else if (FRAME_VISIBLE_P (f
))
2811 Fraise_frame (frame
);
2817 DEFUN ("special-display-p", Fspecial_display_p
, Sspecial_display_p
, 1, 1, 0,
2818 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2819 The value is actually t if the frame should be called with default frame\n\
2820 parameters, and a list of frame parameters if they were specified.\n\
2821 See `special-display-buffer-names', and `special-display-regexps'.")
2823 Lisp_Object buffer_name
;
2827 CHECK_STRING (buffer_name
, 1);
2829 tem
= Fmember (buffer_name
, Vspecial_display_buffer_names
);
2833 tem
= Fassoc (buffer_name
, Vspecial_display_buffer_names
);
2837 for (tem
= Vspecial_display_regexps
; CONSP (tem
); tem
= XCDR (tem
))
2839 Lisp_Object car
= XCAR (tem
);
2841 && fast_string_match (car
, buffer_name
) >= 0)
2843 else if (CONSP (car
)
2844 && STRINGP (XCAR (car
))
2845 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
2851 DEFUN ("same-window-p", Fsame_window_p
, Ssame_window_p
, 1, 1, 0,
2852 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
2853 See `same-window-buffer-names' and `same-window-regexps'.")
2855 Lisp_Object buffer_name
;
2859 CHECK_STRING (buffer_name
, 1);
2861 tem
= Fmember (buffer_name
, Vsame_window_buffer_names
);
2865 tem
= Fassoc (buffer_name
, Vsame_window_buffer_names
);
2869 for (tem
= Vsame_window_regexps
; CONSP (tem
); tem
= XCDR (tem
))
2871 Lisp_Object car
= XCAR (tem
);
2873 && fast_string_match (car
, buffer_name
) >= 0)
2875 else if (CONSP (car
)
2876 && STRINGP (XCAR (car
))
2877 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
2883 /* Use B so the default is (other-buffer). */
2884 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 3,
2885 "BDisplay buffer: \nP",
2886 "Make BUFFER appear in some window but don't select it.\n\
2887 BUFFER can be a buffer or a buffer name.\n\
2888 If BUFFER is shown already in some window, just use that one,\n\
2889 unless the window is the selected window and the optional second\n\
2890 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
2891 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
2892 Returns the window displaying BUFFER.\n\
2893 If `display-reuse-frames' is non-nil, and another frame is currently\n\
2894 displaying BUFFER, then simply raise that frame.\n\
2896 The variables `special-display-buffer-names', `special-display-regexps',\n\
2897 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
2898 buffer names are handled.\n\
2900 If optional argument FRAME is `visible', search all visible frames.\n\
2901 If FRAME is 0, search all visible and iconified frames.\n\
2902 If FRAME is t, search all frames.\n\
2903 If FRAME is a frame, search only that frame.\n\
2904 If FRAME is nil, search only the selected frame\n\
2905 (actually the last nonminibuffer frame),\n\
2906 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,\n\
2907 which means search visible and iconified frames.\n\
2909 If `even-window-heights' is non-nil, window heights will be evened out\n\
2910 if displaying the buffer causes two vertically adjacent windows to be\n\
2912 (buffer
, not_this_window
, frame
)
2913 register Lisp_Object buffer
, not_this_window
, frame
;
2915 register Lisp_Object window
, tem
, swp
;
2919 buffer
= Fget_buffer (buffer
);
2920 CHECK_BUFFER (buffer
, 0);
2922 if (!NILP (Vdisplay_buffer_function
))
2923 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
2925 if (NILP (not_this_window
)
2926 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
2927 return display_buffer_1 (selected_window
);
2929 /* See if the user has specified this buffer should appear
2930 in the selected window. */
2931 if (NILP (not_this_window
))
2933 swp
= Fsame_window_p (XBUFFER (buffer
)->name
);
2934 if (!NILP (swp
) && !no_switch_window (selected_window
))
2936 Fswitch_to_buffer (buffer
, Qnil
);
2937 return display_buffer_1 (selected_window
);
2941 /* If the user wants pop-up-frames or display-reuse-frames, then
2942 look for a window showing BUFFER on any visible or iconified frame.
2943 Otherwise search only the current frame. */
2946 else if (pop_up_frames
2947 || display_buffer_reuse_frames
2948 || last_nonminibuf_frame
== 0)
2949 XSETFASTINT (tem
, 0);
2951 XSETFRAME (tem
, last_nonminibuf_frame
);
2953 window
= Fget_buffer_window (buffer
, tem
);
2955 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
2956 return display_buffer_1 (window
);
2958 /* Certain buffer names get special handling. */
2959 if (!NILP (Vspecial_display_function
) && NILP (swp
))
2961 tem
= Fspecial_display_p (XBUFFER (buffer
)->name
);
2963 return call1 (Vspecial_display_function
, buffer
);
2965 return call2 (Vspecial_display_function
, buffer
, tem
);
2968 /* If there are no frames open that have more than a minibuffer,
2969 we need to create a new frame. */
2970 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
2972 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
2973 Fset_window_buffer (window
, buffer
);
2974 return display_buffer_1 (window
);
2977 f
= SELECTED_FRAME ();
2979 || FRAME_MINIBUF_ONLY_P (f
)
2980 /* If the current frame is a special display frame,
2981 don't try to reuse its windows. */
2982 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f
))->dedicated
))
2987 if (FRAME_MINIBUF_ONLY_P (f
))
2988 XSETFRAME (frames
, last_nonminibuf_frame
);
2989 /* Don't try to create a window if would get an error */
2990 if (split_height_threshold
< window_min_height
<< 1)
2991 split_height_threshold
= window_min_height
<< 1;
2993 /* Note that both Fget_largest_window and Fget_lru_window
2994 ignore minibuffers and dedicated windows.
2995 This means they can return nil. */
2997 /* If the frame we would try to split cannot be split,
2998 try other frames. */
2999 if (FRAME_NO_SPLIT_P (NILP (frames
) ? f
: last_nonminibuf_frame
))
3001 /* Try visible frames first. */
3002 window
= Fget_largest_window (Qvisible
);
3003 /* If that didn't work, try iconified frames. */
3005 window
= Fget_largest_window (make_number (0));
3007 window
= Fget_largest_window (Qt
);
3010 window
= Fget_largest_window (frames
);
3012 /* If we got a tall enough full-width window that can be split,
3015 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3016 && window_height (window
) >= split_height_threshold
3017 && WINDOW_FULL_WIDTH_P (XWINDOW (window
)))
3018 window
= Fsplit_window (window
, Qnil
, Qnil
);
3021 Lisp_Object upper
, lower
, other
;
3023 window
= Fget_lru_window (frames
);
3024 /* If the LRU window is selected, and big enough,
3025 and can be split, split it. */
3027 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3028 && (EQ (window
, selected_window
)
3029 || EQ (XWINDOW (window
)->parent
, Qnil
))
3030 && window_height (window
) >= window_min_height
<< 1)
3031 window
= Fsplit_window (window
, Qnil
, Qnil
);
3032 /* If Fget_lru_window returned nil, try other approaches. */
3034 /* Try visible frames first. */
3036 window
= Fget_buffer_window (buffer
, Qvisible
);
3038 window
= Fget_largest_window (Qvisible
);
3039 /* If that didn't work, try iconified frames. */
3041 window
= Fget_buffer_window (buffer
, make_number (0));
3043 window
= Fget_largest_window (make_number (0));
3044 /* Try invisible frames. */
3046 window
= Fget_buffer_window (buffer
, Qt
);
3048 window
= Fget_largest_window (Qt
);
3049 /* As a last resort, make a new frame. */
3051 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
3052 /* If window appears above or below another,
3053 even out their heights. */
3054 other
= upper
= lower
= Qnil
;
3055 if (!NILP (XWINDOW (window
)->prev
))
3056 other
= upper
= XWINDOW (window
)->prev
, lower
= window
;
3057 if (!NILP (XWINDOW (window
)->next
))
3058 other
= lower
= XWINDOW (window
)->next
, upper
= window
;
3060 && !NILP (Veven_window_heights
)
3061 /* Check that OTHER and WINDOW are vertically arrayed. */
3062 && !EQ (XWINDOW (other
)->top
, XWINDOW (window
)->top
)
3063 && (XFASTINT (XWINDOW (other
)->height
)
3064 > XFASTINT (XWINDOW (window
)->height
)))
3066 int total
= (XFASTINT (XWINDOW (other
)->height
)
3067 + XFASTINT (XWINDOW (window
)->height
));
3068 enlarge_window (upper
,
3069 total
/ 2 - XFASTINT (XWINDOW (upper
)->height
),
3075 window
= Fget_lru_window (Qnil
);
3077 Fset_window_buffer (window
, buffer
);
3078 return display_buffer_1 (window
);
3082 temp_output_buffer_show (buf
)
3083 register Lisp_Object buf
;
3085 register struct buffer
*old
= current_buffer
;
3086 register Lisp_Object window
;
3087 register struct window
*w
;
3089 XBUFFER (buf
)->directory
= current_buffer
->directory
;
3092 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
3096 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
3097 set_buffer_internal (old
);
3099 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
3100 call1 (Vtemp_buffer_show_function
, buf
);
3103 window
= Fdisplay_buffer (buf
, Qnil
, Qnil
);
3105 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
3106 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
3107 Vminibuf_scroll_window
= window
;
3108 w
= XWINDOW (window
);
3109 XSETFASTINT (w
->hscroll
, 0);
3110 XSETFASTINT (w
->min_hscroll
, 0);
3111 set_marker_restricted_both (w
->start
, buf
, 1, 1);
3112 set_marker_restricted_both (w
->pointm
, buf
, 1, 1);
3114 /* Run temp-buffer-show-hook, with the chosen window selected
3115 and it sbuffer current. */
3116 if (!NILP (Vrun_hooks
))
3119 tem
= Fboundp (Qtemp_buffer_show_hook
);
3122 tem
= Fsymbol_value (Qtemp_buffer_show_hook
);
3125 int count
= specpdl_ptr
- specpdl
;
3126 Lisp_Object prev_window
;
3127 prev_window
= selected_window
;
3129 /* Select the window that was chosen, for running the hook. */
3130 record_unwind_protect (Fselect_window
, prev_window
);
3131 select_window_1 (window
, 0);
3132 Fset_buffer (w
->buffer
);
3133 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
3134 select_window_1 (prev_window
, 0);
3135 unbind_to (count
, Qnil
);
3143 make_dummy_parent (window
)
3147 register struct window
*o
, *p
;
3148 register struct Lisp_Vector
*vec
;
3151 o
= XWINDOW (window
);
3152 vec
= allocate_vectorlike ((EMACS_INT
)VECSIZE (struct window
));
3153 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
3154 vec
->contents
[i
] = ((struct Lisp_Vector
*)o
)->contents
[i
];
3155 vec
->size
= VECSIZE (struct window
);
3156 p
= (struct window
*)vec
;
3157 XSETWINDOW (new, p
);
3159 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
3161 /* Put new into window structure in place of window */
3162 replace_window (window
, new);
3175 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
3176 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
3177 WINDOW defaults to selected one and SIZE to half its size.\n\
3178 If optional third arg HORFLAG is non-nil, split side by side\n\
3179 and put SIZE columns in the first of the pair. In that case,\n\
3180 SIZE includes that window's scroll bar, or the divider column to its right.")
3181 (window
, size
, horflag
)
3182 Lisp_Object window
, size
, horflag
;
3184 register Lisp_Object
new;
3185 register struct window
*o
, *p
;
3187 register int size_int
;
3190 window
= selected_window
;
3192 CHECK_LIVE_WINDOW (window
, 0);
3194 o
= XWINDOW (window
);
3195 fo
= XFRAME (WINDOW_FRAME (o
));
3199 if (!NILP (horflag
))
3200 /* Calculate the size of the left-hand window, by dividing
3201 the usable space in columns by two.
3202 We round up, since the left-hand window may include
3203 a dividing line, while the right-hand may not. */
3204 size_int
= (XFASTINT (o
->width
) + 1) >> 1;
3206 size_int
= XFASTINT (o
->height
) >> 1;
3210 CHECK_NUMBER (size
, 1);
3211 size_int
= XINT (size
);
3214 if (MINI_WINDOW_P (o
))
3215 error ("Attempt to split minibuffer window");
3216 else if (window_fixed_size_p (o
, !NILP (horflag
), 0))
3217 error ("Attempt to split fixed-size window");
3219 check_min_window_sizes ();
3223 if (size_int
< window_min_height
)
3224 error ("Window height %d too small (after splitting)", size_int
);
3225 if (size_int
+ window_min_height
> XFASTINT (o
->height
))
3226 error ("Window height %d too small (after splitting)",
3227 XFASTINT (o
->height
) - size_int
);
3228 if (NILP (o
->parent
)
3229 || NILP (XWINDOW (o
->parent
)->vchild
))
3231 make_dummy_parent (window
);
3233 XWINDOW (new)->vchild
= window
;
3238 if (size_int
< window_min_width
)
3239 error ("Window width %d too small (after splitting)", size_int
);
3241 if (size_int
+ window_min_width
> XFASTINT (o
->width
))
3242 error ("Window width %d too small (after splitting)",
3243 XFASTINT (o
->width
) - size_int
);
3244 if (NILP (o
->parent
)
3245 || NILP (XWINDOW (o
->parent
)->hchild
))
3247 make_dummy_parent (window
);
3249 XWINDOW (new)->hchild
= window
;
3253 /* Now we know that window's parent is a vertical combination
3254 if we are dividing vertically, or a horizontal combination
3255 if we are making side-by-side windows */
3257 windows_or_buffers_changed
++;
3258 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
3259 new = make_window ();
3262 p
->frame
= o
->frame
;
3264 if (!NILP (p
->next
))
3265 XWINDOW (p
->next
)->prev
= new;
3268 p
->parent
= o
->parent
;
3270 p
->window_end_valid
= Qnil
;
3271 bzero (&p
->last_cursor
, sizeof p
->last_cursor
);
3273 /* Apportion the available frame space among the two new windows */
3275 if (!NILP (horflag
))
3277 p
->height
= o
->height
;
3279 XSETFASTINT (p
->width
, XFASTINT (o
->width
) - size_int
);
3280 XSETFASTINT (o
->width
, size_int
);
3281 XSETFASTINT (p
->left
, XFASTINT (o
->left
) + size_int
);
3286 p
->width
= o
->width
;
3287 XSETFASTINT (p
->height
, XFASTINT (o
->height
) - size_int
);
3288 XSETFASTINT (o
->height
, size_int
);
3289 XSETFASTINT (p
->top
, XFASTINT (o
->top
) + size_int
);
3292 /* Adjust glyph matrices. */
3294 Fset_window_buffer (new, o
->buffer
);
3298 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
3299 "Make current window ARG lines bigger.\n\
3300 From program, optional second arg non-nil means grow sideways ARG columns.\n\
3301 Interactively, if an argument is not given, make the window one line bigger.")
3303 register Lisp_Object arg
, side
;
3305 CHECK_NUMBER (arg
, 0);
3306 enlarge_window (selected_window
, XINT (arg
), !NILP (side
));
3308 if (! NILP (Vwindow_configuration_change_hook
))
3309 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
3314 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
3315 "Make current window ARG lines smaller.\n\
3316 From program, optional second arg non-nil means shrink sideways arg columns.\n\
3317 Interactively, if an argument is not given, make the window one line smaller.")
3319 register Lisp_Object arg
, side
;
3321 CHECK_NUMBER (arg
, 0);
3322 enlarge_window (selected_window
, -XINT (arg
), !NILP (side
));
3324 if (! NILP (Vwindow_configuration_change_hook
))
3325 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
3331 window_height (window
)
3334 register struct window
*p
= XWINDOW (window
);
3335 return XFASTINT (p
->height
);
3339 window_width (window
)
3342 register struct window
*p
= XWINDOW (window
);
3343 return XFASTINT (p
->width
);
3348 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3350 #define CURSIZE(w) \
3351 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3354 /* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3355 increase its width. Siblings of the selected window are resized to
3356 fullfil the size request. If they become too small in the process,
3357 they will be deleted. */
3360 enlarge_window (window
, delta
, widthflag
)
3362 int delta
, widthflag
;
3364 Lisp_Object parent
, next
, prev
;
3368 int (*sizefun
) P_ ((Lisp_Object
))
3369 = widthflag
? window_width
: window_height
;
3370 void (*setsizefun
) P_ ((Lisp_Object
, int, int))
3371 = (widthflag
? set_window_width
: set_window_height
);
3373 /* Check values of window_min_width and window_min_height for
3375 check_min_window_sizes ();
3377 /* Give up if this window cannot be resized. */
3378 if (window_fixed_size_p (XWINDOW (window
), widthflag
, 1))
3379 error ("Window is not resizable");
3381 /* Find the parent of the selected window. */
3384 p
= XWINDOW (window
);
3390 error ("No other window to side of this one");
3395 ? !NILP (XWINDOW (parent
)->hchild
)
3396 : !NILP (XWINDOW (parent
)->vchild
))
3402 sizep
= &CURSIZE (window
);
3405 register int maxdelta
;
3407 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
3408 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
3409 - window_min_size (XWINDOW (p
->next
),
3411 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
3412 - window_min_size (XWINDOW (p
->prev
),
3414 /* This is a frame with only one window, a minibuffer-only
3415 or a minibufferless frame. */
3418 if (delta
> maxdelta
)
3419 /* This case traps trying to make the minibuffer
3420 the full frame, or make the only window aside from the
3421 minibuffer the full frame. */
3425 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
), widthflag
, 0, 0))
3427 delete_window (window
);
3434 /* Find the total we can get from other siblings. */
3436 for (next
= p
->next
; ! NILP (next
); next
= XWINDOW (next
)->next
)
3437 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
3439 for (prev
= p
->prev
; ! NILP (prev
); prev
= XWINDOW (prev
)->prev
)
3440 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
3443 /* If we can get it all from them, do so. */
3444 if (delta
<= maximum
)
3446 Lisp_Object first_unaffected
;
3447 Lisp_Object first_affected
;
3452 first_affected
= window
;
3453 /* Look at one sibling at a time,
3454 moving away from this window in both directions alternately,
3455 and take as much as we can get without deleting that sibling. */
3456 while (delta
!= 0 && (!NILP (next
) || !NILP (prev
)))
3460 int this_one
= ((*sizefun
) (next
)
3461 - window_min_size (XWINDOW (next
),
3462 widthflag
, 0, &fixed_p
));
3465 if (this_one
> delta
)
3468 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
3469 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
3474 next
= XWINDOW (next
)->next
;
3482 int this_one
= ((*sizefun
) (prev
)
3483 - window_min_size (XWINDOW (prev
),
3484 widthflag
, 0, &fixed_p
));
3487 if (this_one
> delta
)
3490 first_affected
= prev
;
3492 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
3493 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
3498 prev
= XWINDOW (prev
)->prev
;
3502 xassert (delta
== 0);
3504 /* Now recalculate the edge positions of all the windows affected,
3505 based on the new sizes. */
3506 first_unaffected
= next
;
3507 prev
= first_affected
;
3508 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
3509 prev
= next
, next
= XWINDOW (next
)->next
)
3511 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
3512 /* This does not change size of NEXT,
3513 but it propagates the new top edge to its children */
3514 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
3519 register int delta1
;
3520 register int opht
= (*sizefun
) (parent
);
3522 /* If trying to grow this window to or beyond size of the parent,
3523 make delta1 so big that, on shrinking back down,
3524 all the siblings end up with less than one line and are deleted. */
3525 if (opht
<= XINT (*sizep
) + delta
)
3526 delta1
= opht
* opht
* 2;
3529 /* Otherwise, make delta1 just right so that if we add
3530 delta1 lines to this window and to the parent, and then
3531 shrink the parent back to its original size, the new
3532 proportional size of this window will increase by delta.
3534 The function size_window will compute the new height h'
3535 of the window from delta1 as:
3538 x = delta1 - delta1/n * n for the 1st resizable child
3541 where n is the number of children that can be resized.
3542 We can ignore x by choosing a delta1 that is a multiple of
3543 n. We want the height of this window to come out as
3553 The number of children n rquals the number of resizable
3554 children of this window + 1 because we know window itself
3555 is resizable (otherwise we would have signalled an error. */
3557 struct window
*w
= XWINDOW (window
);
3561 for (s
= w
->next
; !NILP (s
); s
= XWINDOW (s
)->next
)
3562 if (!window_fixed_size_p (XWINDOW (s
), widthflag
, 0))
3564 for (s
= w
->prev
; !NILP (s
); s
= XWINDOW (s
)->prev
)
3565 if (!window_fixed_size_p (XWINDOW (s
), widthflag
, 0))
3571 /* Add delta1 lines or columns to this window, and to the parent,
3572 keeping things consistent while not affecting siblings. */
3573 XSETINT (CURSIZE (parent
), opht
+ delta1
);
3574 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
3576 /* Squeeze out delta1 lines or columns from our parent,
3577 shriking this window and siblings proportionately.
3578 This brings parent back to correct size.
3579 Delta1 was calculated so this makes this window the desired size,
3580 taking it all out of the siblings. */
3581 (*setsizefun
) (parent
, opht
, 0);
3584 XSETFASTINT (p
->last_modified
, 0);
3585 XSETFASTINT (p
->last_overlay_modified
, 0);
3587 /* Adjust glyph matrices. */
3588 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
3596 /***********************************************************************
3597 Resizing Mini-Windows
3598 ***********************************************************************/
3600 static void shrink_window_lowest_first
P_ ((struct window
*, int));
3602 enum save_restore_action
3609 static int save_restore_orig_size
P_ ((struct window
*,
3610 enum save_restore_action
));
3612 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3613 from lowest windows first. */
3616 shrink_window_lowest_first (w
, height
)
3624 xassert (!MINI_WINDOW_P (w
));
3626 /* Set redisplay hints. */
3627 XSETFASTINT (w
->last_modified
, 0);
3628 XSETFASTINT (w
->last_overlay_modified
, 0);
3629 windows_or_buffers_changed
++;
3630 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
3632 old_height
= XFASTINT (w
->height
);
3633 XSETFASTINT (w
->height
, height
);
3635 if (!NILP (w
->hchild
))
3637 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
3639 c
= XWINDOW (child
);
3641 shrink_window_lowest_first (c
, height
);
3644 else if (!NILP (w
->vchild
))
3646 Lisp_Object last_child
;
3647 int delta
= old_height
- height
;
3652 /* Find the last child. We are taking space from lowest windows
3653 first, so we iterate over children from the last child
3655 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
3658 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3659 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
3663 c
= XWINDOW (child
);
3664 this_one
= XFASTINT (c
->height
) - MIN_SAFE_WINDOW_HEIGHT
;
3666 if (this_one
> delta
)
3669 shrink_window_lowest_first (c
, XFASTINT (c
->height
) - this_one
);
3673 /* Compute new positions. */
3674 last_top
= XINT (w
->top
);
3675 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
3677 c
= XWINDOW (child
);
3678 c
->top
= make_number (last_top
);
3679 shrink_window_lowest_first (c
, XFASTINT (c
->height
));
3680 last_top
+= XFASTINT (c
->height
);
3686 /* Save, restore, or check positions and sizes in the window tree
3687 rooted at W. ACTION says what to do.
3689 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3690 members are valid for all windows in the window tree. Value is
3691 non-zero if they are valid.
3693 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3694 orig_top and orig_height for all windows in the tree.
3696 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3697 values stored in orig_top and orig_height for all windows. */
3700 save_restore_orig_size (w
, action
)
3702 enum save_restore_action action
;
3708 if (!NILP (w
->hchild
))
3710 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
3713 else if (!NILP (w
->vchild
))
3715 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
3721 case CHECK_ORIG_SIZES
:
3722 if (!INTEGERP (w
->orig_top
) || !INTEGERP (w
->orig_height
))
3726 case SAVE_ORIG_SIZES
:
3727 w
->orig_top
= w
->top
;
3728 w
->orig_height
= w
->height
;
3729 XSETFASTINT (w
->last_modified
, 0);
3730 XSETFASTINT (w
->last_overlay_modified
, 0);
3733 case RESTORE_ORIG_SIZES
:
3734 xassert (INTEGERP (w
->orig_top
) && INTEGERP (w
->orig_height
));
3735 w
->top
= w
->orig_top
;
3736 w
->height
= w
->orig_height
;
3737 w
->orig_height
= w
->orig_top
= Qnil
;
3738 XSETFASTINT (w
->last_modified
, 0);
3739 XSETFASTINT (w
->last_overlay_modified
, 0);
3746 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
3753 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3754 without deleting other windows. */
3757 grow_mini_window (w
, delta
)
3761 struct frame
*f
= XFRAME (w
->frame
);
3762 struct window
*root
;
3764 xassert (MINI_WINDOW_P (w
));
3765 xassert (delta
>= 0);
3767 /* Check values of window_min_width and window_min_height for
3769 check_min_window_sizes ();
3771 /* Compute how much we can enlarge the mini-window without deleting
3773 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
3776 int min_height
= window_min_size (root
, 0, 0, 0);
3777 if (XFASTINT (root
->height
) - delta
< min_height
)
3778 delta
= XFASTINT (root
->height
) - min_height
;
3783 /* Save original window sizes and positions, if not already done. */
3784 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
3785 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
3787 /* Shrink other windows. */
3788 shrink_window_lowest_first (root
, XFASTINT (root
->height
) - delta
);
3790 /* Grow the mini-window. */
3791 w
->top
= make_number (XFASTINT (root
->top
) + XFASTINT (root
->height
));
3792 w
->height
= make_number (XFASTINT (w
->height
) + delta
);
3793 XSETFASTINT (w
->last_modified
, 0);
3794 XSETFASTINT (w
->last_overlay_modified
, 0);
3801 /* Shrink mini-window W. If there is recorded info about window sizes
3802 before a call to grow_mini_window, restore recorded window sizes.
3803 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3807 shrink_mini_window (w
)
3810 struct frame
*f
= XFRAME (w
->frame
);
3811 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
3813 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
3815 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
3817 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
3818 windows_or_buffers_changed
= 1;
3820 else if (XFASTINT (w
->height
) > 1)
3822 /* Distribute the additional lines of the mini-window
3823 among the other windows. */
3825 XSETWINDOW (window
, w
);
3826 enlarge_window (window
, 1 - XFASTINT (w
->height
), 0);
3832 /* Mark window cursors off for all windows in the window tree rooted
3833 at W by setting their phys_cursor_on_p flag to zero. Called from
3834 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3835 the frame are cleared. */
3838 mark_window_cursors_off (w
)
3843 if (!NILP (w
->hchild
))
3844 mark_window_cursors_off (XWINDOW (w
->hchild
));
3845 else if (!NILP (w
->vchild
))
3846 mark_window_cursors_off (XWINDOW (w
->vchild
));
3848 w
->phys_cursor_on_p
= 0;
3850 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
3855 /* Return number of lines of text (not counting mode line) in W. */
3858 window_internal_height (w
)
3861 int ht
= XFASTINT (w
->height
);
3863 if (MINI_WINDOW_P (w
))
3866 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
3867 || !NILP (w
->next
) || !NILP (w
->prev
)
3868 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w
))))
3875 /* Return the number of columns in W.
3876 Don't count columns occupied by scroll bars or the vertical bar
3877 separating W from the sibling to its right. */
3880 window_internal_width (w
)
3883 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
3884 int width
= XINT (w
->width
);
3886 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3887 /* Scroll bars occupy a few columns. */
3888 width
-= FRAME_SCROLL_BAR_COLS (f
);
3889 else if (!WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
3890 /* The column of `|' characters separating side-by-side windows
3891 occupies one column only. */
3894 /* On window-systems, areas to the left and right of the window
3895 are used to display bitmaps there. */
3896 if (FRAME_WINDOW_P (f
))
3897 width
-= FRAME_FLAGS_AREA_COLS (f
);
3903 /************************************************************************
3905 ***********************************************************************/
3907 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3908 one screen-full, which is defined as the height of the window minus
3909 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3910 instead. Negative values of N mean scroll down. NOERROR non-zero
3911 means don't signal an error if we try to move over BEGV or ZV,
3915 window_scroll (window
, n
, whole
, noerror
)
3921 /* If we must, use the pixel-based version which is much slower than
3922 the line-based one but can handle varying line heights. */
3923 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
3924 window_scroll_pixel_based (window
, n
, whole
, noerror
);
3926 window_scroll_line_based (window
, n
, whole
, noerror
);
3930 /* Implementation of window_scroll that works based on pixel line
3931 heights. See the comment of window_scroll for parameter
3935 window_scroll_pixel_based (window
, n
, whole
, noerror
)
3942 struct window
*w
= XWINDOW (window
);
3943 struct text_pos start
;
3945 int this_scroll_margin
;
3947 /* True if we fiddled the window vscroll field without really scrolling. */
3950 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
3952 /* If PT is not visible in WINDOW, move back one half of
3954 tem
= Fpos_visible_in_window_p (make_number (PT
), window
, Qnil
);
3957 /* Move backward half the height of the window. Performance note:
3958 vmotion used here is about 10% faster, but would give wrong
3959 results for variable height lines. */
3960 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
3961 it
.current_y
= it
.last_visible_y
;
3962 move_it_vertically (&it
, -it
.last_visible_y
/ 2);
3964 /* The function move_iterator_vertically may move over more than
3965 the specified y-distance. If it->w is small, e.g. a
3966 mini-buffer window, we may end up in front of the window's
3967 display area. This is the case when Start displaying at the
3968 start of the line containing PT in this case. */
3969 if (it
.current_y
<= 0)
3971 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
3972 move_it_vertically (&it
, 0);
3976 start
= it
.current
.pos
;
3979 /* If scroll_preserve_screen_position is non-zero, we try to set
3980 point in the same window line as it is now, so get that line. */
3981 if (!NILP (Vscroll_preserve_screen_position
))
3983 start_display (&it
, w
, start
);
3984 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
3985 preserve_y
= it
.current_y
;
3990 /* Move iterator it from start the specified distance forward or
3991 backward. The result is the new window start. */
3992 start_display (&it
, w
, start
);
3995 int screen_full
= (it
.last_visible_y
3996 - next_screen_context_lines
* CANON_Y_UNIT (it
.f
));
3997 int direction
= n
< 0 ? -1 : 1;
3998 int dy
= direction
* screen_full
;
4000 /* Note that move_it_vertically always moves the iterator to the
4001 start of a line. So, if the last line doesn't have a newline,
4002 we would end up at the start of the line ending at ZV. */
4004 move_it_vertically_backward (&it
, -dy
);
4006 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
4007 MOVE_TO_POS
| MOVE_TO_Y
);
4010 move_it_by_lines (&it
, n
, 1);
4012 /* End if we end up at ZV or BEGV. */
4013 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
4014 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
4016 if (IT_CHARPOS (it
) == ZV
)
4018 if (it
.current_y
+ it
.max_ascent
+ it
.max_descent
4019 > it
.last_visible_y
)
4021 /* The last line was only partially visible, make it fully
4023 w
->vscroll
= (it
.last_visible_y
4024 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
4025 adjust_glyphs (it
.f
);
4030 Fsignal (Qend_of_buffer
, Qnil
);
4034 if (w
->vscroll
!= 0)
4035 /* The first line was only partially visible, make it fully
4041 Fsignal (Qbeginning_of_buffer
, Qnil
);
4044 /* If control gets here, then we vscrolled. */
4046 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
4048 /* Don't try to change the window start below. */
4054 /* Set the window start, and set up the window for redisplay. */
4055 set_marker_restricted (w
->start
, make_number (IT_CHARPOS (it
)),
4057 w
->start_at_line_beg
= Fbolp ();
4058 w
->update_mode_line
= Qt
;
4059 XSETFASTINT (w
->last_modified
, 0);
4060 XSETFASTINT (w
->last_overlay_modified
, 0);
4061 /* Set force_start so that redisplay_window will run the
4062 window-scroll-functions. */
4063 w
->force_start
= Qt
;
4066 it
.current_y
= it
.vpos
= 0;
4068 /* Preserve the screen position if we must. */
4069 if (preserve_y
>= 0)
4071 move_it_to (&it
, -1, -1, preserve_y
, -1, MOVE_TO_Y
);
4072 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4076 /* Move PT out of scroll margins. */
4077 this_scroll_margin
= max (0, scroll_margin
);
4078 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->height
) / 4);
4079 this_scroll_margin
*= CANON_Y_UNIT (it
.f
);
4083 /* We moved the window start towards ZV, so PT may be now
4084 in the scroll margin at the top. */
4085 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4086 while (it
.current_y
< this_scroll_margin
)
4087 move_it_by_lines (&it
, 1, 1);
4088 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4092 int charpos
, bytepos
;
4094 /* We moved the window start towards BEGV, so PT may be now
4095 in the scroll margin at the bottom. */
4096 move_it_to (&it
, PT
, -1,
4097 it
.last_visible_y
- this_scroll_margin
- 1, -1,
4098 MOVE_TO_POS
| MOVE_TO_Y
);
4100 /* Save our position, in case it's correct. */
4101 charpos
= IT_CHARPOS (it
);
4102 bytepos
= IT_BYTEPOS (it
);
4104 /* See if point is on a partially visible line at the end. */
4105 move_it_by_lines (&it
, 1, 1);
4106 if (it
.current_y
> it
.last_visible_y
)
4107 /* The last line was only partially visible, so back up two
4108 lines to make sure we're on a fully visible line. */
4110 move_it_by_lines (&it
, -2, 0);
4111 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4114 /* No, the position we saved is OK, so use it. */
4115 SET_PT_BOTH (charpos
, bytepos
);
4121 /* Implementation of window_scroll that works based on screen lines.
4122 See the comment of window_scroll for parameter descriptions. */
4125 window_scroll_line_based (window
, n
, whole
, noerror
)
4131 register struct window
*w
= XWINDOW (window
);
4132 register int opoint
= PT
, opoint_byte
= PT_BYTE
;
4133 register int pos
, pos_byte
;
4134 register int ht
= window_internal_height (w
);
4135 register Lisp_Object tem
;
4139 struct position posit
;
4142 startpos
= marker_position (w
->start
);
4144 posit
= *compute_motion (startpos
, 0, 0, 0,
4146 window_internal_width (w
), XINT (w
->hscroll
),
4148 original_vpos
= posit
.vpos
;
4150 XSETFASTINT (tem
, PT
);
4151 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
4155 Fvertical_motion (make_number (- (ht
/ 2)), window
);
4160 lose
= n
< 0 && PT
== BEGV
;
4161 Fvertical_motion (make_number (n
), window
);
4165 SET_PT_BOTH (opoint
, opoint_byte
);
4172 Fsignal (Qbeginning_of_buffer
, Qnil
);
4177 int this_scroll_margin
= scroll_margin
;
4179 /* Don't use a scroll margin that is negative or too large. */
4180 if (this_scroll_margin
< 0)
4181 this_scroll_margin
= 0;
4183 if (XINT (w
->height
) < 4 * scroll_margin
)
4184 this_scroll_margin
= XINT (w
->height
) / 4;
4186 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
4187 w
->start_at_line_beg
= bolp
;
4188 w
->update_mode_line
= Qt
;
4189 XSETFASTINT (w
->last_modified
, 0);
4190 XSETFASTINT (w
->last_overlay_modified
, 0);
4191 /* Set force_start so that redisplay_window will run
4192 the window-scroll-functions. */
4193 w
->force_start
= Qt
;
4195 if (whole
&& !NILP (Vscroll_preserve_screen_position
))
4197 SET_PT_BOTH (pos
, pos_byte
);
4198 Fvertical_motion (make_number (original_vpos
), window
);
4200 /* If we scrolled forward, put point enough lines down
4201 that it is outside the scroll margin. */
4206 if (this_scroll_margin
> 0)
4208 SET_PT_BOTH (pos
, pos_byte
);
4209 Fvertical_motion (make_number (this_scroll_margin
), window
);
4215 if (top_margin
<= opoint
)
4216 SET_PT_BOTH (opoint
, opoint_byte
);
4217 else if (!NILP (Vscroll_preserve_screen_position
))
4219 SET_PT_BOTH (pos
, pos_byte
);
4220 Fvertical_motion (make_number (original_vpos
), window
);
4223 SET_PT (top_margin
);
4229 /* If we scrolled backward, put point near the end of the window
4230 but not within the scroll margin. */
4231 SET_PT_BOTH (pos
, pos_byte
);
4232 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
4233 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
4236 bottom_margin
= PT
+ 1;
4238 if (bottom_margin
> opoint
)
4239 SET_PT_BOTH (opoint
, opoint_byte
);
4242 if (!NILP (Vscroll_preserve_screen_position
))
4244 SET_PT_BOTH (pos
, pos_byte
);
4245 Fvertical_motion (make_number (original_vpos
), window
);
4248 Fvertical_motion (make_number (-1), window
);
4257 Fsignal (Qend_of_buffer
, Qnil
);
4262 /* Scroll selected_window up or down. If N is nil, scroll a
4263 screen-full which is defined as the height of the window minus
4264 next_screen_context_lines. If N is the symbol `-', scroll.
4265 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4266 up. This is the guts of Fscroll_up and Fscroll_down. */
4269 scroll_command (n
, direction
)
4273 register int defalt
;
4274 int count
= specpdl_ptr
- specpdl
;
4276 xassert (abs (direction
) == 1);
4278 /* If selected window's buffer isn't current, make it current for
4279 the moment. But don't screw up if window_scroll gets an error. */
4280 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
4282 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
4283 Fset_buffer (XWINDOW (selected_window
)->buffer
);
4285 /* Make redisplay consider other windows than just selected_window. */
4286 ++windows_or_buffers_changed
;
4289 defalt
= (window_internal_height (XWINDOW (selected_window
))
4290 - next_screen_context_lines
);
4291 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
4294 window_scroll (selected_window
, defalt
, 1, 0);
4295 else if (EQ (n
, Qminus
))
4296 window_scroll (selected_window
, - defalt
, 1, 0);
4299 n
= Fprefix_numeric_value (n
);
4300 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
4303 unbind_to (count
, Qnil
);
4306 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
4307 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
4308 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4309 Negative ARG means scroll downward.\n\
4310 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4311 When calling from a program, supply as argument a number, nil, or `-'.")
4315 scroll_command (arg
, 1);
4319 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
4320 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
4321 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4322 Negative ARG means scroll upward.\n\
4323 If ARG is the atom `-', scroll upward by nearly full screen.\n\
4324 When calling from a program, supply as argument a number, nil, or `-'.")
4328 scroll_command (arg
, -1);
4332 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
4333 "Return the other window for \"other window scroll\" commands.\n\
4334 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4335 specifies the window.\n\
4336 If `other-window-scroll-buffer' is non-nil, a window\n\
4337 showing that buffer is used.")
4342 if (MINI_WINDOW_P (XWINDOW (selected_window
))
4343 && !NILP (Vminibuf_scroll_window
))
4344 window
= Vminibuf_scroll_window
;
4345 /* If buffer is specified, scroll that buffer. */
4346 else if (!NILP (Vother_window_scroll_buffer
))
4348 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
4350 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
4354 /* Nothing specified; look for a neighboring window on the same
4356 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
4358 if (EQ (window
, selected_window
))
4359 /* That didn't get us anywhere; look for a window on another
4362 window
= Fnext_window (window
, Qnil
, Qt
);
4363 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
4364 && ! EQ (window
, selected_window
));
4367 CHECK_LIVE_WINDOW (window
, 0);
4369 if (EQ (window
, selected_window
))
4370 error ("There is no other window");
4375 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
4376 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
4377 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4378 The next window is the one below the current one; or the one at the top\n\
4379 if the current one is at the bottom. Negative ARG means scroll downward.\n\
4380 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4381 When calling from a program, supply as argument a number, nil, or `-'.\n\
4383 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4384 specifies the window to scroll.\n\
4385 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
4386 showing that buffer, popping the buffer up if necessary.")
4388 register Lisp_Object arg
;
4390 register Lisp_Object window
;
4391 register int defalt
;
4392 register struct window
*w
;
4393 register int count
= specpdl_ptr
- specpdl
;
4395 window
= Fother_window_for_scrolling ();
4397 w
= XWINDOW (window
);
4398 defalt
= window_internal_height (w
) - next_screen_context_lines
;
4399 if (defalt
< 1) defalt
= 1;
4401 /* Don't screw up if window_scroll gets an error. */
4402 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
4403 ++windows_or_buffers_changed
;
4405 Fset_buffer (w
->buffer
);
4406 SET_PT (marker_position (w
->pointm
));
4409 window_scroll (window
, defalt
, 1, 1);
4410 else if (EQ (arg
, Qminus
))
4411 window_scroll (window
, -defalt
, 1, 1);
4416 CHECK_NUMBER (arg
, 0);
4417 window_scroll (window
, XINT (arg
), 0, 1);
4420 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
4421 unbind_to (count
, Qnil
);
4426 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 1, "P",
4427 "Scroll selected window display ARG columns left.\n\
4428 Default for ARG is window width minus 2.")
4430 register Lisp_Object arg
;
4434 struct window
*w
= XWINDOW (selected_window
);
4437 XSETFASTINT (arg
, window_internal_width (w
) - 2);
4439 arg
= Fprefix_numeric_value (arg
);
4441 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
4442 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
4444 if (interactive_p (0))
4445 w
->min_hscroll
= w
->hscroll
;
4450 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 1, "P",
4451 "Scroll selected window display ARG columns right.\n\
4452 Default for ARG is window width minus 2.")
4454 register Lisp_Object arg
;
4458 struct window
*w
= XWINDOW (selected_window
);
4461 XSETFASTINT (arg
, window_internal_width (w
) - 2);
4463 arg
= Fprefix_numeric_value (arg
);
4465 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
4466 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
4468 if (interactive_p (0))
4469 w
->min_hscroll
= w
->hscroll
;
4474 /* Value is the number of lines actually displayed in window W,
4475 as opposed to its height. */
4478 displayed_window_lines (w
)
4482 struct text_pos start
;
4483 int height
= window_box_height (w
);
4484 struct buffer
*old_buffer
;
4487 if (XBUFFER (w
->buffer
) != current_buffer
)
4489 old_buffer
= current_buffer
;
4490 set_buffer_internal (XBUFFER (w
->buffer
));
4495 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4496 start_display (&it
, w
, start
);
4497 move_it_vertically (&it
, height
);
4498 bottom_y
= line_bottom_y (&it
);
4500 /* Add in empty lines at the bottom of the window. */
4501 if (bottom_y
< height
)
4503 int uy
= CANON_Y_UNIT (it
.f
);
4504 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
4508 set_buffer_internal (old_buffer
);
4514 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
4515 "Center point in window and redisplay frame.\n\
4516 With prefix argument ARG, recenter putting point on screen line ARG\n\
4517 relative to the current window. If ARG is negative, it counts up from the\n\
4518 bottom of the window. (ARG should be less than the height of the window.)\n\
4520 If ARG is omitted or nil, erase the entire frame and then\n\
4521 redraw with point in the center of the current window.\n\
4522 Just C-u as prefix means put point in the center of the window\n\
4523 and redisplay normally--don't erase and redraw the frame.")
4525 register Lisp_Object arg
;
4527 struct window
*w
= XWINDOW (selected_window
);
4528 struct buffer
*buf
= XBUFFER (w
->buffer
);
4529 struct buffer
*obuf
= current_buffer
;
4531 int charpos
, bytepos
;
4537 /* Invalidate pixel data calculated for all compositions. */
4538 for (i
= 0; i
< n_compositions
; i
++)
4539 composition_table
[i
]->font
= NULL
;
4541 Fredraw_frame (w
->frame
);
4542 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
4545 else if (CONSP (arg
)) /* Just C-u. */
4549 arg
= Fprefix_numeric_value (arg
);
4550 CHECK_NUMBER (arg
, 0);
4553 set_buffer_internal (buf
);
4555 /* Handle centering on a gfaphical frame specially. Such frames can
4556 have variable-height lines and centering point on the basis of
4557 line counts would lead to strange effects. */
4558 if (center_p
&& FRAME_WINDOW_P (XFRAME (w
->frame
)))
4563 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
4564 start_display (&it
, w
, pt
);
4565 move_it_vertically (&it
, - it
.last_visible_y
/ 2);
4566 charpos
= IT_CHARPOS (it
);
4567 bytepos
= IT_BYTEPOS (it
);
4571 struct position pos
;
4575 int ht
= displayed_window_lines (w
);
4576 arg
= make_number (ht
/ 2);
4578 else if (XINT (arg
) < 0)
4580 int ht
= displayed_window_lines (w
);
4581 XSETINT (arg
, XINT (arg
) + ht
);
4584 pos
= *vmotion (PT
, - XINT (arg
), w
);
4585 charpos
= pos
.bufpos
;
4586 bytepos
= pos
.bytepos
;
4589 /* Set the new window start. */
4590 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
4591 w
->window_end_valid
= Qnil
;
4592 w
->force_start
= Qt
;
4593 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
4594 w
->start_at_line_beg
= Qt
;
4596 w
->start_at_line_beg
= Qnil
;
4598 set_buffer_internal (obuf
);
4603 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
4605 "Return the height in lines of the text display area of WINDOW.\n\
4606 This doesn't include the mode-line (or header-line if any) or any\n\
4607 partial-height lines in the text display area.")
4611 struct window
*w
= decode_window (window
);
4612 int pixel_height
= window_box_height (w
);
4613 int line_height
= pixel_height
/ CANON_Y_UNIT (XFRAME (w
->frame
));
4614 return make_number (line_height
);
4619 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
4621 "Position point relative to window.\n\
4622 With no argument, position point at center of window.\n\
4623 An argument specifies vertical position within the window;\n\
4624 zero means top of window, negative means relative to bottom of window.")
4628 struct window
*w
= XWINDOW (selected_window
);
4632 window
= selected_window
;
4633 start
= marker_position (w
->start
);
4634 if (start
< BEGV
|| start
> ZV
)
4636 int height
= window_internal_height (w
);
4637 Fvertical_motion (make_number (- (height
/ 2)), window
);
4638 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
4639 w
->start_at_line_beg
= Fbolp ();
4640 w
->force_start
= Qt
;
4643 Fgoto_char (w
->start
);
4645 lines
= displayed_window_lines (w
);
4647 XSETFASTINT (arg
, lines
/ 2);
4650 arg
= Fprefix_numeric_value (arg
);
4652 XSETINT (arg
, XINT (arg
) + lines
);
4655 /* Skip past a partially visible first line. */
4657 XSETINT (arg
, XINT (arg
) + 1);
4659 return Fvertical_motion (arg
, window
);
4664 /***********************************************************************
4665 Window Configuration
4666 ***********************************************************************/
4668 struct save_window_data
4670 EMACS_INT size_from_Lisp_Vector_struct
;
4671 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4672 Lisp_Object frame_width
, frame_height
, frame_menu_bar_lines
;
4673 Lisp_Object frame_tool_bar_lines
;
4674 Lisp_Object selected_frame
;
4675 Lisp_Object current_window
;
4676 Lisp_Object current_buffer
;
4677 Lisp_Object minibuf_scroll_window
;
4678 Lisp_Object root_window
;
4679 Lisp_Object focus_frame
;
4680 /* Record the values of window-min-width and window-min-height
4681 so that window sizes remain consistent with them. */
4682 Lisp_Object min_width
, min_height
;
4683 /* A vector, each of whose elements is a struct saved_window
4685 Lisp_Object saved_windows
;
4688 /* This is saved as a Lisp_Vector */
4691 /* these first two must agree with struct Lisp_Vector in lisp.h */
4692 EMACS_INT size_from_Lisp_Vector_struct
;
4693 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4696 Lisp_Object buffer
, start
, pointm
, mark
;
4697 Lisp_Object left
, top
, width
, height
, hscroll
, min_hscroll
;
4698 Lisp_Object parent
, prev
;
4699 Lisp_Object start_at_line_beg
;
4700 Lisp_Object display_table
;
4701 Lisp_Object orig_top
, orig_height
;
4704 #define SAVED_WINDOW_VECTOR_SIZE 17 /* Arg to Fmake_vector */
4706 #define SAVED_WINDOW_N(swv,n) \
4707 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4709 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
4710 "Return t if OBJECT is a window-configuration object.")
4714 if (WINDOW_CONFIGURATIONP (object
))
4719 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
4720 "Return the frame that CONFIG, a window-configuration object, is about.")
4724 register struct save_window_data
*data
;
4725 struct Lisp_Vector
*saved_windows
;
4727 if (! WINDOW_CONFIGURATIONP (config
))
4728 wrong_type_argument (Qwindow_configuration_p
, config
);
4730 data
= (struct save_window_data
*) XVECTOR (config
);
4731 saved_windows
= XVECTOR (data
->saved_windows
);
4732 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4735 DEFUN ("set-window-configuration", Fset_window_configuration
,
4736 Sset_window_configuration
, 1, 1, 0,
4737 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4738 CONFIGURATION must be a value previously returned\n\
4739 by `current-window-configuration' (which see).\n\
4740 If CONFIGURATION was made from a frame that is now deleted,\n\
4741 only frame-independent values can be restored. In this case,\n\
4742 the return value is nil. Otherwise the value is t.")
4744 Lisp_Object configuration
;
4746 register struct save_window_data
*data
;
4747 struct Lisp_Vector
*saved_windows
;
4748 Lisp_Object new_current_buffer
;
4753 while (!WINDOW_CONFIGURATIONP (configuration
))
4754 wrong_type_argument (Qwindow_configuration_p
, configuration
);
4756 data
= (struct save_window_data
*) XVECTOR (configuration
);
4757 saved_windows
= XVECTOR (data
->saved_windows
);
4759 new_current_buffer
= data
->current_buffer
;
4760 if (NILP (XBUFFER (new_current_buffer
)->name
))
4761 new_current_buffer
= Qnil
;
4764 if (XBUFFER (new_current_buffer
) == current_buffer
)
4768 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4771 /* If f is a dead frame, don't bother rebuilding its window tree.
4772 However, there is other stuff we should still try to do below. */
4773 if (FRAME_LIVE_P (f
))
4775 register struct window
*w
;
4776 register struct saved_window
*p
;
4777 struct window
*root_window
;
4778 struct window
**leaf_windows
;
4782 /* If the frame has been resized since this window configuration was
4783 made, we change the frame to the size specified in the
4784 configuration, restore the configuration, and then resize it
4785 back. We keep track of the prevailing height in these variables. */
4786 int previous_frame_height
= FRAME_HEIGHT (f
);
4787 int previous_frame_width
= FRAME_WIDTH (f
);
4788 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
4789 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
4791 /* The mouse highlighting code could get screwed up
4792 if it runs during this. */
4795 if (XFASTINT (data
->frame_height
) != previous_frame_height
4796 || XFASTINT (data
->frame_width
) != previous_frame_width
)
4797 change_frame_size (f
, XFASTINT (data
->frame_height
),
4798 XFASTINT (data
->frame_width
), 0, 0, 0);
4799 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4800 if (XFASTINT (data
->frame_menu_bar_lines
)
4801 != previous_frame_menu_bar_lines
)
4802 x_set_menu_bar_lines (f
, data
->frame_menu_bar_lines
, make_number (0));
4803 #ifdef HAVE_WINDOW_SYSTEM
4804 if (XFASTINT (data
->frame_tool_bar_lines
)
4805 != previous_frame_tool_bar_lines
)
4806 x_set_tool_bar_lines (f
, data
->frame_tool_bar_lines
, make_number (0));
4810 /* "Swap out" point from the selected window
4811 into its buffer. We do this now, before
4812 restoring the window contents, and prevent it from
4813 being done later on when we select a new window. */
4814 if (! NILP (XWINDOW (selected_window
)->buffer
))
4816 w
= XWINDOW (selected_window
);
4817 set_marker_both (w
->pointm
,
4819 BUF_PT (XBUFFER (w
->buffer
)),
4820 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
4823 windows_or_buffers_changed
++;
4824 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4826 /* Problem: Freeing all matrices and later allocating them again
4827 is a serious redisplay flickering problem. What we would
4828 really like to do is to free only those matrices not reused
4830 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4832 = (struct window
**) alloca (count_windows (root_window
)
4833 * sizeof (struct window
*));
4834 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
4836 /* Temporarily avoid any problems with windows that are smaller
4837 than they are supposed to be. */
4838 window_min_height
= 1;
4839 window_min_width
= 1;
4842 Mark all windows now on frame as "deleted".
4843 Restoring the new configuration "undeletes" any that are in it.
4845 Save their current buffers in their height fields, since we may
4846 need it later, if a buffer saved in the configuration is now
4848 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4850 for (k
= 0; k
< saved_windows
->size
; k
++)
4852 p
= SAVED_WINDOW_N (saved_windows
, k
);
4853 w
= XWINDOW (p
->window
);
4856 if (!NILP (p
->parent
))
4857 w
->parent
= SAVED_WINDOW_N (saved_windows
,
4858 XFASTINT (p
->parent
))->window
;
4862 if (!NILP (p
->prev
))
4864 w
->prev
= SAVED_WINDOW_N (saved_windows
,
4865 XFASTINT (p
->prev
))->window
;
4866 XWINDOW (w
->prev
)->next
= p
->window
;
4871 if (!NILP (w
->parent
))
4873 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
4875 XWINDOW (w
->parent
)->vchild
= p
->window
;
4876 XWINDOW (w
->parent
)->hchild
= Qnil
;
4880 XWINDOW (w
->parent
)->hchild
= p
->window
;
4881 XWINDOW (w
->parent
)->vchild
= Qnil
;
4886 /* If we squirreled away the buffer in the window's height,
4888 if (BUFFERP (w
->height
))
4889 w
->buffer
= w
->height
;
4892 w
->width
= p
->width
;
4893 w
->height
= p
->height
;
4894 w
->hscroll
= p
->hscroll
;
4895 w
->min_hscroll
= p
->min_hscroll
;
4896 w
->display_table
= p
->display_table
;
4897 w
->orig_top
= p
->orig_top
;
4898 w
->orig_height
= p
->orig_height
;
4899 XSETFASTINT (w
->last_modified
, 0);
4900 XSETFASTINT (w
->last_overlay_modified
, 0);
4902 /* Reinstall the saved buffer and pointers into it. */
4903 if (NILP (p
->buffer
))
4904 w
->buffer
= p
->buffer
;
4907 if (!NILP (XBUFFER (p
->buffer
)->name
))
4908 /* If saved buffer is alive, install it. */
4910 w
->buffer
= p
->buffer
;
4911 w
->start_at_line_beg
= p
->start_at_line_beg
;
4912 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
4913 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
4914 Fset_marker (XBUFFER (w
->buffer
)->mark
,
4915 p
->mark
, w
->buffer
);
4917 /* As documented in Fcurrent_window_configuration, don't
4918 save the location of point in the buffer which was current
4919 when the window configuration was recorded. */
4920 if (!EQ (p
->buffer
, new_current_buffer
)
4921 && XBUFFER (p
->buffer
) == current_buffer
)
4922 Fgoto_char (w
->pointm
);
4924 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
4925 /* Else unless window has a live buffer, get one. */
4927 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
4928 /* This will set the markers to beginning of visible
4930 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
4931 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
4932 w
->start_at_line_beg
= Qt
;
4935 /* Keeping window's old buffer; make sure the markers
4938 /* Set window markers at start of visible range. */
4939 if (XMARKER (w
->start
)->buffer
== 0)
4940 set_marker_restricted (w
->start
, make_number (0),
4942 if (XMARKER (w
->pointm
)->buffer
== 0)
4943 set_marker_restricted_both (w
->pointm
, w
->buffer
,
4944 BUF_PT (XBUFFER (w
->buffer
)),
4945 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
4946 w
->start_at_line_beg
= Qt
;
4951 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
4952 /* Prevent "swapping out point" in the old selected window
4953 using the buffer that has been restored into it.
4954 That swapping out has already been done,
4955 near the beginning of this function. */
4956 selected_window
= Qnil
;
4957 Fselect_window (data
->current_window
);
4958 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
4961 if (NILP (data
->focus_frame
)
4962 || (FRAMEP (data
->focus_frame
)
4963 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
4964 Fredirect_frame_focus (frame
, data
->focus_frame
);
4966 #if 0 /* I don't understand why this is needed, and it causes problems
4967 when the frame's old selected window has been deleted. */
4968 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
4969 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
4973 /* Set the screen height to the value it had before this function. */
4974 if (previous_frame_height
!= FRAME_HEIGHT (f
)
4975 || previous_frame_width
!= FRAME_WIDTH (f
))
4976 change_frame_size (f
, previous_frame_height
, previous_frame_width
,
4978 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4979 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
4980 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
4982 #ifdef HAVE_WINDOW_SYSTEM
4983 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
4984 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
4989 /* Now, free glyph matrices in windows that were not reused. */
4990 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
4992 if (NILP (leaf_windows
[i
]->buffer
))
4994 /* Assert it's not reused as a combination. */
4995 xassert (NILP (leaf_windows
[i
]->hchild
)
4996 && NILP (leaf_windows
[i
]->vchild
));
4997 free_window_matrices (leaf_windows
[i
]);
4999 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
5003 /* If more than one window shows the new and old current buffer,
5004 don't try to preserve point in that buffer. */
5005 if (old_point
> 0 && n
> 1)
5012 /* Fselect_window will have made f the selected frame, so we
5013 reselect the proper frame here. Fhandle_switch_frame will change the
5014 selected window too, but that doesn't make the call to
5015 Fselect_window above totally superfluous; it still sets f's
5017 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
5018 do_switch_frame (data
->selected_frame
, Qnil
, 0);
5020 if (! NILP (Vwindow_configuration_change_hook
)
5021 && ! NILP (Vrun_hooks
))
5022 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
5025 if (!NILP (new_current_buffer
))
5027 Fset_buffer (new_current_buffer
);
5029 /* If the buffer that is current now is the same
5030 that was current before setting the window configuration,
5031 don't alter its PT. */
5036 /* Restore the minimum heights recorded in the configuration. */
5037 window_min_height
= XINT (data
->min_height
);
5038 window_min_width
= XINT (data
->min_width
);
5040 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
5042 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
5045 /* Mark all windows now on frame as deleted
5046 by setting their buffers to nil. */
5049 delete_all_subwindows (w
)
5050 register struct window
*w
;
5052 if (!NILP (w
->next
))
5053 delete_all_subwindows (XWINDOW (w
->next
));
5054 if (!NILP (w
->vchild
))
5055 delete_all_subwindows (XWINDOW (w
->vchild
));
5056 if (!NILP (w
->hchild
))
5057 delete_all_subwindows (XWINDOW (w
->hchild
));
5059 w
->height
= w
->buffer
; /* See Fset_window_configuration for excuse. */
5061 if (!NILP (w
->buffer
))
5064 /* We set all three of these fields to nil, to make sure that we can
5065 distinguish this dead window from any live window. Live leaf
5066 windows will have buffer set, and combination windows will have
5067 vchild or hchild set. */
5072 Vwindow_list
= Qnil
;
5076 count_windows (window
)
5077 register struct window
*window
;
5079 register int count
= 1;
5080 if (!NILP (window
->next
))
5081 count
+= count_windows (XWINDOW (window
->next
));
5082 if (!NILP (window
->vchild
))
5083 count
+= count_windows (XWINDOW (window
->vchild
));
5084 if (!NILP (window
->hchild
))
5085 count
+= count_windows (XWINDOW (window
->hchild
));
5090 /* Fill vector FLAT with leaf windows under W, starting at index I.
5091 Value is last index + 1. */
5094 get_leaf_windows (w
, flat
, i
)
5096 struct window
**flat
;
5101 if (!NILP (w
->hchild
))
5102 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
5103 else if (!NILP (w
->vchild
))
5104 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
5108 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5115 /* Return a pointer to the glyph W's physical cursor is on. Value is
5116 null if W's current matrix is invalid, so that no meaningfull glyph
5120 get_phys_cursor_glyph (w
)
5123 struct glyph_row
*row
;
5124 struct glyph
*glyph
;
5126 if (w
->phys_cursor
.vpos
>= 0
5127 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
5128 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
5130 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
5131 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
5140 save_window_save (window
, vector
, i
)
5142 struct Lisp_Vector
*vector
;
5145 register struct saved_window
*p
;
5146 register struct window
*w
;
5147 register Lisp_Object tem
;
5149 for (;!NILP (window
); window
= w
->next
)
5151 p
= SAVED_WINDOW_N (vector
, i
);
5152 w
= XWINDOW (window
);
5154 XSETFASTINT (w
->temslot
, i
++);
5156 p
->buffer
= w
->buffer
;
5159 p
->width
= w
->width
;
5160 p
->height
= w
->height
;
5161 p
->hscroll
= w
->hscroll
;
5162 p
->min_hscroll
= w
->min_hscroll
;
5163 p
->display_table
= w
->display_table
;
5164 p
->orig_top
= w
->orig_top
;
5165 p
->orig_height
= w
->orig_height
;
5166 if (!NILP (w
->buffer
))
5168 /* Save w's value of point in the window configuration.
5169 If w is the selected window, then get the value of point
5170 from the buffer; pointm is garbage in the selected window. */
5171 if (EQ (window
, selected_window
))
5173 p
->pointm
= Fmake_marker ();
5174 set_marker_both (p
->pointm
, w
->buffer
,
5175 BUF_PT (XBUFFER (w
->buffer
)),
5176 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
5179 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
5181 p
->start
= Fcopy_marker (w
->start
, Qnil
);
5182 p
->start_at_line_beg
= w
->start_at_line_beg
;
5184 tem
= XBUFFER (w
->buffer
)->mark
;
5185 p
->mark
= Fcopy_marker (tem
, Qnil
);
5192 p
->start_at_line_beg
= Qnil
;
5195 if (NILP (w
->parent
))
5198 p
->parent
= XWINDOW (w
->parent
)->temslot
;
5203 p
->prev
= XWINDOW (w
->prev
)->temslot
;
5205 if (!NILP (w
->vchild
))
5206 i
= save_window_save (w
->vchild
, vector
, i
);
5207 if (!NILP (w
->hchild
))
5208 i
= save_window_save (w
->hchild
, vector
, i
);
5214 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
5215 Scurrent_window_configuration
, 0, 1, 0,
5216 "Return an object representing the current window configuration of FRAME.\n\
5217 If FRAME is nil or omitted, use the selected frame.\n\
5218 This describes the number of windows, their sizes and current buffers,\n\
5219 and for each displayed buffer, where display starts, and the positions of\n\
5220 point and mark. An exception is made for point in the current buffer:\n\
5221 its value is -not- saved.\n\
5222 This also records the currently selected frame, and FRAME's focus\n\
5223 redirection (see `redirect-frame-focus').")
5227 register Lisp_Object tem
;
5228 register int n_windows
;
5229 register struct save_window_data
*data
;
5230 register struct Lisp_Vector
*vec
;
5235 frame
= selected_frame
;
5236 CHECK_LIVE_FRAME (frame
, 0);
5239 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5240 vec
= allocate_vectorlike (VECSIZE (struct save_window_data
));
5241 for (i
= 0; i
< VECSIZE (struct save_window_data
); i
++)
5242 vec
->contents
[i
] = Qnil
;
5243 vec
->size
= VECSIZE (struct save_window_data
);
5244 data
= (struct save_window_data
*)vec
;
5246 XSETFASTINT (data
->frame_width
, FRAME_WIDTH (f
));
5247 XSETFASTINT (data
->frame_height
, FRAME_HEIGHT (f
));
5248 XSETFASTINT (data
->frame_menu_bar_lines
, FRAME_MENU_BAR_LINES (f
));
5249 XSETFASTINT (data
->frame_tool_bar_lines
, FRAME_TOOL_BAR_LINES (f
));
5250 data
->selected_frame
= selected_frame
;
5251 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
5252 XSETBUFFER (data
->current_buffer
, current_buffer
);
5253 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
5254 data
->root_window
= FRAME_ROOT_WINDOW (f
);
5255 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
5256 XSETINT (data
->min_height
, window_min_height
);
5257 XSETINT (data
->min_width
, window_min_width
);
5258 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
5259 data
->saved_windows
= tem
;
5260 for (i
= 0; i
< n_windows
; i
++)
5261 XVECTOR (tem
)->contents
[i
]
5262 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
5263 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
5264 XSETWINDOW_CONFIGURATION (tem
, data
);
5268 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
5270 "Execute body, preserving window sizes and contents.\n\
5271 Restore which buffer appears in which window, where display starts,\n\
5272 and the value of point and mark for each window.\n\
5273 Also restore the choice of selected window.\n\
5274 Also restore which buffer is current.\n\
5275 Does not restore the value of point in current buffer.")
5279 register Lisp_Object val
;
5280 register int count
= specpdl_ptr
- specpdl
;
5282 record_unwind_protect (Fset_window_configuration
,
5283 Fcurrent_window_configuration (Qnil
));
5284 val
= Fprogn (args
);
5285 return unbind_to (count
, val
);
5289 /***********************************************************************
5291 ***********************************************************************/
5293 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
5295 "Set width of marginal areas of window WINDOW.\n\
5296 If window is nil, set margins of the currently selected window.\n\
5297 First parameter LEFT-WIDTH specifies the number of character\n\
5298 cells to reserve for the left marginal area. Second parameter\n\
5299 RIGHT-WIDTH does the same for the right marginal area.\n\
5300 A nil width parameter means no margin.")
5301 (window
, left
, right
)
5302 Lisp_Object window
, left
, right
;
5304 struct window
*w
= decode_window (window
);
5307 CHECK_NUMBER_OR_FLOAT (left
, 1);
5309 CHECK_NUMBER_OR_FLOAT (right
, 2);
5311 /* Check widths < 0 and translate a zero width to nil.
5312 Margins that are too wide have to be checked elsewhere. */
5313 if ((INTEGERP (left
) && XINT (left
) < 0)
5314 || (FLOATP (left
) && XFLOAT_DATA (left
) <= 0))
5315 XSETFASTINT (left
, 0);
5316 if (INTEGERP (left
) && XFASTINT (left
) == 0)
5319 if ((INTEGERP (right
) && XINT (right
) < 0)
5320 || (FLOATP (right
) && XFLOAT_DATA (right
) <= 0))
5321 XSETFASTINT (right
, 0);
5322 if (INTEGERP (right
) && XFASTINT (right
) == 0)
5325 w
->left_margin_width
= left
;
5326 w
->right_margin_width
= right
;
5328 ++windows_or_buffers_changed
;
5329 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
5334 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
5336 "Get width of marginal areas of window WINDOW.\n\
5337 If WINDOW is omitted or nil, use the currently selected window.\n\
5338 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
5339 If a marginal area does not exist, its width will be returned\n\
5344 struct window
*w
= decode_window (window
);
5345 return Fcons (w
->left_margin_width
, w
->right_margin_width
);
5350 /***********************************************************************
5352 ***********************************************************************/
5354 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 1, 0,
5355 "Return the amount by which WINDOW is scrolled vertically.\n\
5356 Use the selected window if WINDOW is nil or omitted.\n\
5357 Value is a multiple of the canonical character height of WINDOW.")
5366 window
= selected_window
;
5368 CHECK_WINDOW (window
, 0);
5369 w
= XWINDOW (window
);
5370 f
= XFRAME (w
->frame
);
5372 if (FRAME_WINDOW_P (f
))
5373 result
= CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
);
5375 result
= make_number (0);
5380 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
5382 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5383 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
5384 non-negative multiple of the canonical character height of WINDOW.")
5386 Lisp_Object window
, vscroll
;
5392 window
= selected_window
;
5394 CHECK_WINDOW (window
, 0);
5395 CHECK_NUMBER_OR_FLOAT (vscroll
, 1);
5397 w
= XWINDOW (window
);
5398 f
= XFRAME (w
->frame
);
5400 if (FRAME_WINDOW_P (f
))
5402 int old_dy
= w
->vscroll
;
5404 w
->vscroll
= - CANON_Y_UNIT (f
) * XFLOATINT (vscroll
);
5405 w
->vscroll
= min (w
->vscroll
, 0);
5407 /* Adjust glyph matrix of the frame if the virtual display
5408 area becomes larger than before. */
5409 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
5412 /* Prevent redisplay shortcuts. */
5413 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
5416 return Fwindow_vscroll (window
);
5420 /* Call FN for all leaf windows on frame F. FN is called with the
5421 first argument being a pointer to the leaf window, and with
5422 additional argument USER_DATA. Stops when FN returns 0. */
5425 foreach_window (f
, fn
, user_data
)
5427 int (* fn
) P_ ((struct window
*, void *));
5430 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
5434 /* Helper function for foreach_window. Call FN for all leaf windows
5435 reachable from W. FN is called with the first argument being a
5436 pointer to the leaf window, and with additional argument USER_DATA.
5437 Stop when FN returns 0. Value is 0 if stopped by FN. */
5440 foreach_window_1 (w
, fn
, user_data
)
5442 int (* fn
) P_ ((struct window
*, void *));
5447 for (cont
= 1; w
&& cont
;)
5449 if (!NILP (w
->hchild
))
5450 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
5451 else if (!NILP (w
->vchild
))
5452 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
5454 cont
= fn (w
, user_data
);
5456 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5463 /* Freeze or unfreeze the window start of W if unless it is a
5464 mini-window or the selected window. FREEZE_P non-null means freeze
5465 the window start. */
5468 freeze_window_start (w
, freeze_p
)
5472 if (w
== XWINDOW (selected_window
)
5473 || MINI_WINDOW_P (w
)
5474 || (MINI_WINDOW_P (XWINDOW (selected_window
))
5475 && ! NILP (Vminibuf_scroll_window
)
5476 && w
== XWINDOW (Vminibuf_scroll_window
)))
5479 w
->frozen_window_start_p
= freeze_p
!= NULL
;
5484 /* Freeze or unfreeze the window starts of all leaf windows on frame
5485 F, except the selected window and a mini-window. FREEZE_P non-zero
5486 means freeze the window start. */
5489 freeze_window_starts (f
, freeze_p
)
5493 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
5497 /***********************************************************************
5499 ***********************************************************************/
5501 /* Return 1 if window configurations C1 and C2
5502 describe the same state of affairs. This is used by Fequal. */
5505 compare_window_configurations (c1
, c2
, ignore_positions
)
5507 int ignore_positions
;
5509 register struct save_window_data
*d1
, *d2
;
5510 struct Lisp_Vector
*sw1
, *sw2
;
5513 if (!WINDOW_CONFIGURATIONP (c1
))
5514 wrong_type_argument (Qwindow_configuration_p
, c1
);
5515 if (!WINDOW_CONFIGURATIONP (c2
))
5516 wrong_type_argument (Qwindow_configuration_p
, c2
);
5518 d1
= (struct save_window_data
*) XVECTOR (c1
);
5519 d2
= (struct save_window_data
*) XVECTOR (c2
);
5520 sw1
= XVECTOR (d1
->saved_windows
);
5521 sw2
= XVECTOR (d2
->saved_windows
);
5523 if (! EQ (d1
->frame_width
, d2
->frame_width
))
5525 if (! EQ (d1
->frame_height
, d2
->frame_height
))
5527 if (! EQ (d1
->frame_menu_bar_lines
, d2
->frame_menu_bar_lines
))
5529 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
5531 /* Don't compare the current_window field directly.
5532 Instead see w1_is_current and w2_is_current, below. */
5533 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
5535 if (! ignore_positions
)
5536 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
5538 /* Don't compare the root_window field.
5539 We don't require the two configurations
5540 to use the same window object,
5541 and the two root windows must be equivalent
5542 if everything else compares equal. */
5543 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
5545 if (! EQ (d1
->min_width
, d2
->min_width
))
5547 if (! EQ (d1
->min_height
, d2
->min_height
))
5550 /* Verify that the two confis have the same number of windows. */
5551 if (sw1
->size
!= sw2
->size
)
5554 for (i
= 0; i
< sw1
->size
; i
++)
5556 struct saved_window
*p1
, *p2
;
5557 int w1_is_current
, w2_is_current
;
5559 p1
= SAVED_WINDOW_N (sw1
, i
);
5560 p2
= SAVED_WINDOW_N (sw2
, i
);
5562 /* Verify that the current windows in the two
5563 configurations correspond to each other. */
5564 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
5565 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
5567 if (w1_is_current
!= w2_is_current
)
5570 /* Verify that the corresponding windows do match. */
5571 if (! EQ (p1
->buffer
, p2
->buffer
))
5573 if (! EQ (p1
->left
, p2
->left
))
5575 if (! EQ (p1
->top
, p2
->top
))
5577 if (! EQ (p1
->width
, p2
->width
))
5579 if (! EQ (p1
->height
, p2
->height
))
5581 if (! EQ (p1
->display_table
, p2
->display_table
))
5583 if (! EQ (p1
->parent
, p2
->parent
))
5585 if (! EQ (p1
->prev
, p2
->prev
))
5587 if (! ignore_positions
)
5589 if (! EQ (p1
->hscroll
, p2
->hscroll
))
5591 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
5593 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
5595 if (NILP (Fequal (p1
->start
, p2
->start
)))
5597 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
5599 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
5607 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
5608 Scompare_window_configurations
, 2, 2, 0,
5609 "Compare two window configurations as regards the structure of windows.\n\
5610 This function ignores details such as the values of point and mark\n\
5611 and scrolling positions.")
5615 if (compare_window_configurations (x
, y
, 1))
5623 struct frame
*f
= make_terminal_frame ();
5624 XSETFRAME (selected_frame
, f
);
5625 Vterminal_frame
= selected_frame
;
5626 minibuf_window
= f
->minibuffer_window
;
5627 selected_window
= f
->selected_window
;
5628 last_nonminibuf_frame
= f
;
5630 window_initialized
= 1;
5636 Vwindow_list
= Qnil
;
5642 Qleft_fringe
= intern ("left-fringe");
5643 staticpro (&Qleft_fringe
);
5644 Qright_fringe
= intern ("right-fringe");
5645 staticpro (&Qright_fringe
);
5647 Qwindow_size_fixed
= intern ("window-size-fixed");
5648 staticpro (&Qwindow_size_fixed
);
5650 staticpro (&Qwindow_configuration_change_hook
);
5651 Qwindow_configuration_change_hook
5652 = intern ("window-configuration-change-hook");
5654 Qwindowp
= intern ("windowp");
5655 staticpro (&Qwindowp
);
5657 Qwindow_configuration_p
= intern ("window-configuration-p");
5658 staticpro (&Qwindow_configuration_p
);
5660 Qwindow_live_p
= intern ("window-live-p");
5661 staticpro (&Qwindow_live_p
);
5663 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
5664 staticpro (&Qtemp_buffer_show_hook
);
5666 staticpro (&Vwindow_list
);
5668 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
5669 "Non-nil means call as function to display a help buffer.\n\
5670 The function is called with one argument, the buffer to be displayed.\n\
5671 Used by `with-output-to-temp-buffer'.\n\
5672 If this function is used, then it must do the entire job of showing\n\
5673 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5674 Vtemp_buffer_show_function
= Qnil
;
5676 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
5677 "If non-nil, function to call to handle `display-buffer'.\n\
5678 It will receive two args, the buffer and a flag which if non-nil means\n\
5679 that the currently selected window is not acceptable.\n\
5680 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5681 work using this function.");
5682 Vdisplay_buffer_function
= Qnil
;
5684 DEFVAR_LISP ("even-window-heights", &Veven_window_heights
,
5685 "*If non-nil, `display-buffer' should even the window heights.\n\
5686 If nil, `display-buffer' will leave the window configuration alone.");
5687 Veven_window_heights
= Qt
;
5689 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
5690 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5691 Vminibuf_scroll_window
= Qnil
;
5693 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
5694 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5695 Vother_window_scroll_buffer
= Qnil
;
5697 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
5698 "*Non-nil means `display-buffer' should make a separate frame.");
5701 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames
,
5702 "*Non-nil means `display-buffer' should reuse frames.\n\
5703 If the buffer in question is already displayed in a frame, raise that frame.");
5704 display_buffer_reuse_frames
= 0;
5706 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
5707 "Function to call to handle automatic new frame creation.\n\
5708 It is called with no arguments and should return a newly created frame.\n\
5710 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5711 where `pop-up-frame-alist' would hold the default frame parameters.");
5712 Vpop_up_frame_function
= Qnil
;
5714 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
5715 "*List of buffer names that should have their own special frames.\n\
5716 Displaying a buffer whose name is in this list makes a special frame for it\n\
5717 using `special-display-function'. See also `special-display-regexps'.\n\
5719 An element of the list can be a list instead of just a string.\n\
5720 There are two ways to use a list as an element:\n\
5721 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5722 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5723 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5724 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5725 All this is done by the function found in `special-display-function'.\n\
5727 If this variable appears \"not to work\", because you add a name to it\n\
5728 but that buffer still appears in the selected window, look at the\n\
5729 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5730 Those variables take precedence over this one.");
5731 Vspecial_display_buffer_names
= Qnil
;
5733 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
5734 "*List of regexps saying which buffers should have their own special frames.\n\
5735 If a buffer name matches one of these regexps, it gets its own frame.\n\
5736 Displaying a buffer whose name is in this list makes a special frame for it\n\
5737 using `special-display-function'.\n\
5739 An element of the list can be a list instead of just a string.\n\
5740 There are two ways to use a list as an element:\n\
5741 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5742 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5743 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5744 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5745 All this is done by the function found in `special-display-function'.\n\
5747 If this variable appears \"not to work\", because you add a regexp to it\n\
5748 but the matching buffers still appear in the selected window, look at the\n\
5749 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5750 Those variables take precedence over this one.");
5751 Vspecial_display_regexps
= Qnil
;
5753 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
5754 "Function to call to make a new frame for a special buffer.\n\
5755 It is called with two arguments, the buffer and optional buffer specific\n\
5756 data, and should return a window displaying that buffer.\n\
5757 The default value makes a separate frame for the buffer,\n\
5758 using `special-display-frame-alist' to specify the frame parameters.\n\
5760 A buffer is special if its is listed in `special-display-buffer-names'\n\
5761 or matches a regexp in `special-display-regexps'.");
5762 Vspecial_display_function
= Qnil
;
5764 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
5765 "*List of buffer names that should appear in the selected window.\n\
5766 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5767 switches to it in the selected window, rather than making it appear\n\
5768 in some other window.\n\
5770 An element of the list can be a cons cell instead of just a string.\n\
5771 Then the car must be a string, which specifies the buffer name.\n\
5772 This is for compatibility with `special-display-buffer-names';\n\
5773 the cdr of the cons cell is ignored.\n\
5775 See also `same-window-regexps'.");
5776 Vsame_window_buffer_names
= Qnil
;
5778 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
5779 "*List of regexps saying which buffers should appear in the selected window.\n\
5780 If a buffer name matches one of these regexps, then displaying it\n\
5781 using `display-buffer' or `pop-to-buffer' switches to it\n\
5782 in the selected window, rather than making it appear in some other window.\n\
5784 An element of the list can be a cons cell instead of just a string.\n\
5785 Then the car must be a string, which specifies the buffer name.\n\
5786 This is for compatibility with `special-display-buffer-names';\n\
5787 the cdr of the cons cell is ignored.\n\
5789 See also `same-window-buffer-names'.");
5790 Vsame_window_regexps
= Qnil
;
5792 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
5793 "*Non-nil means display-buffer should make new windows.");
5796 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
5797 "*Number of lines of continuity when scrolling by screenfuls.");
5798 next_screen_context_lines
= 2;
5800 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
5801 "*display-buffer would prefer to split the largest window if this large.\n\
5802 If there is only one window, it is split regardless of this value.");
5803 split_height_threshold
= 500;
5805 DEFVAR_INT ("window-min-height", &window_min_height
,
5806 "*Delete any window less than this tall (including its mode line).");
5807 window_min_height
= 4;
5809 DEFVAR_INT ("window-min-width", &window_min_width
,
5810 "*Delete any window less than this wide.");
5811 window_min_width
= 10;
5813 DEFVAR_LISP ("scroll-preserve-screen-position",
5814 &Vscroll_preserve_screen_position
,
5815 "*Non-nil means scroll commands move point to keep its screen line unchanged.");
5816 Vscroll_preserve_screen_position
= Qnil
;
5818 DEFVAR_LISP ("window-configuration-change-hook",
5819 &Vwindow_configuration_change_hook
,
5820 "Functions to call when window configuration changes.\n\
5821 The selected frame is the one whose configuration has changed.");
5822 Vwindow_configuration_change_hook
= Qnil
;
5824 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed
,
5825 "Non-nil in a buffer means windows displaying the buffer are fixed-size.\n\
5826 Emacs won't change the size of any window displaying that buffer,\n\
5827 unless you explicitly change the size, or Emacs has no other choice.\n\
5828 This variable automatically becomes buffer-local when set.");
5829 Fmake_variable_buffer_local (Qwindow_size_fixed
);
5830 window_size_fixed
= 0;
5832 defsubr (&Sselected_window
);
5833 defsubr (&Sminibuffer_window
);
5834 defsubr (&Swindow_minibuffer_p
);
5835 defsubr (&Swindowp
);
5836 defsubr (&Swindow_live_p
);
5837 defsubr (&Spos_visible_in_window_p
);
5838 defsubr (&Swindow_buffer
);
5839 defsubr (&Swindow_height
);
5840 defsubr (&Swindow_width
);
5841 defsubr (&Swindow_hscroll
);
5842 defsubr (&Sset_window_hscroll
);
5843 defsubr (&Swindow_redisplay_end_trigger
);
5844 defsubr (&Sset_window_redisplay_end_trigger
);
5845 defsubr (&Swindow_edges
);
5846 defsubr (&Scoordinates_in_window_p
);
5847 defsubr (&Swindow_at
);
5848 defsubr (&Swindow_point
);
5849 defsubr (&Swindow_start
);
5850 defsubr (&Swindow_end
);
5851 defsubr (&Sset_window_point
);
5852 defsubr (&Sset_window_start
);
5853 defsubr (&Swindow_dedicated_p
);
5854 defsubr (&Sset_window_dedicated_p
);
5855 defsubr (&Swindow_display_table
);
5856 defsubr (&Sset_window_display_table
);
5857 defsubr (&Snext_window
);
5858 defsubr (&Sprevious_window
);
5859 defsubr (&Sother_window
);
5860 defsubr (&Sget_lru_window
);
5861 defsubr (&Sget_largest_window
);
5862 defsubr (&Sget_buffer_window
);
5863 defsubr (&Sdelete_other_windows
);
5864 defsubr (&Sdelete_windows_on
);
5865 defsubr (&Sreplace_buffer_in_windows
);
5866 defsubr (&Sdelete_window
);
5867 defsubr (&Sset_window_buffer
);
5868 defsubr (&Sselect_window
);
5869 defsubr (&Sspecial_display_p
);
5870 defsubr (&Ssame_window_p
);
5871 defsubr (&Sdisplay_buffer
);
5872 defsubr (&Ssplit_window
);
5873 defsubr (&Senlarge_window
);
5874 defsubr (&Sshrink_window
);
5875 defsubr (&Sscroll_up
);
5876 defsubr (&Sscroll_down
);
5877 defsubr (&Sscroll_left
);
5878 defsubr (&Sscroll_right
);
5879 defsubr (&Sother_window_for_scrolling
);
5880 defsubr (&Sscroll_other_window
);
5881 defsubr (&Srecenter
);
5882 defsubr (&Swindow_text_height
);
5883 defsubr (&Smove_to_window_line
);
5884 defsubr (&Swindow_configuration_p
);
5885 defsubr (&Swindow_configuration_frame
);
5886 defsubr (&Sset_window_configuration
);
5887 defsubr (&Scurrent_window_configuration
);
5888 defsubr (&Ssave_window_excursion
);
5889 defsubr (&Sset_window_margins
);
5890 defsubr (&Swindow_margins
);
5891 defsubr (&Swindow_vscroll
);
5892 defsubr (&Sset_window_vscroll
);
5893 defsubr (&Scompare_window_configurations
);
5894 defsubr (&Swindow_list
);
5900 initial_define_key (control_x_map
, '1', "delete-other-windows");
5901 initial_define_key (control_x_map
, '2', "split-window");
5902 initial_define_key (control_x_map
, '0', "delete-window");
5903 initial_define_key (control_x_map
, 'o', "other-window");
5904 initial_define_key (control_x_map
, '^', "enlarge-window");
5905 initial_define_key (control_x_map
, '<', "scroll-left");
5906 initial_define_key (control_x_map
, '>', "scroll-right");
5908 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
5909 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
5910 initial_define_key (meta_map
, 'v', "scroll-down");
5912 initial_define_key (global_map
, Ctl('L'), "recenter");
5913 initial_define_key (meta_map
, 'r', "move-to-window-line");