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_height
= 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
);
4500 set_buffer_internal (old_buffer
);
4502 bottom_y
= it
.current_y
+ it
.max_ascent
+ it
.max_descent
;
4504 if (bottom_y
> it
.current_y
&& bottom_y
<= it
.last_visible_y
)
4505 /* Hit a line without a terminating newline. */
4508 /* Add in empty lines at the bottom of the window. */
4509 if (bottom_y
< height
)
4511 struct frame
*f
= XFRAME (w
->frame
);
4512 int rest
= height
- bottom_y
;
4513 int lines
= rest
/ CANON_Y_UNIT (f
);
4521 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
4522 "Center point in window and redisplay frame.\n\
4523 With prefix argument ARG, recenter putting point on screen line ARG\n\
4524 relative to the current window. If ARG is negative, it counts up from the\n\
4525 bottom of the window. (ARG should be less than the height of the window.)\n\
4527 If ARG is omitted or nil, erase the entire frame and then\n\
4528 redraw with point in the center of the current window.\n\
4529 Just C-u as prefix means put point in the center of the window\n\
4530 and redisplay normally--don't erase and redraw the frame.")
4532 register Lisp_Object arg
;
4534 struct window
*w
= XWINDOW (selected_window
);
4535 struct buffer
*buf
= XBUFFER (w
->buffer
);
4536 struct buffer
*obuf
= current_buffer
;
4538 int charpos
, bytepos
;
4544 /* Invalidate pixel data calculated for all compositions. */
4545 for (i
= 0; i
< n_compositions
; i
++)
4546 composition_table
[i
]->font
= NULL
;
4548 Fredraw_frame (w
->frame
);
4549 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
4552 else if (CONSP (arg
)) /* Just C-u. */
4556 arg
= Fprefix_numeric_value (arg
);
4557 CHECK_NUMBER (arg
, 0);
4560 set_buffer_internal (buf
);
4562 /* Handle centering on a gfaphical frame specially. Such frames can
4563 have variable-height lines and centering point on the basis of
4564 line counts would lead to strange effects. */
4565 if (center_p
&& FRAME_WINDOW_P (XFRAME (w
->frame
)))
4570 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
4571 start_display (&it
, w
, pt
);
4572 move_it_vertically (&it
, - it
.last_visible_y
/ 2);
4573 charpos
= IT_CHARPOS (it
);
4574 bytepos
= IT_BYTEPOS (it
);
4578 struct position pos
;
4582 int ht
= displayed_window_lines (w
);
4583 arg
= make_number (ht
/ 2);
4585 else if (XINT (arg
) < 0)
4587 int ht
= displayed_window_lines (w
);
4588 XSETINT (arg
, XINT (arg
) + ht
);
4591 pos
= *vmotion (PT
, - XINT (arg
), w
);
4592 charpos
= pos
.bufpos
;
4593 bytepos
= pos
.bytepos
;
4596 /* Set the new window start. */
4597 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
4598 w
->window_end_valid
= Qnil
;
4599 w
->force_start
= Qt
;
4600 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
4601 w
->start_at_line_beg
= Qt
;
4603 w
->start_at_line_beg
= Qnil
;
4605 set_buffer_internal (obuf
);
4610 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
4612 "Return the height in lines of the text display area of WINDOW.\n\
4613 This doesn't include the mode-line (or header-line if any) or any\n\
4614 partial-height lines in the text display area.")
4618 struct window
*w
= decode_window (window
);
4619 int pixel_height
= window_box_height (w
);
4620 int line_height
= pixel_height
/ CANON_Y_UNIT (XFRAME (w
->frame
));
4621 return make_number (line_height
);
4626 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
4628 "Position point relative to window.\n\
4629 With no argument, position point at center of window.\n\
4630 An argument specifies vertical position within the window;\n\
4631 zero means top of window, negative means relative to bottom of window.")
4635 struct window
*w
= XWINDOW (selected_window
);
4639 window
= selected_window
;
4640 start
= marker_position (w
->start
);
4641 if (start
< BEGV
|| start
> ZV
)
4643 int height
= window_internal_height (w
);
4644 Fvertical_motion (make_number (- (height
/ 2)), window
);
4645 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
4646 w
->start_at_line_beg
= Fbolp ();
4647 w
->force_start
= Qt
;
4650 Fgoto_char (w
->start
);
4652 lines
= displayed_window_lines (w
);
4654 XSETFASTINT (arg
, lines
/ 2);
4657 arg
= Fprefix_numeric_value (arg
);
4659 XSETINT (arg
, XINT (arg
) + lines
);
4662 #if 0 /* I don't understand why this is done. Among other things,
4663 it means that C-u 0 M-r moves to line 1, and C-u -1 M-r
4664 moves to the line below the window end. 2000-02-05, gerd */
4666 /* Skip past a partially visible first line. */
4667 XSETINT (arg
, XINT (arg
) + 1);
4670 return Fvertical_motion (arg
, window
);
4675 /***********************************************************************
4676 Window Configuration
4677 ***********************************************************************/
4679 struct save_window_data
4681 EMACS_INT size_from_Lisp_Vector_struct
;
4682 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4683 Lisp_Object frame_width
, frame_height
, frame_menu_bar_lines
;
4684 Lisp_Object frame_tool_bar_lines
;
4685 Lisp_Object selected_frame
;
4686 Lisp_Object current_window
;
4687 Lisp_Object current_buffer
;
4688 Lisp_Object minibuf_scroll_window
;
4689 Lisp_Object root_window
;
4690 Lisp_Object focus_frame
;
4691 /* Record the values of window-min-width and window-min-height
4692 so that window sizes remain consistent with them. */
4693 Lisp_Object min_width
, min_height
;
4694 /* A vector, each of whose elements is a struct saved_window
4696 Lisp_Object saved_windows
;
4699 /* This is saved as a Lisp_Vector */
4702 /* these first two must agree with struct Lisp_Vector in lisp.h */
4703 EMACS_INT size_from_Lisp_Vector_struct
;
4704 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4707 Lisp_Object buffer
, start
, pointm
, mark
;
4708 Lisp_Object left
, top
, width
, height
, hscroll
, min_hscroll
;
4709 Lisp_Object parent
, prev
;
4710 Lisp_Object start_at_line_beg
;
4711 Lisp_Object display_table
;
4712 Lisp_Object orig_top
, orig_height
;
4715 #define SAVED_WINDOW_VECTOR_SIZE 17 /* Arg to Fmake_vector */
4717 #define SAVED_WINDOW_N(swv,n) \
4718 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4720 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
4721 "Return t if OBJECT is a window-configuration object.")
4725 if (WINDOW_CONFIGURATIONP (object
))
4730 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
4731 "Return the frame that CONFIG, a window-configuration object, is about.")
4735 register struct save_window_data
*data
;
4736 struct Lisp_Vector
*saved_windows
;
4738 if (! WINDOW_CONFIGURATIONP (config
))
4739 wrong_type_argument (Qwindow_configuration_p
, config
);
4741 data
= (struct save_window_data
*) XVECTOR (config
);
4742 saved_windows
= XVECTOR (data
->saved_windows
);
4743 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4746 DEFUN ("set-window-configuration", Fset_window_configuration
,
4747 Sset_window_configuration
, 1, 1, 0,
4748 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4749 CONFIGURATION must be a value previously returned\n\
4750 by `current-window-configuration' (which see).\n\
4751 If CONFIGURATION was made from a frame that is now deleted,\n\
4752 only frame-independent values can be restored. In this case,\n\
4753 the return value is nil. Otherwise the value is t.")
4755 Lisp_Object configuration
;
4757 register struct save_window_data
*data
;
4758 struct Lisp_Vector
*saved_windows
;
4759 Lisp_Object new_current_buffer
;
4764 while (!WINDOW_CONFIGURATIONP (configuration
))
4765 wrong_type_argument (Qwindow_configuration_p
, configuration
);
4767 data
= (struct save_window_data
*) XVECTOR (configuration
);
4768 saved_windows
= XVECTOR (data
->saved_windows
);
4770 new_current_buffer
= data
->current_buffer
;
4771 if (NILP (XBUFFER (new_current_buffer
)->name
))
4772 new_current_buffer
= Qnil
;
4775 if (XBUFFER (new_current_buffer
) == current_buffer
)
4779 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4782 /* If f is a dead frame, don't bother rebuilding its window tree.
4783 However, there is other stuff we should still try to do below. */
4784 if (FRAME_LIVE_P (f
))
4786 register struct window
*w
;
4787 register struct saved_window
*p
;
4788 struct window
*root_window
;
4789 struct window
**leaf_windows
;
4793 /* If the frame has been resized since this window configuration was
4794 made, we change the frame to the size specified in the
4795 configuration, restore the configuration, and then resize it
4796 back. We keep track of the prevailing height in these variables. */
4797 int previous_frame_height
= FRAME_HEIGHT (f
);
4798 int previous_frame_width
= FRAME_WIDTH (f
);
4799 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
4800 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
4802 /* The mouse highlighting code could get screwed up
4803 if it runs during this. */
4806 if (XFASTINT (data
->frame_height
) != previous_frame_height
4807 || XFASTINT (data
->frame_width
) != previous_frame_width
)
4808 change_frame_size (f
, XFASTINT (data
->frame_height
),
4809 XFASTINT (data
->frame_width
), 0, 0, 0);
4810 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4811 if (XFASTINT (data
->frame_menu_bar_lines
)
4812 != previous_frame_menu_bar_lines
)
4813 x_set_menu_bar_lines (f
, data
->frame_menu_bar_lines
, make_number (0));
4814 #ifdef HAVE_WINDOW_SYSTEM
4815 if (XFASTINT (data
->frame_tool_bar_lines
)
4816 != previous_frame_tool_bar_lines
)
4817 x_set_tool_bar_lines (f
, data
->frame_tool_bar_lines
, make_number (0));
4821 /* "Swap out" point from the selected window
4822 into its buffer. We do this now, before
4823 restoring the window contents, and prevent it from
4824 being done later on when we select a new window. */
4825 if (! NILP (XWINDOW (selected_window
)->buffer
))
4827 w
= XWINDOW (selected_window
);
4828 set_marker_both (w
->pointm
,
4830 BUF_PT (XBUFFER (w
->buffer
)),
4831 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
4834 windows_or_buffers_changed
++;
4835 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4837 /* Problem: Freeing all matrices and later allocating them again
4838 is a serious redisplay flickering problem. What we would
4839 really like to do is to free only those matrices not reused
4841 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4843 = (struct window
**) alloca (count_windows (root_window
)
4844 * sizeof (struct window
*));
4845 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
4847 /* Temporarily avoid any problems with windows that are smaller
4848 than they are supposed to be. */
4849 window_min_height
= 1;
4850 window_min_width
= 1;
4853 Mark all windows now on frame as "deleted".
4854 Restoring the new configuration "undeletes" any that are in it.
4856 Save their current buffers in their height fields, since we may
4857 need it later, if a buffer saved in the configuration is now
4859 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4861 for (k
= 0; k
< saved_windows
->size
; k
++)
4863 p
= SAVED_WINDOW_N (saved_windows
, k
);
4864 w
= XWINDOW (p
->window
);
4867 if (!NILP (p
->parent
))
4868 w
->parent
= SAVED_WINDOW_N (saved_windows
,
4869 XFASTINT (p
->parent
))->window
;
4873 if (!NILP (p
->prev
))
4875 w
->prev
= SAVED_WINDOW_N (saved_windows
,
4876 XFASTINT (p
->prev
))->window
;
4877 XWINDOW (w
->prev
)->next
= p
->window
;
4882 if (!NILP (w
->parent
))
4884 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
4886 XWINDOW (w
->parent
)->vchild
= p
->window
;
4887 XWINDOW (w
->parent
)->hchild
= Qnil
;
4891 XWINDOW (w
->parent
)->hchild
= p
->window
;
4892 XWINDOW (w
->parent
)->vchild
= Qnil
;
4897 /* If we squirreled away the buffer in the window's height,
4899 if (BUFFERP (w
->height
))
4900 w
->buffer
= w
->height
;
4903 w
->width
= p
->width
;
4904 w
->height
= p
->height
;
4905 w
->hscroll
= p
->hscroll
;
4906 w
->min_hscroll
= p
->min_hscroll
;
4907 w
->display_table
= p
->display_table
;
4908 w
->orig_top
= p
->orig_top
;
4909 w
->orig_height
= p
->orig_height
;
4910 XSETFASTINT (w
->last_modified
, 0);
4911 XSETFASTINT (w
->last_overlay_modified
, 0);
4913 /* Reinstall the saved buffer and pointers into it. */
4914 if (NILP (p
->buffer
))
4915 w
->buffer
= p
->buffer
;
4918 if (!NILP (XBUFFER (p
->buffer
)->name
))
4919 /* If saved buffer is alive, install it. */
4921 w
->buffer
= p
->buffer
;
4922 w
->start_at_line_beg
= p
->start_at_line_beg
;
4923 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
4924 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
4925 Fset_marker (XBUFFER (w
->buffer
)->mark
,
4926 p
->mark
, w
->buffer
);
4928 /* As documented in Fcurrent_window_configuration, don't
4929 save the location of point in the buffer which was current
4930 when the window configuration was recorded. */
4931 if (!EQ (p
->buffer
, new_current_buffer
)
4932 && XBUFFER (p
->buffer
) == current_buffer
)
4933 Fgoto_char (w
->pointm
);
4935 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
4936 /* Else unless window has a live buffer, get one. */
4938 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
4939 /* This will set the markers to beginning of visible
4941 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
4942 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
4943 w
->start_at_line_beg
= Qt
;
4946 /* Keeping window's old buffer; make sure the markers
4949 /* Set window markers at start of visible range. */
4950 if (XMARKER (w
->start
)->buffer
== 0)
4951 set_marker_restricted (w
->start
, make_number (0),
4953 if (XMARKER (w
->pointm
)->buffer
== 0)
4954 set_marker_restricted_both (w
->pointm
, w
->buffer
,
4955 BUF_PT (XBUFFER (w
->buffer
)),
4956 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
4957 w
->start_at_line_beg
= Qt
;
4962 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
4963 /* Prevent "swapping out point" in the old selected window
4964 using the buffer that has been restored into it.
4965 That swapping out has already been done,
4966 near the beginning of this function. */
4967 selected_window
= Qnil
;
4968 Fselect_window (data
->current_window
);
4969 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
4972 if (NILP (data
->focus_frame
)
4973 || (FRAMEP (data
->focus_frame
)
4974 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
4975 Fredirect_frame_focus (frame
, data
->focus_frame
);
4977 #if 0 /* I don't understand why this is needed, and it causes problems
4978 when the frame's old selected window has been deleted. */
4979 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
4980 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
4984 /* Set the screen height to the value it had before this function. */
4985 if (previous_frame_height
!= FRAME_HEIGHT (f
)
4986 || previous_frame_width
!= FRAME_WIDTH (f
))
4987 change_frame_size (f
, previous_frame_height
, previous_frame_width
,
4989 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4990 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
4991 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
4993 #ifdef HAVE_WINDOW_SYSTEM
4994 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
4995 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
5000 /* Now, free glyph matrices in windows that were not reused. */
5001 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
5003 if (NILP (leaf_windows
[i
]->buffer
))
5005 /* Assert it's not reused as a combination. */
5006 xassert (NILP (leaf_windows
[i
]->hchild
)
5007 && NILP (leaf_windows
[i
]->vchild
));
5008 free_window_matrices (leaf_windows
[i
]);
5010 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
5014 /* If more than one window shows the new and old current buffer,
5015 don't try to preserve point in that buffer. */
5016 if (old_point
> 0 && n
> 1)
5023 /* Fselect_window will have made f the selected frame, so we
5024 reselect the proper frame here. Fhandle_switch_frame will change the
5025 selected window too, but that doesn't make the call to
5026 Fselect_window above totally superfluous; it still sets f's
5028 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
5029 do_switch_frame (data
->selected_frame
, Qnil
, 0);
5031 if (! NILP (Vwindow_configuration_change_hook
)
5032 && ! NILP (Vrun_hooks
))
5033 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
5036 if (!NILP (new_current_buffer
))
5038 Fset_buffer (new_current_buffer
);
5040 /* If the buffer that is current now is the same
5041 that was current before setting the window configuration,
5042 don't alter its PT. */
5047 /* Restore the minimum heights recorded in the configuration. */
5048 window_min_height
= XINT (data
->min_height
);
5049 window_min_width
= XINT (data
->min_width
);
5051 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
5053 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
5056 /* Mark all windows now on frame as deleted
5057 by setting their buffers to nil. */
5060 delete_all_subwindows (w
)
5061 register struct window
*w
;
5063 if (!NILP (w
->next
))
5064 delete_all_subwindows (XWINDOW (w
->next
));
5065 if (!NILP (w
->vchild
))
5066 delete_all_subwindows (XWINDOW (w
->vchild
));
5067 if (!NILP (w
->hchild
))
5068 delete_all_subwindows (XWINDOW (w
->hchild
));
5070 w
->height
= w
->buffer
; /* See Fset_window_configuration for excuse. */
5072 if (!NILP (w
->buffer
))
5075 /* We set all three of these fields to nil, to make sure that we can
5076 distinguish this dead window from any live window. Live leaf
5077 windows will have buffer set, and combination windows will have
5078 vchild or hchild set. */
5083 Vwindow_list
= Qnil
;
5087 count_windows (window
)
5088 register struct window
*window
;
5090 register int count
= 1;
5091 if (!NILP (window
->next
))
5092 count
+= count_windows (XWINDOW (window
->next
));
5093 if (!NILP (window
->vchild
))
5094 count
+= count_windows (XWINDOW (window
->vchild
));
5095 if (!NILP (window
->hchild
))
5096 count
+= count_windows (XWINDOW (window
->hchild
));
5101 /* Fill vector FLAT with leaf windows under W, starting at index I.
5102 Value is last index + 1. */
5105 get_leaf_windows (w
, flat
, i
)
5107 struct window
**flat
;
5112 if (!NILP (w
->hchild
))
5113 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
5114 else if (!NILP (w
->vchild
))
5115 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
5119 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5126 /* Return a pointer to the glyph W's physical cursor is on. Value is
5127 null if W's current matrix is invalid, so that no meaningfull glyph
5131 get_phys_cursor_glyph (w
)
5134 struct glyph_row
*row
;
5135 struct glyph
*glyph
;
5137 if (w
->phys_cursor
.vpos
>= 0
5138 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
5139 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
5141 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
5142 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
5151 save_window_save (window
, vector
, i
)
5153 struct Lisp_Vector
*vector
;
5156 register struct saved_window
*p
;
5157 register struct window
*w
;
5158 register Lisp_Object tem
;
5160 for (;!NILP (window
); window
= w
->next
)
5162 p
= SAVED_WINDOW_N (vector
, i
);
5163 w
= XWINDOW (window
);
5165 XSETFASTINT (w
->temslot
, i
++);
5167 p
->buffer
= w
->buffer
;
5170 p
->width
= w
->width
;
5171 p
->height
= w
->height
;
5172 p
->hscroll
= w
->hscroll
;
5173 p
->min_hscroll
= w
->min_hscroll
;
5174 p
->display_table
= w
->display_table
;
5175 p
->orig_top
= w
->orig_top
;
5176 p
->orig_height
= w
->orig_height
;
5177 if (!NILP (w
->buffer
))
5179 /* Save w's value of point in the window configuration.
5180 If w is the selected window, then get the value of point
5181 from the buffer; pointm is garbage in the selected window. */
5182 if (EQ (window
, selected_window
))
5184 p
->pointm
= Fmake_marker ();
5185 set_marker_both (p
->pointm
, w
->buffer
,
5186 BUF_PT (XBUFFER (w
->buffer
)),
5187 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
5190 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
5192 p
->start
= Fcopy_marker (w
->start
, Qnil
);
5193 p
->start_at_line_beg
= w
->start_at_line_beg
;
5195 tem
= XBUFFER (w
->buffer
)->mark
;
5196 p
->mark
= Fcopy_marker (tem
, Qnil
);
5203 p
->start_at_line_beg
= Qnil
;
5206 if (NILP (w
->parent
))
5209 p
->parent
= XWINDOW (w
->parent
)->temslot
;
5214 p
->prev
= XWINDOW (w
->prev
)->temslot
;
5216 if (!NILP (w
->vchild
))
5217 i
= save_window_save (w
->vchild
, vector
, i
);
5218 if (!NILP (w
->hchild
))
5219 i
= save_window_save (w
->hchild
, vector
, i
);
5225 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
5226 Scurrent_window_configuration
, 0, 1, 0,
5227 "Return an object representing the current window configuration of FRAME.\n\
5228 If FRAME is nil or omitted, use the selected frame.\n\
5229 This describes the number of windows, their sizes and current buffers,\n\
5230 and for each displayed buffer, where display starts, and the positions of\n\
5231 point and mark. An exception is made for point in the current buffer:\n\
5232 its value is -not- saved.\n\
5233 This also records the currently selected frame, and FRAME's focus\n\
5234 redirection (see `redirect-frame-focus').")
5238 register Lisp_Object tem
;
5239 register int n_windows
;
5240 register struct save_window_data
*data
;
5241 register struct Lisp_Vector
*vec
;
5246 frame
= selected_frame
;
5247 CHECK_LIVE_FRAME (frame
, 0);
5250 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5251 vec
= allocate_vectorlike (VECSIZE (struct save_window_data
));
5252 for (i
= 0; i
< VECSIZE (struct save_window_data
); i
++)
5253 vec
->contents
[i
] = Qnil
;
5254 vec
->size
= VECSIZE (struct save_window_data
);
5255 data
= (struct save_window_data
*)vec
;
5257 XSETFASTINT (data
->frame_width
, FRAME_WIDTH (f
));
5258 XSETFASTINT (data
->frame_height
, FRAME_HEIGHT (f
));
5259 XSETFASTINT (data
->frame_menu_bar_lines
, FRAME_MENU_BAR_LINES (f
));
5260 XSETFASTINT (data
->frame_tool_bar_lines
, FRAME_TOOL_BAR_LINES (f
));
5261 data
->selected_frame
= selected_frame
;
5262 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
5263 XSETBUFFER (data
->current_buffer
, current_buffer
);
5264 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
5265 data
->root_window
= FRAME_ROOT_WINDOW (f
);
5266 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
5267 XSETINT (data
->min_height
, window_min_height
);
5268 XSETINT (data
->min_width
, window_min_width
);
5269 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
5270 data
->saved_windows
= tem
;
5271 for (i
= 0; i
< n_windows
; i
++)
5272 XVECTOR (tem
)->contents
[i
]
5273 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
5274 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
5275 XSETWINDOW_CONFIGURATION (tem
, data
);
5279 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
5281 "Execute body, preserving window sizes and contents.\n\
5282 Restore which buffer appears in which window, where display starts,\n\
5283 and the value of point and mark for each window.\n\
5284 Also restore the choice of selected window.\n\
5285 Also restore which buffer is current.\n\
5286 Does not restore the value of point in current buffer.")
5290 register Lisp_Object val
;
5291 register int count
= specpdl_ptr
- specpdl
;
5293 record_unwind_protect (Fset_window_configuration
,
5294 Fcurrent_window_configuration (Qnil
));
5295 val
= Fprogn (args
);
5296 return unbind_to (count
, val
);
5300 /***********************************************************************
5302 ***********************************************************************/
5304 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
5306 "Set width of marginal areas of window WINDOW.\n\
5307 If window is nil, set margins of the currently selected window.\n\
5308 First parameter LEFT-WIDTH specifies the number of character\n\
5309 cells to reserve for the left marginal area. Second parameter\n\
5310 RIGHT-WIDTH does the same for the right marginal area.\n\
5311 A nil width parameter means no margin.")
5312 (window
, left
, right
)
5313 Lisp_Object window
, left
, right
;
5315 struct window
*w
= decode_window (window
);
5318 CHECK_NUMBER_OR_FLOAT (left
, 1);
5320 CHECK_NUMBER_OR_FLOAT (right
, 2);
5322 /* Check widths < 0 and translate a zero width to nil.
5323 Margins that are too wide have to be checked elsewhere. */
5324 if ((INTEGERP (left
) && XINT (left
) < 0)
5325 || (FLOATP (left
) && XFLOAT_DATA (left
) <= 0))
5326 XSETFASTINT (left
, 0);
5327 if (INTEGERP (left
) && XFASTINT (left
) == 0)
5330 if ((INTEGERP (right
) && XINT (right
) < 0)
5331 || (FLOATP (right
) && XFLOAT_DATA (right
) <= 0))
5332 XSETFASTINT (right
, 0);
5333 if (INTEGERP (right
) && XFASTINT (right
) == 0)
5336 w
->left_margin_width
= left
;
5337 w
->right_margin_width
= right
;
5339 ++windows_or_buffers_changed
;
5340 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
5345 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
5347 "Get width of marginal areas of window WINDOW.\n\
5348 If WINDOW is omitted or nil, use the currently selected window.\n\
5349 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
5350 If a marginal area does not exist, its width will be returned\n\
5355 struct window
*w
= decode_window (window
);
5356 return Fcons (w
->left_margin_width
, w
->right_margin_width
);
5361 /***********************************************************************
5363 ***********************************************************************/
5365 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 1, 0,
5366 "Return the amount by which WINDOW is scrolled vertically.\n\
5367 Use the selected window if WINDOW is nil or omitted.\n\
5368 Value is a multiple of the canonical character height of WINDOW.")
5377 window
= selected_window
;
5379 CHECK_WINDOW (window
, 0);
5380 w
= XWINDOW (window
);
5381 f
= XFRAME (w
->frame
);
5383 if (FRAME_WINDOW_P (f
))
5384 result
= CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
);
5386 result
= make_number (0);
5391 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
5393 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5394 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
5395 non-negative multiple of the canonical character height of WINDOW.")
5397 Lisp_Object window
, vscroll
;
5403 window
= selected_window
;
5405 CHECK_WINDOW (window
, 0);
5406 CHECK_NUMBER_OR_FLOAT (vscroll
, 1);
5408 w
= XWINDOW (window
);
5409 f
= XFRAME (w
->frame
);
5411 if (FRAME_WINDOW_P (f
))
5413 int old_dy
= w
->vscroll
;
5415 w
->vscroll
= - CANON_Y_UNIT (f
) * XFLOATINT (vscroll
);
5416 w
->vscroll
= min (w
->vscroll
, 0);
5418 /* Adjust glyph matrix of the frame if the virtual display
5419 area becomes larger than before. */
5420 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
5423 /* Prevent redisplay shortcuts. */
5424 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
5427 return Fwindow_vscroll (window
);
5431 /* Call FN for all leaf windows on frame F. FN is called with the
5432 first argument being a pointer to the leaf window, and with
5433 additional argument USER_DATA. Stops when FN returns 0. */
5436 foreach_window (f
, fn
, user_data
)
5438 int (* fn
) P_ ((struct window
*, void *));
5441 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
5445 /* Helper function for foreach_window. Call FN for all leaf windows
5446 reachable from W. FN is called with the first argument being a
5447 pointer to the leaf window, and with additional argument USER_DATA.
5448 Stop when FN returns 0. Value is 0 if stopped by FN. */
5451 foreach_window_1 (w
, fn
, user_data
)
5453 int (* fn
) P_ ((struct window
*, void *));
5458 for (cont
= 1; w
&& cont
;)
5460 if (!NILP (w
->hchild
))
5461 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
5462 else if (!NILP (w
->vchild
))
5463 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
5465 cont
= fn (w
, user_data
);
5467 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5474 /* Freeze or unfreeze the window start of W if unless it is a
5475 mini-window or the selected window. FREEZE_P non-null means freeze
5476 the window start. */
5479 freeze_window_start (w
, freeze_p
)
5483 if (w
== XWINDOW (selected_window
)
5484 || MINI_WINDOW_P (w
)
5485 || (MINI_WINDOW_P (XWINDOW (selected_window
))
5486 && ! NILP (Vminibuf_scroll_window
)
5487 && w
== XWINDOW (Vminibuf_scroll_window
)))
5490 w
->frozen_window_start_p
= freeze_p
!= NULL
;
5495 /* Freeze or unfreeze the window starts of all leaf windows on frame
5496 F, except the selected window and a mini-window. FREEZE_P non-zero
5497 means freeze the window start. */
5500 freeze_window_starts (f
, freeze_p
)
5504 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
5508 /***********************************************************************
5510 ***********************************************************************/
5512 /* Return 1 if window configurations C1 and C2
5513 describe the same state of affairs. This is used by Fequal. */
5516 compare_window_configurations (c1
, c2
, ignore_positions
)
5518 int ignore_positions
;
5520 register struct save_window_data
*d1
, *d2
;
5521 struct Lisp_Vector
*sw1
, *sw2
;
5524 if (!WINDOW_CONFIGURATIONP (c1
))
5525 wrong_type_argument (Qwindow_configuration_p
, c1
);
5526 if (!WINDOW_CONFIGURATIONP (c2
))
5527 wrong_type_argument (Qwindow_configuration_p
, c2
);
5529 d1
= (struct save_window_data
*) XVECTOR (c1
);
5530 d2
= (struct save_window_data
*) XVECTOR (c2
);
5531 sw1
= XVECTOR (d1
->saved_windows
);
5532 sw2
= XVECTOR (d2
->saved_windows
);
5534 if (! EQ (d1
->frame_width
, d2
->frame_width
))
5536 if (! EQ (d1
->frame_height
, d2
->frame_height
))
5538 if (! EQ (d1
->frame_menu_bar_lines
, d2
->frame_menu_bar_lines
))
5540 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
5542 /* Don't compare the current_window field directly.
5543 Instead see w1_is_current and w2_is_current, below. */
5544 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
5546 if (! ignore_positions
)
5547 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
5549 /* Don't compare the root_window field.
5550 We don't require the two configurations
5551 to use the same window object,
5552 and the two root windows must be equivalent
5553 if everything else compares equal. */
5554 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
5556 if (! EQ (d1
->min_width
, d2
->min_width
))
5558 if (! EQ (d1
->min_height
, d2
->min_height
))
5561 /* Verify that the two confis have the same number of windows. */
5562 if (sw1
->size
!= sw2
->size
)
5565 for (i
= 0; i
< sw1
->size
; i
++)
5567 struct saved_window
*p1
, *p2
;
5568 int w1_is_current
, w2_is_current
;
5570 p1
= SAVED_WINDOW_N (sw1
, i
);
5571 p2
= SAVED_WINDOW_N (sw2
, i
);
5573 /* Verify that the current windows in the two
5574 configurations correspond to each other. */
5575 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
5576 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
5578 if (w1_is_current
!= w2_is_current
)
5581 /* Verify that the corresponding windows do match. */
5582 if (! EQ (p1
->buffer
, p2
->buffer
))
5584 if (! EQ (p1
->left
, p2
->left
))
5586 if (! EQ (p1
->top
, p2
->top
))
5588 if (! EQ (p1
->width
, p2
->width
))
5590 if (! EQ (p1
->height
, p2
->height
))
5592 if (! EQ (p1
->display_table
, p2
->display_table
))
5594 if (! EQ (p1
->parent
, p2
->parent
))
5596 if (! EQ (p1
->prev
, p2
->prev
))
5598 if (! ignore_positions
)
5600 if (! EQ (p1
->hscroll
, p2
->hscroll
))
5602 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
5604 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
5606 if (NILP (Fequal (p1
->start
, p2
->start
)))
5608 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
5610 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
5618 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
5619 Scompare_window_configurations
, 2, 2, 0,
5620 "Compare two window configurations as regards the structure of windows.\n\
5621 This function ignores details such as the values of point and mark\n\
5622 and scrolling positions.")
5626 if (compare_window_configurations (x
, y
, 1))
5634 struct frame
*f
= make_terminal_frame ();
5635 XSETFRAME (selected_frame
, f
);
5636 Vterminal_frame
= selected_frame
;
5637 minibuf_window
= f
->minibuffer_window
;
5638 selected_window
= f
->selected_window
;
5639 last_nonminibuf_frame
= f
;
5641 window_initialized
= 1;
5647 Vwindow_list
= Qnil
;
5653 Qleft_fringe
= intern ("left-fringe");
5654 staticpro (&Qleft_fringe
);
5655 Qright_fringe
= intern ("right-fringe");
5656 staticpro (&Qright_fringe
);
5658 Qwindow_size_fixed
= intern ("window-size-fixed");
5659 staticpro (&Qwindow_size_fixed
);
5661 staticpro (&Qwindow_configuration_change_hook
);
5662 Qwindow_configuration_change_hook
5663 = intern ("window-configuration-change-hook");
5665 Qwindowp
= intern ("windowp");
5666 staticpro (&Qwindowp
);
5668 Qwindow_configuration_p
= intern ("window-configuration-p");
5669 staticpro (&Qwindow_configuration_p
);
5671 Qwindow_live_p
= intern ("window-live-p");
5672 staticpro (&Qwindow_live_p
);
5674 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
5675 staticpro (&Qtemp_buffer_show_hook
);
5677 staticpro (&Vwindow_list
);
5679 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
5680 "Non-nil means call as function to display a help buffer.\n\
5681 The function is called with one argument, the buffer to be displayed.\n\
5682 Used by `with-output-to-temp-buffer'.\n\
5683 If this function is used, then it must do the entire job of showing\n\
5684 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5685 Vtemp_buffer_show_function
= Qnil
;
5687 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
5688 "If non-nil, function to call to handle `display-buffer'.\n\
5689 It will receive two args, the buffer and a flag which if non-nil means\n\
5690 that the currently selected window is not acceptable.\n\
5691 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5692 work using this function.");
5693 Vdisplay_buffer_function
= Qnil
;
5695 DEFVAR_LISP ("even-window-heights", &Veven_window_heights
,
5696 "*If non-nil, `display-buffer' should even the window heights.\n\
5697 If nil, `display-buffer' will leave the window configuration alone.");
5698 Veven_window_heights
= Qt
;
5700 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
5701 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5702 Vminibuf_scroll_window
= Qnil
;
5704 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
5705 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5706 Vother_window_scroll_buffer
= Qnil
;
5708 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
5709 "*Non-nil means `display-buffer' should make a separate frame.");
5712 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames
,
5713 "*Non-nil means `display-buffer' should reuse frames.\n\
5714 If the buffer in question is already displayed in a frame, raise that frame.");
5715 display_buffer_reuse_frames
= 0;
5717 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
5718 "Function to call to handle automatic new frame creation.\n\
5719 It is called with no arguments and should return a newly created frame.\n\
5721 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5722 where `pop-up-frame-alist' would hold the default frame parameters.");
5723 Vpop_up_frame_function
= Qnil
;
5725 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
5726 "*List of buffer names that should have their own special frames.\n\
5727 Displaying a buffer whose name is in this list makes a special frame for it\n\
5728 using `special-display-function'. See also `special-display-regexps'.\n\
5730 An element of the list can be a list instead of just a string.\n\
5731 There are two ways to use a list as an element:\n\
5732 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5733 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5734 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5735 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5736 All this is done by the function found in `special-display-function'.\n\
5738 If this variable appears \"not to work\", because you add a name to it\n\
5739 but that buffer still appears in the selected window, look at the\n\
5740 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5741 Those variables take precedence over this one.");
5742 Vspecial_display_buffer_names
= Qnil
;
5744 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
5745 "*List of regexps saying which buffers should have their own special frames.\n\
5746 If a buffer name matches one of these regexps, it gets its own frame.\n\
5747 Displaying a buffer whose name is in this list makes a special frame for it\n\
5748 using `special-display-function'.\n\
5750 An element of the list can be a list instead of just a string.\n\
5751 There are two ways to use a list as an element:\n\
5752 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5753 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5754 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5755 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5756 All this is done by the function found in `special-display-function'.\n\
5758 If this variable appears \"not to work\", because you add a regexp to it\n\
5759 but the matching buffers still appear in the selected window, look at the\n\
5760 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5761 Those variables take precedence over this one.");
5762 Vspecial_display_regexps
= Qnil
;
5764 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
5765 "Function to call to make a new frame for a special buffer.\n\
5766 It is called with two arguments, the buffer and optional buffer specific\n\
5767 data, and should return a window displaying that buffer.\n\
5768 The default value makes a separate frame for the buffer,\n\
5769 using `special-display-frame-alist' to specify the frame parameters.\n\
5771 A buffer is special if its is listed in `special-display-buffer-names'\n\
5772 or matches a regexp in `special-display-regexps'.");
5773 Vspecial_display_function
= Qnil
;
5775 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
5776 "*List of buffer names that should appear in the selected window.\n\
5777 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5778 switches to it in the selected window, rather than making it appear\n\
5779 in some other window.\n\
5781 An element of the list can be a cons cell instead of just a string.\n\
5782 Then the car must be a string, which specifies the buffer name.\n\
5783 This is for compatibility with `special-display-buffer-names';\n\
5784 the cdr of the cons cell is ignored.\n\
5786 See also `same-window-regexps'.");
5787 Vsame_window_buffer_names
= Qnil
;
5789 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
5790 "*List of regexps saying which buffers should appear in the selected window.\n\
5791 If a buffer name matches one of these regexps, then displaying it\n\
5792 using `display-buffer' or `pop-to-buffer' switches to it\n\
5793 in the selected window, rather than making it appear in some other window.\n\
5795 An element of the list can be a cons cell instead of just a string.\n\
5796 Then the car must be a string, which specifies the buffer name.\n\
5797 This is for compatibility with `special-display-buffer-names';\n\
5798 the cdr of the cons cell is ignored.\n\
5800 See also `same-window-buffer-names'.");
5801 Vsame_window_regexps
= Qnil
;
5803 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
5804 "*Non-nil means display-buffer should make new windows.");
5807 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
5808 "*Number of lines of continuity when scrolling by screenfuls.");
5809 next_screen_context_lines
= 2;
5811 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
5812 "*display-buffer would prefer to split the largest window if this large.\n\
5813 If there is only one window, it is split regardless of this value.");
5814 split_height_threshold
= 500;
5816 DEFVAR_INT ("window-min-height", &window_min_height
,
5817 "*Delete any window less than this tall (including its mode line).");
5818 window_min_height
= 4;
5820 DEFVAR_INT ("window-min-width", &window_min_width
,
5821 "*Delete any window less than this wide.");
5822 window_min_width
= 10;
5824 DEFVAR_LISP ("scroll-preserve-screen-position",
5825 &Vscroll_preserve_screen_position
,
5826 "*Non-nil means scroll commands move point to keep its screen line unchanged.");
5827 Vscroll_preserve_screen_position
= Qnil
;
5829 DEFVAR_LISP ("window-configuration-change-hook",
5830 &Vwindow_configuration_change_hook
,
5831 "Functions to call when window configuration changes.\n\
5832 The selected frame is the one whose configuration has changed.");
5833 Vwindow_configuration_change_hook
= Qnil
;
5835 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed
,
5836 "Non-nil in a buffer means windows displaying the buffer are fixed-size.\n\
5837 Emacs won't change the size of any window displaying that buffer,\n\
5838 unless you explicitly change the size, or Emacs has no other choice.\n\
5839 This variable automatically becomes buffer-local when set.");
5840 Fmake_variable_buffer_local (Qwindow_size_fixed
);
5841 window_size_fixed
= 0;
5843 defsubr (&Sselected_window
);
5844 defsubr (&Sminibuffer_window
);
5845 defsubr (&Swindow_minibuffer_p
);
5846 defsubr (&Swindowp
);
5847 defsubr (&Swindow_live_p
);
5848 defsubr (&Spos_visible_in_window_p
);
5849 defsubr (&Swindow_buffer
);
5850 defsubr (&Swindow_height
);
5851 defsubr (&Swindow_width
);
5852 defsubr (&Swindow_hscroll
);
5853 defsubr (&Sset_window_hscroll
);
5854 defsubr (&Swindow_redisplay_end_trigger
);
5855 defsubr (&Sset_window_redisplay_end_trigger
);
5856 defsubr (&Swindow_edges
);
5857 defsubr (&Scoordinates_in_window_p
);
5858 defsubr (&Swindow_at
);
5859 defsubr (&Swindow_point
);
5860 defsubr (&Swindow_start
);
5861 defsubr (&Swindow_end
);
5862 defsubr (&Sset_window_point
);
5863 defsubr (&Sset_window_start
);
5864 defsubr (&Swindow_dedicated_p
);
5865 defsubr (&Sset_window_dedicated_p
);
5866 defsubr (&Swindow_display_table
);
5867 defsubr (&Sset_window_display_table
);
5868 defsubr (&Snext_window
);
5869 defsubr (&Sprevious_window
);
5870 defsubr (&Sother_window
);
5871 defsubr (&Sget_lru_window
);
5872 defsubr (&Sget_largest_window
);
5873 defsubr (&Sget_buffer_window
);
5874 defsubr (&Sdelete_other_windows
);
5875 defsubr (&Sdelete_windows_on
);
5876 defsubr (&Sreplace_buffer_in_windows
);
5877 defsubr (&Sdelete_window
);
5878 defsubr (&Sset_window_buffer
);
5879 defsubr (&Sselect_window
);
5880 defsubr (&Sspecial_display_p
);
5881 defsubr (&Ssame_window_p
);
5882 defsubr (&Sdisplay_buffer
);
5883 defsubr (&Ssplit_window
);
5884 defsubr (&Senlarge_window
);
5885 defsubr (&Sshrink_window
);
5886 defsubr (&Sscroll_up
);
5887 defsubr (&Sscroll_down
);
5888 defsubr (&Sscroll_left
);
5889 defsubr (&Sscroll_right
);
5890 defsubr (&Sother_window_for_scrolling
);
5891 defsubr (&Sscroll_other_window
);
5892 defsubr (&Srecenter
);
5893 defsubr (&Swindow_text_height
);
5894 defsubr (&Smove_to_window_line
);
5895 defsubr (&Swindow_configuration_p
);
5896 defsubr (&Swindow_configuration_frame
);
5897 defsubr (&Sset_window_configuration
);
5898 defsubr (&Scurrent_window_configuration
);
5899 defsubr (&Ssave_window_excursion
);
5900 defsubr (&Sset_window_margins
);
5901 defsubr (&Swindow_margins
);
5902 defsubr (&Swindow_vscroll
);
5903 defsubr (&Sset_window_vscroll
);
5904 defsubr (&Scompare_window_configurations
);
5905 defsubr (&Swindow_list
);
5911 initial_define_key (control_x_map
, '1', "delete-other-windows");
5912 initial_define_key (control_x_map
, '2', "split-window");
5913 initial_define_key (control_x_map
, '0', "delete-window");
5914 initial_define_key (control_x_map
, 'o', "other-window");
5915 initial_define_key (control_x_map
, '^', "enlarge-window");
5916 initial_define_key (control_x_map
, '<', "scroll-left");
5917 initial_define_key (control_x_map
, '>', "scroll-right");
5919 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
5920 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
5921 initial_define_key (meta_map
, 'v', "scroll-down");
5923 initial_define_key (global_map
, Ctl('L'), "recenter");
5924 initial_define_key (meta_map
, 'r', "move-to-window-line");