("latin-8-prefix", "latin-9-prefix"): New.
[emacs.git] / src / window.c
blobc7aa6769aa70d0f46909dc4cb719a00d23a1a44b
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 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include "lisp.h"
24 #include "buffer.h"
25 #include "keyboard.h"
26 #include "frame.h"
27 #include "window.h"
28 #include "commands.h"
29 #include "indent.h"
30 #include "termchar.h"
31 #include "disptab.h"
32 #include "dispextern.h"
33 #include "blockinput.h"
34 #include "intervals.h"
36 #ifdef HAVE_X_WINDOWS
37 #include "xterm.h"
38 #endif /* HAVE_X_WINDOWS */
39 #ifdef WINDOWSNT
40 #include "w32term.h"
41 #endif
42 #ifdef MSDOS
43 #include "msdos.h"
44 #endif
46 #ifndef max
47 #define max(a, b) ((a) < (b) ? (b) : (a))
48 #endif
51 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
52 Lisp_Object Qwindow_size_fixed, Qleft_bitmap_area, Qright_bitmap_area;
53 extern Lisp_Object Qheight, Qwidth;
55 static struct window *decode_window P_ ((Lisp_Object));
56 static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
57 static int count_windows P_ ((struct window *));
58 static int get_leaf_windows P_ ((struct window *, struct window **, int));
59 static void window_scroll P_ ((Lisp_Object, int, int, int));
60 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
61 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
62 static int window_min_size_1 P_ ((struct window *, int));
63 static int window_min_size P_ ((struct window *, int, int, int *));
64 static void size_window P_ ((Lisp_Object, int, int, int));
65 static int freeze_window_start P_ ((struct window *, void *));
66 static int window_fixed_size_p P_ ((struct window *, int, int));
67 static void enlarge_window P_ ((Lisp_Object, int, int));
68 static Lisp_Object window_list P_ ((void));
69 static int add_window_to_list P_ ((struct window *, void *));
70 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
71 Lisp_Object));
72 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
73 Lisp_Object, int));
74 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
75 Lisp_Object *));
76 static int foreach_window_1 P_ ((struct window *,
77 int (* fn) (struct window *, void *),
78 void *));
80 /* This is the window in which the terminal's cursor should
81 be left when nothing is being done with it. This must
82 always be a leaf window, and its buffer is selected by
83 the top level editing loop at the end of each command.
85 This value is always the same as
86 FRAME_SELECTED_WINDOW (selected_frame). */
88 Lisp_Object selected_window;
90 /* A list of all windows for use by next_window and Fwindow_list.
91 Functions creating or deleting windows should invalidate this cache
92 by setting it to nil. */
94 Lisp_Object Vwindow_list;
96 /* The mini-buffer window of the selected frame.
97 Note that you cannot test for mini-bufferness of an arbitrary window
98 by comparing against this; but you can test for mini-bufferness of
99 the selected window. */
101 Lisp_Object minibuf_window;
103 /* Non-nil means it is the window for C-M-v to scroll
104 when the mini-buffer is selected. */
106 Lisp_Object Vminibuf_scroll_window;
108 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
110 Lisp_Object Vother_window_scroll_buffer;
112 /* Non-nil means it's function to call to display temp buffers. */
114 Lisp_Object Vtemp_buffer_show_function;
116 /* If a window gets smaller than either of these, it is removed. */
118 int window_min_height;
119 int window_min_width;
121 /* Nonzero implies Fdisplay_buffer should create windows. */
123 int pop_up_windows;
125 /* Nonzero implies make new frames for Fdisplay_buffer. */
127 int pop_up_frames;
129 /* Nonzero means reuse existing frames for displaying buffers. */
131 int display_buffer_reuse_frames;
133 /* Non-nil means use this function instead of default */
135 Lisp_Object Vpop_up_frame_function;
137 /* Function to call to handle Fdisplay_buffer. */
139 Lisp_Object Vdisplay_buffer_function;
141 /* List of buffer *names* for buffers that should have their own frames. */
143 Lisp_Object Vspecial_display_buffer_names;
145 /* List of regexps for buffer names that should have their own frames. */
147 Lisp_Object Vspecial_display_regexps;
149 /* Function to pop up a special frame. */
151 Lisp_Object Vspecial_display_function;
153 /* List of buffer *names* for buffers to appear in selected window. */
155 Lisp_Object Vsame_window_buffer_names;
157 /* List of regexps for buffer names to appear in selected window. */
159 Lisp_Object Vsame_window_regexps;
161 /* Hook run at end of temp_output_buffer_show. */
163 Lisp_Object Qtemp_buffer_show_hook;
165 /* Fdisplay_buffer always splits the largest window
166 if that window is more than this high. */
168 int split_height_threshold;
170 /* Number of lines of continuity in scrolling by screenfuls. */
172 int next_screen_context_lines;
174 /* Incremented for each window created. */
176 static int sequence_number;
178 /* Nonzero after init_window_once has finished. */
180 static int window_initialized;
182 /* Hook to run when window config changes. */
184 Lisp_Object Qwindow_configuration_change_hook;
185 Lisp_Object Vwindow_configuration_change_hook;
187 /* Nonzero means scroll commands try to put point
188 at the same screen height as previously. */
190 Lisp_Object Vscroll_preserve_screen_position;
192 #if 0 /* This isn't used anywhere. */
193 /* Nonzero means we can split a frame even if it is "unsplittable". */
194 static int inhibit_frame_unsplittable;
195 #endif /* 0 */
197 #define min(a, b) ((a) < (b) ? (a) : (b))
199 extern int scroll_margin;
201 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
203 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
204 "Returns t if OBJECT is a window.")
205 (object)
206 Lisp_Object object;
208 return WINDOWP (object) ? Qt : Qnil;
211 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
212 "Returns t if OBJECT is a window which is currently visible.")
213 (object)
214 Lisp_Object object;
216 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
219 Lisp_Object
220 make_window ()
222 Lisp_Object val;
223 register struct window *p;
224 register struct Lisp_Vector *vec;
225 int i;
227 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
228 for (i = 0; i < VECSIZE (struct window); i++)
229 vec->contents[i] = Qnil;
230 vec->size = VECSIZE (struct window);
231 p = (struct window *) vec;
232 XSETFASTINT (p->sequence_number, ++sequence_number);
233 XSETFASTINT (p->left, 0);
234 XSETFASTINT (p->top, 0);
235 XSETFASTINT (p->height, 0);
236 XSETFASTINT (p->width, 0);
237 XSETFASTINT (p->hscroll, 0);
238 p->orig_top = p->orig_height = Qnil;
239 p->start = Fmake_marker ();
240 p->pointm = Fmake_marker ();
241 XSETFASTINT (p->use_time, 0);
242 p->frame = Qnil;
243 p->display_table = Qnil;
244 p->dedicated = Qnil;
245 p->pseudo_window_p = 0;
246 bzero (&p->cursor, sizeof (p->cursor));
247 bzero (&p->last_cursor, sizeof (p->last_cursor));
248 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
249 p->desired_matrix = p->current_matrix = 0;
250 p->phys_cursor_type = -1;
251 p->must_be_updated_p = 0;
252 XSETFASTINT (p->window_end_vpos, 0);
253 XSETFASTINT (p->window_end_pos, 0);
254 p->window_end_valid = Qnil;
255 p->vscroll = 0;
256 XSETWINDOW (val, p);
257 XSETFASTINT (p->last_point, 0);
258 p->frozen_window_start_p = 0;
260 Vwindow_list = Qnil;
261 return val;
264 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
265 "Return the window that the cursor now appears in and commands apply to.")
268 return selected_window;
271 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
272 "Return the window used now for minibuffers.\n\
273 If the optional argument FRAME is specified, return the minibuffer window\n\
274 used by that frame.")
275 (frame)
276 Lisp_Object frame;
278 if (NILP (frame))
279 frame = selected_frame;
280 CHECK_LIVE_FRAME (frame, 0);
281 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
284 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
285 "Returns non-nil if WINDOW is a minibuffer window.")
286 (window)
287 Lisp_Object window;
289 struct window *w = decode_window (window);
290 return (MINI_WINDOW_P (w) ? Qt : Qnil);
293 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
294 Spos_visible_in_window_p, 0, 2, 0,
295 "Return t if position POS is currently on the frame in WINDOW.\n\
296 Returns nil if that position is scrolled vertically out of view.\n\
297 POS defaults to point; WINDOW, to the selected window.")
298 (pos, window)
299 Lisp_Object pos, window;
301 register struct window *w;
302 register int posint;
303 register struct buffer *buf;
304 struct text_pos top;
305 Lisp_Object in_window;
307 if (NILP (pos))
308 posint = PT;
309 else
311 CHECK_NUMBER_COERCE_MARKER (pos, 0);
312 posint = XINT (pos);
315 w = decode_window (window);
316 buf = XBUFFER (w->buffer);
317 SET_TEXT_POS_FROM_MARKER (top, w->start);
319 /* If position above window, it's not visible. */
320 if (posint < CHARPOS (top))
321 in_window = Qnil;
322 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
323 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
324 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
325 /* If frame is up to date, and POSINT is < window end pos, use
326 that info. This doesn't work for POSINT == end pos, because
327 the window end pos is actually the position _after_ the last
328 char in the window. */
329 in_window = Qt;
330 else if (posint > BUF_ZV (buf))
331 in_window = Qnil;
332 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
333 /* If window start is out of range, do something reasonable. */
334 in_window = Qnil;
335 else
337 struct it it;
338 start_display (&it, w, top);
339 move_it_to (&it, posint, 0, it.last_visible_y, -1,
340 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
341 in_window = IT_CHARPOS (it) == posint ? Qt : Qnil;
344 return in_window;
347 static struct window *
348 decode_window (window)
349 register Lisp_Object window;
351 if (NILP (window))
352 return XWINDOW (selected_window);
354 CHECK_LIVE_WINDOW (window, 0);
355 return XWINDOW (window);
358 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
359 "Return the buffer that WINDOW is displaying.")
360 (window)
361 Lisp_Object window;
363 return decode_window (window)->buffer;
366 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
367 "Return the number of lines in WINDOW (including its mode line).")
368 (window)
369 Lisp_Object window;
371 return decode_window (window)->height;
374 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
375 "Return the number of display columns in WINDOW.\n\
376 This is the width that is usable columns available for text in WINDOW.\n\
377 If you want to find out how many columns WINDOW takes up,\n\
378 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
379 (window)
380 Lisp_Object window;
382 return make_number (window_internal_width (decode_window (window)));
385 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
386 "Return the number of columns by which WINDOW is scrolled from left margin.")
387 (window)
388 Lisp_Object window;
390 return decode_window (window)->hscroll;
393 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
394 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
395 NCOL should be zero or positive.")
396 (window, ncol)
397 register Lisp_Object window, ncol;
399 register struct window *w;
401 CHECK_NUMBER (ncol, 1);
402 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
403 w = decode_window (window);
404 if (XINT (w->hscroll) != XINT (ncol))
405 /* Prevent redisplay shortcuts */
406 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
407 w->hscroll = ncol;
408 return ncol;
411 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
412 Swindow_redisplay_end_trigger, 0, 1, 0,
413 "Return WINDOW's redisplay end trigger value.\n\
414 See `set-window-redisplay-end-trigger' for more information.")
415 (window)
416 Lisp_Object window;
418 return decode_window (window)->redisplay_end_trigger;
421 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
422 Sset_window_redisplay_end_trigger, 2, 2, 0,
423 "Set WINDOW's redisplay end trigger value to VALUE.\n\
424 VALUE should be a buffer position (typically a marker) or nil.\n\
425 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
426 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
427 with two arguments: WINDOW, and the end trigger value.\n\
428 Afterwards the end-trigger value is reset to nil.")
429 (window, value)
430 register Lisp_Object window, value;
432 register struct window *w;
434 w = decode_window (window);
435 w->redisplay_end_trigger = value;
436 return value;
439 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
440 "Return a list of the edge coordinates of WINDOW.\n\
441 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
442 RIGHT is one more than the rightmost column used by WINDOW,\n\
443 and BOTTOM is one more than the bottommost row used by WINDOW\n\
444 and its mode-line.")
445 (window)
446 Lisp_Object window;
448 register struct window *w = decode_window (window);
450 return Fcons (w->left, Fcons (w->top,
451 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
452 Fcons (make_number (XFASTINT (w->top)
453 + XFASTINT (w->height)),
454 Qnil))));
457 /* Test if the character at column *X, row *Y is within window W.
458 If it is not, return 0;
459 if it is in the window's text area,
460 set *x and *y to its location relative to the upper left corner
461 of the window, and
462 return 1;
463 if it is on the window's modeline, return 2;
464 if it is on the border between the window and its right sibling,
465 return 3.
466 if it is on the window's top line, return 4;
467 if it is in the bitmap area to the left/right of the window,
468 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
470 X and Y are frame relative pixel coordinates. */
472 static int
473 coordinates_in_window (w, x, y)
474 register struct window *w;
475 register int *x, *y;
477 struct frame *f = XFRAME (WINDOW_FRAME (w));
478 int left_x, right_x, top_y, bottom_y;
479 int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
481 /* In what's below, we subtract 1 when computing right_x because we
482 want the rightmost pixel, which is given by left_pixel+width-1. */
483 if (w->pseudo_window_p)
485 left_x = 0;
486 right_x = XFASTINT (w->width) * CANON_Y_UNIT (f) - 1;
487 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
488 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
490 else
492 left_x = (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w)
493 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
494 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w) - 1;
495 top_y = (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w)
496 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
497 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
500 if (*y < top_y
501 || *y >= bottom_y
502 || *x < (left_x
503 - flags_area_width
504 - (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
505 * CANON_X_UNIT (f)))
506 || *x > right_x + flags_area_width)
507 /* Completely outside anything interesting. */
508 return 0;
509 else if (WINDOW_WANTS_MODELINE_P (w)
510 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
511 /* On the mode line. */
512 return 2;
513 else if (WINDOW_WANTS_HEADER_LINE_P (w)
514 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
515 /* On the top line. */
516 return 4;
517 else if (*x < left_x || *x >= right_x)
519 /* Other lines than the mode line don't include flags areas and
520 scroll bars on the left. */
522 /* Convert X and Y to window-relative pixel coordinates. */
523 *x -= left_x;
524 *y -= top_y;
525 return *x < left_x ? 5 : 6;
527 else if (!w->pseudo_window_p
528 && !WINDOW_RIGHTMOST_P (w)
529 && *x >= right_x - CANON_X_UNIT (f))
530 /* On the border on the right side of the window? Assume that
531 this area begins at RIGHT_X minus a canonical char width. */
532 return 3;
533 else
535 /* Convert X and Y to window-relative pixel coordinates. */
536 *x -= left_x;
537 *y -= top_y;
538 return 1;
542 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
543 Scoordinates_in_window_p, 2, 2, 0,
544 "Return non-nil if COORDINATES are in WINDOW.\n\
545 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
546 measured in characters from the upper-left corner of the frame.\n\
547 (0 . 0) denotes the character in the upper left corner of the\n\
548 frame.\n\
549 If COORDINATES are in the text portion of WINDOW,\n\
550 the coordinates relative to the window are returned.\n\
551 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
552 If they are in the top mode line of WINDOW, `header-line' is returned.\n\
553 If they are in the bitmap-area to the left of the window,\n\
554 `left-bitmap-area' is returned, if they are in the area on the right of\n\
555 the window, `right-bitmap-area' is returned.\n\
556 If they are on the border between WINDOW and its right sibling,\n\
557 `vertical-line' is returned.")
558 (coordinates, window)
559 register Lisp_Object coordinates, window;
561 struct window *w;
562 struct frame *f;
563 int x, y;
564 Lisp_Object lx, ly;
566 CHECK_LIVE_WINDOW (window, 0);
567 w = XWINDOW (window);
568 f = XFRAME (w->frame);
569 CHECK_CONS (coordinates, 1);
570 lx = Fcar (coordinates);
571 ly = Fcdr (coordinates);
572 CHECK_NUMBER_OR_FLOAT (lx, 1);
573 CHECK_NUMBER_OR_FLOAT (ly, 1);
574 x = PIXEL_X_FROM_CANON_X (f, lx);
575 y = PIXEL_Y_FROM_CANON_Y (f, ly);
577 switch (coordinates_in_window (w, &x, &y))
579 case 0: /* NOT in window at all. */
580 return Qnil;
582 case 1: /* In text part of window. */
583 /* X and Y are now window relative pixel coordinates.
584 Convert them to canonical char units before returning
585 them. */
586 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
587 CANON_Y_FROM_PIXEL_Y (f, y));
589 case 2: /* In mode line of window. */
590 return Qmode_line;
592 case 3: /* On right border of window. */
593 return Qvertical_line;
595 case 4:
596 return Qheader_line;
598 case 5:
599 return Qleft_bitmap_area;
601 case 6:
602 return Qright_bitmap_area;
604 default:
605 abort ();
610 /* Callback for foreach_window, used in window_from_coordinates.
611 Check if window W contains coordinates specified by USER_DATA which
612 is actually a pointer to a struct check_window_data CW.
614 Check if window W contains coordinates *CW->x and *CW->y. If it
615 does, return W in *CW->window, as Lisp_Object, and return in
616 *CW->part the part of the window under coordinates *X,*Y. Return
617 zero from this function to stop iterating over windows. */
619 struct check_window_data
621 Lisp_Object *window;
622 int *x, *y, *part;
625 static int
626 check_window_containing (w, user_data)
627 struct window *w;
628 void *user_data;
630 struct check_window_data *cw = (struct check_window_data *) user_data;
631 int found;
633 found = coordinates_in_window (w, cw->x, cw->y);
634 if (found)
636 *cw->part = found - 1;
637 XSETWINDOW (*cw->window, w);
640 return !found;
644 /* Find the window containing frame-relative pixel position X/Y and
645 return it as a Lisp_Object. If X, Y is on the window's modeline,
646 set *PART to 1; if it is on the separating line between the window
647 and its right sibling, set it to 2; otherwise set it to 0. If
648 there is no window under X, Y return nil and leave *PART
649 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
651 This function was previously implemented with a loop cycling over
652 windows with Fnext_window, and starting with the frame's selected
653 window. It turned out that this doesn't work with an
654 implementation of next_window using Vwindow_list, because
655 FRAME_SELECTED_WINDOW (F) is not always contained in the window
656 tree of F when this function is called asynchronously from
657 note_mouse_highlight. The original loop didn't terminate in this
658 case. */
660 Lisp_Object
661 window_from_coordinates (f, x, y, part, tool_bar_p)
662 struct frame *f;
663 int x, y;
664 int *part;
665 int tool_bar_p;
667 Lisp_Object window;
668 struct check_window_data cw;
670 window = Qnil;
671 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
672 foreach_window (f, check_window_containing, &cw);
674 /* If not found above, see if it's in the tool bar window, if a tool
675 bar exists. */
676 if (NILP (window)
677 && tool_bar_p
678 && WINDOWP (f->tool_bar_window)
679 && XINT (XWINDOW (f->tool_bar_window)->height) > 0
680 && coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y))
682 *part = 0;
683 window = f->tool_bar_window;
686 return window;
689 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
690 "Return window containing coordinates X and Y on FRAME.\n\
691 If omitted, FRAME defaults to the currently selected frame.\n\
692 The top left corner of the frame is considered to be row 0,\n\
693 column 0.")
694 (x, y, frame)
695 Lisp_Object x, y, frame;
697 int part;
698 struct frame *f;
700 if (NILP (frame))
701 frame = selected_frame;
702 CHECK_LIVE_FRAME (frame, 2);
703 f = XFRAME (frame);
705 /* Check that arguments are integers or floats. */
706 CHECK_NUMBER_OR_FLOAT (x, 0);
707 CHECK_NUMBER_OR_FLOAT (y, 1);
709 return window_from_coordinates (f,
710 PIXEL_X_FROM_CANON_X (f, x),
711 PIXEL_Y_FROM_CANON_Y (f, y),
712 &part, 0);
715 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
716 "Return current value of point in WINDOW.\n\
717 For a nonselected window, this is the value point would have\n\
718 if that window were selected.\n\
720 Note that, when WINDOW is the selected window and its buffer\n\
721 is also currently selected, the value returned is the same as (point).\n\
722 It would be more strictly correct to return the `top-level' value\n\
723 of point, outside of any save-excursion forms.\n\
724 But that is hard to define.")
725 (window)
726 Lisp_Object window;
728 register struct window *w = decode_window (window);
730 if (w == XWINDOW (selected_window)
731 && current_buffer == XBUFFER (w->buffer))
732 return Fpoint ();
733 return Fmarker_position (w->pointm);
736 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
737 "Return position at which display currently starts in WINDOW.\n\
738 This is updated by redisplay or by calling `set-window-start'.")
739 (window)
740 Lisp_Object window;
742 return Fmarker_position (decode_window (window)->start);
745 /* This is text temporarily removed from the doc string below.
747 This function returns nil if the position is not currently known.\n\
748 That happens when redisplay is preempted and doesn't finish.\n\
749 If in that case you want to compute where the end of the window would\n\
750 have been if redisplay had finished, do this:\n\
751 (save-excursion\n\
752 (goto-char (window-start window))\n\
753 (vertical-motion (1- (window-height window)) window)\n\
754 (point))") */
756 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
757 "Return position at which display currently ends in WINDOW.\n\
758 This is updated by redisplay, when it runs to completion.\n\
759 Simply changing the buffer text or setting `window-start'\n\
760 does not update this value.\n\
761 If UP-TO-DATE is non-nil, compute the up-to-date position\n\
762 if it isn't already recorded.")
763 (window, update)
764 Lisp_Object window, update;
766 Lisp_Object value;
767 struct window *w = decode_window (window);
768 Lisp_Object buf;
770 buf = w->buffer;
771 CHECK_BUFFER (buf, 0);
773 #if 0 /* This change broke some things. We should make it later. */
774 /* If we don't know the end position, return nil.
775 The user can compute it with vertical-motion if he wants to.
776 It would be nicer to do it automatically,
777 but that's so slow that it would probably bother people. */
778 if (NILP (w->window_end_valid))
779 return Qnil;
780 #endif
782 if (! NILP (update)
783 && ! (! NILP (w->window_end_valid)
784 && XFASTINT (w->last_modified) >= MODIFF))
786 struct text_pos startp;
787 struct it it;
789 /* In case W->start is out of the range, use something
790 reasonable. This situation occured when loading a file with
791 `-l' containing a call to `rmail' with subsequent other
792 commands. At the end, W->start happened to be BEG, while
793 rmail had already narrowed the buffer. */
794 if (XMARKER (w->start)->charpos < BEGV)
795 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
796 else if (XMARKER (w->start)->charpos > ZV)
797 SET_TEXT_POS (startp, ZV, ZV_BYTE);
798 else
799 SET_TEXT_POS_FROM_MARKER (startp, w->start);
801 /* Cannot use Fvertical_motion because that function doesn't
802 cope with variable-height lines. */
803 start_display (&it, w, startp);
804 move_it_vertically (&it, window_box_height (w));
805 value = make_number (IT_CHARPOS (it));
807 else
808 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
810 return value;
813 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
814 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
815 (window, pos)
816 Lisp_Object window, pos;
818 register struct window *w = decode_window (window);
820 CHECK_NUMBER_COERCE_MARKER (pos, 1);
821 if (w == XWINDOW (selected_window)
822 && XBUFFER (w->buffer) == current_buffer)
823 Fgoto_char (pos);
824 else
825 set_marker_restricted (w->pointm, pos, w->buffer);
827 return pos;
830 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
831 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
832 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
833 from overriding motion of point in order to display at this exact start.")
834 (window, pos, noforce)
835 Lisp_Object window, pos, noforce;
837 register struct window *w = decode_window (window);
839 CHECK_NUMBER_COERCE_MARKER (pos, 1);
840 set_marker_restricted (w->start, pos, w->buffer);
841 /* this is not right, but much easier than doing what is right. */
842 w->start_at_line_beg = Qnil;
843 if (NILP (noforce))
844 w->force_start = Qt;
845 w->update_mode_line = Qt;
846 XSETFASTINT (w->last_modified, 0);
847 XSETFASTINT (w->last_overlay_modified, 0);
848 if (!EQ (window, selected_window))
849 windows_or_buffers_changed++;
851 return pos;
854 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
855 1, 1, 0,
856 "Return WINDOW's dedicated object, usually t or nil.\n\
857 See also `set-window-dedicated-p'.")
858 (window)
859 Lisp_Object window;
861 return decode_window (window)->dedicated;
864 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
865 Sset_window_dedicated_p, 2, 2, 0,
866 "Control whether WINDOW is dedicated to the buffer it displays.\n\
867 If it is dedicated, Emacs will not automatically change\n\
868 which buffer appears in it.\n\
869 The second argument is the new value for the dedication flag;\n\
870 non-nil means yes.")
871 (window, arg)
872 Lisp_Object window, arg;
874 register struct window *w = decode_window (window);
876 if (NILP (arg))
877 w->dedicated = Qnil;
878 else
879 w->dedicated = Qt;
881 return w->dedicated;
884 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
885 0, 1, 0,
886 "Return the display-table that WINDOW is using.")
887 (window)
888 Lisp_Object window;
890 return decode_window (window)->display_table;
893 /* Get the display table for use on window W. This is either W's
894 display table or W's buffer's display table. Ignore the specified
895 tables if they are not valid; if no valid table is specified,
896 return 0. */
898 struct Lisp_Char_Table *
899 window_display_table (w)
900 struct window *w;
902 struct Lisp_Char_Table *dp = NULL;
904 if (DISP_TABLE_P (w->display_table))
905 dp = XCHAR_TABLE (w->display_table);
906 else if (BUFFERP (w->buffer))
908 struct buffer *b = XBUFFER (w->buffer);
910 if (DISP_TABLE_P (b->display_table))
911 dp = XCHAR_TABLE (b->display_table);
912 else if (DISP_TABLE_P (Vstandard_display_table))
913 dp = XCHAR_TABLE (Vstandard_display_table);
916 return dp;
919 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
920 "Set WINDOW's display-table to TABLE.")
921 (window, table)
922 register Lisp_Object window, table;
924 register struct window *w;
926 w = decode_window (window);
927 w->display_table = table;
928 return table;
931 /* Record info on buffer window w is displaying
932 when it is about to cease to display that buffer. */
933 static void
934 unshow_buffer (w)
935 register struct window *w;
937 Lisp_Object buf;
938 struct buffer *b;
940 buf = w->buffer;
941 b = XBUFFER (buf);
942 if (b != XMARKER (w->pointm)->buffer)
943 abort ();
945 #if 0
946 if (w == XWINDOW (selected_window)
947 || ! EQ (buf, XWINDOW (selected_window)->buffer))
948 /* Do this except when the selected window's buffer
949 is being removed from some other window. */
950 #endif
951 /* last_window_start records the start position that this buffer
952 had in the last window to be disconnected from it.
953 Now that this statement is unconditional,
954 it is possible for the buffer to be displayed in the
955 selected window, while last_window_start reflects another
956 window which was recently showing the same buffer.
957 Some people might say that might be a good thing. Let's see. */
958 b->last_window_start = marker_position (w->start);
960 /* Point in the selected window's buffer
961 is actually stored in that buffer, and the window's pointm isn't used.
962 So don't clobber point in that buffer. */
963 if (! EQ (buf, XWINDOW (selected_window)->buffer)
964 /* This line helps to fix Horsley's testbug.el bug. */
965 && !(WINDOWP (b->last_selected_window)
966 && w != XWINDOW (b->last_selected_window)
967 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
968 temp_set_point_both (b,
969 clip_to_bounds (BUF_BEGV (b),
970 XMARKER (w->pointm)->charpos,
971 BUF_ZV (b)),
972 clip_to_bounds (BUF_BEGV_BYTE (b),
973 marker_byte_position (w->pointm),
974 BUF_ZV_BYTE (b)));
976 if (WINDOWP (b->last_selected_window)
977 && w == XWINDOW (b->last_selected_window))
978 b->last_selected_window = Qnil;
981 /* Put replacement into the window structure in place of old. */
982 static void
983 replace_window (old, replacement)
984 Lisp_Object old, replacement;
986 register Lisp_Object tem;
987 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
989 /* If OLD is its frame's root_window, then replacement is the new
990 root_window for that frame. */
992 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
993 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
995 p->left = o->left;
996 p->top = o->top;
997 p->width = o->width;
998 p->height = o->height;
999 p->desired_matrix = p->current_matrix = 0;
1000 p->vscroll = 0;
1001 bzero (&p->cursor, sizeof (p->cursor));
1002 bzero (&p->last_cursor, sizeof (p->last_cursor));
1003 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1004 p->phys_cursor_type = -1;
1005 p->must_be_updated_p = 0;
1006 p->pseudo_window_p = 0;
1007 XSETFASTINT (p->window_end_vpos, 0);
1008 XSETFASTINT (p->window_end_pos, 0);
1009 p->window_end_valid = Qnil;
1010 p->frozen_window_start_p = 0;
1011 p->orig_top = p->orig_height = Qnil;
1013 p->next = tem = o->next;
1014 if (!NILP (tem))
1015 XWINDOW (tem)->prev = replacement;
1017 p->prev = tem = o->prev;
1018 if (!NILP (tem))
1019 XWINDOW (tem)->next = replacement;
1021 p->parent = tem = o->parent;
1022 if (!NILP (tem))
1024 if (EQ (XWINDOW (tem)->vchild, old))
1025 XWINDOW (tem)->vchild = replacement;
1026 if (EQ (XWINDOW (tem)->hchild, old))
1027 XWINDOW (tem)->hchild = replacement;
1030 /*** Here, if replacement is a vertical combination
1031 and so is its new parent, we should make replacement's
1032 children be children of that parent instead. ***/
1035 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1036 "Remove WINDOW from the display. Default is selected window.")
1037 (window)
1038 register Lisp_Object window;
1040 delete_window (window);
1042 if (! NILP (Vwindow_configuration_change_hook)
1043 && ! NILP (Vrun_hooks))
1044 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1046 return Qnil;
1049 void
1050 delete_window (window)
1051 register Lisp_Object window;
1053 register Lisp_Object tem, parent, sib;
1054 register struct window *p;
1055 register struct window *par;
1056 FRAME_PTR frame;
1058 /* Because this function is called by other C code on non-leaf
1059 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1060 so we can't decode_window here. */
1061 if (NILP (window))
1062 window = selected_window;
1063 else
1064 CHECK_WINDOW (window, 0);
1065 p = XWINDOW (window);
1067 /* It's okay to delete an already-deleted window. */
1068 if (NILP (p->buffer)
1069 && NILP (p->hchild)
1070 && NILP (p->vchild))
1071 return;
1073 parent = p->parent;
1074 if (NILP (parent))
1075 error ("Attempt to delete minibuffer or sole ordinary window");
1076 par = XWINDOW (parent);
1078 windows_or_buffers_changed++;
1079 Vwindow_list = Qnil;
1080 frame = XFRAME (WINDOW_FRAME (p));
1081 FRAME_WINDOW_SIZES_CHANGED (frame) = 1;
1083 /* Are we trying to delete any frame's selected window? */
1085 Lisp_Object frame, pwindow;
1087 /* See if the frame's selected window is either WINDOW
1088 or any subwindow of it, by finding all that window's parents
1089 and comparing each one with WINDOW. */
1090 frame = WINDOW_FRAME (XWINDOW (window));
1091 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
1093 while (!NILP (pwindow))
1095 if (EQ (window, pwindow))
1096 break;
1097 pwindow = XWINDOW (pwindow)->parent;
1100 if (EQ (window, pwindow))
1102 Lisp_Object alternative;
1103 alternative = Fnext_window (window, Qlambda, Qnil);
1105 /* If we're about to delete the selected window on the
1106 selected frame, then we should use Fselect_window to select
1107 the new window. On the other hand, if we're about to
1108 delete the selected window on any other frame, we shouldn't do
1109 anything but set the frame's selected_window slot. */
1110 if (EQ (window, selected_window))
1111 Fselect_window (alternative);
1112 else
1113 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
1117 tem = p->buffer;
1118 /* tem is null for dummy parent windows
1119 (which have inferiors but not any contents themselves) */
1120 if (!NILP (tem))
1122 unshow_buffer (p);
1123 unchain_marker (p->pointm);
1124 unchain_marker (p->start);
1127 /* Free window glyph matrices. It is sure that they are allocated
1128 again when ADJUST_GLYPHS is called. Block input so that expose
1129 events and other events that access glyph matrices are not
1130 processed while we are changing them. */
1131 BLOCK_INPUT;
1132 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (frame)));
1134 tem = p->next;
1135 if (!NILP (tem))
1136 XWINDOW (tem)->prev = p->prev;
1138 tem = p->prev;
1139 if (!NILP (tem))
1140 XWINDOW (tem)->next = p->next;
1142 if (EQ (window, par->hchild))
1143 par->hchild = p->next;
1144 if (EQ (window, par->vchild))
1145 par->vchild = p->next;
1147 /* Find one of our siblings to give our space to. */
1148 sib = p->prev;
1149 if (NILP (sib))
1151 /* If p gives its space to its next sibling, that sibling needs
1152 to have its top/left side pulled back to where p's is.
1153 set_window_{height,width} will re-position the sibling's
1154 children. */
1155 sib = p->next;
1156 XWINDOW (sib)->top = p->top;
1157 XWINDOW (sib)->left = p->left;
1160 /* Stretch that sibling. */
1161 if (!NILP (par->vchild))
1162 set_window_height (sib,
1163 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1165 if (!NILP (par->hchild))
1166 set_window_width (sib,
1167 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1170 /* If parent now has only one child,
1171 put the child into the parent's place. */
1172 tem = par->hchild;
1173 if (NILP (tem))
1174 tem = par->vchild;
1175 if (NILP (XWINDOW (tem)->next))
1176 replace_window (parent, tem);
1178 /* Since we may be deleting combination windows, we must make sure that
1179 not only p but all its children have been marked as deleted. */
1180 if (! NILP (p->hchild))
1181 delete_all_subwindows (XWINDOW (p->hchild));
1182 else if (! NILP (p->vchild))
1183 delete_all_subwindows (XWINDOW (p->vchild));
1185 /* Mark this window as deleted. */
1186 p->buffer = p->hchild = p->vchild = Qnil;
1188 /* Adjust glyph matrices. */
1189 adjust_glyphs (frame);
1190 UNBLOCK_INPUT;
1195 /***********************************************************************
1196 Window List
1197 ***********************************************************************/
1199 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1200 pointer. This is a callback function for foreach_window, used in
1201 function window_list. */
1203 static int
1204 add_window_to_list (w, user_data)
1205 struct window *w;
1206 void *user_data;
1208 Lisp_Object *list = (Lisp_Object *) user_data;
1209 Lisp_Object window;
1210 XSETWINDOW (window, w);
1211 *list = Fcons (window, *list);
1212 return 1;
1216 /* Return a list of all windows, for use by next_window. If
1217 Vwindow_list is a list, return that list. Otherwise, build a new
1218 list, cache it in Vwindow_list, and return that. */
1220 static Lisp_Object
1221 window_list ()
1223 if (!CONSP (Vwindow_list))
1225 Lisp_Object tail;
1227 Vwindow_list = Qnil;
1228 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1230 Lisp_Object args[2];
1232 /* We are visiting windows in canonical order, and add
1233 new windows at the front of args[1], which means we
1234 have to reverse this list at the end. */
1235 args[1] = Qnil;
1236 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1237 args[0] = Vwindow_list;
1238 args[1] = Fnreverse (args[1]);
1239 Vwindow_list = Fnconc (2, args);
1243 return Vwindow_list;
1247 /* Value is non-zero if WINDOW satisfies the constraints given by
1248 OWINDOW, MINIBUF and ALL_FRAMES.
1250 MINIBUF t means WINDOW may be minibuffer windows.
1251 `lambda' means WINDOW may not be a minibuffer window.
1252 a window means a specific minibuffer window
1254 ALL_FRAMES t means search all frames,
1255 nil means search just current frame,
1256 `visible' means search just visible frames,
1257 0 means search visible and iconified frames,
1258 a window means search the frame that window belongs to,
1259 a frame means consider windows on that frame, only. */
1261 static int
1262 candidate_window_p (window, owindow, minibuf, all_frames)
1263 Lisp_Object window, owindow, minibuf, all_frames;
1265 struct window *w = XWINDOW (window);
1266 struct frame *f = XFRAME (w->frame);
1267 int candidate_p = 1;
1269 if (!BUFFERP (w->buffer))
1270 candidate_p = 0;
1271 else if (MINI_WINDOW_P (w)
1272 && (EQ (minibuf, Qlambda)
1273 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1275 /* If MINIBUF is `lambda' don't consider any mini-windows.
1276 If it is a window, consider only that one. */
1277 candidate_p = 0;
1279 else if (EQ (all_frames, Qt))
1280 candidate_p = 1;
1281 else if (NILP (all_frames))
1283 xassert (WINDOWP (owindow));
1284 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1286 else if (EQ (all_frames, Qvisible))
1288 FRAME_SAMPLE_VISIBILITY (f);
1289 candidate_p = FRAME_VISIBLE_P (f);
1291 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1293 FRAME_SAMPLE_VISIBILITY (f);
1294 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1296 else if (WINDOWP (all_frames))
1297 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1298 || EQ (XWINDOW (all_frames)->frame, w->frame)
1299 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1300 else if (FRAMEP (all_frames))
1301 candidate_p = EQ (all_frames, w->frame);
1303 return candidate_p;
1307 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1308 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1309 ALL_FRAMES. */
1311 static void
1312 decode_next_window_args (window, minibuf, all_frames)
1313 Lisp_Object *window, *minibuf, *all_frames;
1315 if (NILP (*window))
1316 *window = selected_window;
1317 else
1318 CHECK_LIVE_WINDOW (*window, 0);
1320 /* MINIBUF nil may or may not include minibuffers. Decide if it
1321 does. */
1322 if (NILP (*minibuf))
1323 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1324 else if (!EQ (*minibuf, Qt))
1325 *minibuf = Qlambda;
1327 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1328 => count none of them, or a specific minibuffer window (the
1329 active one) to count. */
1331 /* ALL_FRAMES nil doesn't specify which frames to include. */
1332 if (NILP (*all_frames))
1333 *all_frames = (!EQ (*minibuf, Qlambda)
1334 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1335 : Qnil);
1336 else if (EQ (*all_frames, Qvisible))
1338 else if (XFASTINT (*all_frames) == 0)
1340 else if (FRAMEP (*all_frames))
1342 else if (!EQ (*all_frames, Qt))
1343 *all_frames = Qnil;
1345 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1346 search just current frame, `visible' meaning search just visible
1347 frames, 0 meaning search visible and iconified frames, or a
1348 window, meaning search the frame that window belongs to, or a
1349 frame, meaning consider windows on that frame, only. */
1353 /* Return the next or previous window of WINDOW in canonical ordering
1354 of windows. NEXT_P non-zero means return the next window. See the
1355 documentation string of next-window for the meaning of MINIBUF and
1356 ALL_FRAMES. */
1358 static Lisp_Object
1359 next_window (window, minibuf, all_frames, next_p)
1360 Lisp_Object window, minibuf, all_frames;
1361 int next_p;
1363 decode_next_window_args (&window, &minibuf, &all_frames);
1365 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1366 return the first window on the frame. */
1367 if (FRAMEP (all_frames)
1368 && !EQ (all_frames, XWINDOW (window)->frame))
1369 return Fframe_first_window (all_frames);
1371 if (next_p)
1373 Lisp_Object list;
1375 /* Find WINDOW in the list of all windows. */
1376 list = Fmemq (window, window_list ());
1378 /* Scan forward from WINDOW to the end of the window list. */
1379 if (CONSP (list))
1380 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1381 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1382 break;
1384 /* Scan from the start of the window list up to WINDOW. */
1385 if (!CONSP (list))
1386 for (list = Vwindow_list;
1387 CONSP (list) && !EQ (XCAR (list), window);
1388 list = XCDR (list))
1389 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1390 break;
1392 if (CONSP (list))
1393 window = XCAR (list);
1395 else
1397 Lisp_Object candidate, list;
1399 /* Scan through the list of windows for candidates. If there are
1400 candidate windows in front of WINDOW, the last one of these
1401 is the one we want. If there are candidates following WINDOW
1402 in the list, again the last one of these is the one we want. */
1403 candidate = Qnil;
1404 for (list = window_list (); CONSP (list); list = XCDR (list))
1406 if (EQ (XCAR (list), window))
1408 if (WINDOWP (candidate))
1409 break;
1411 else if (candidate_window_p (XCAR (list), window, minibuf,
1412 all_frames))
1413 candidate = XCAR (list);
1416 if (WINDOWP (candidate))
1417 window = candidate;
1420 return window;
1424 /* This comment supplies the doc string for `next-window',
1425 for make-docfile to see. We cannot put this in the real DEFUN
1426 due to limits in the Unix cpp.
1428 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
1429 "Return next window after WINDOW in canonical ordering of windows.\n\
1430 If omitted, WINDOW defaults to the selected window.\n\
1432 Optional second arg MINIBUF t means count the minibuffer window even\n\
1433 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1434 it is active. MINIBUF neither t nor nil means not to count the\n\
1435 minibuffer even if it is active.\n\
1437 Several frames may share a single minibuffer; if the minibuffer\n\
1438 counts, all windows on all frames that share that minibuffer count\n\
1439 too. Therefore, `next-window' can be used to iterate through the\n\
1440 set of windows even when the minibuffer is on another frame. If the\n\
1441 minibuffer does not count, only windows from WINDOW's frame count.\n\
1443 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1444 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1445 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1446 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1447 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1448 Anything else means restrict to WINDOW's frame.\n\
1450 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1451 `next-window' to iterate through the entire cycle of acceptable\n\
1452 windows, eventually ending up back at the window you started with.\n\
1453 `previous-window' traverses the same cycle, in the reverse order.")
1454 (window, minibuf, all_frames) */
1456 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1458 (window, minibuf, all_frames)
1459 Lisp_Object window, minibuf, all_frames;
1461 return next_window (window, minibuf, all_frames, 1);
1465 /* This comment supplies the doc string for `previous-window',
1466 for make-docfile to see. We cannot put this in the real DEFUN
1467 due to limits in the Unix cpp.
1469 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1470 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1471 If omitted, WINDOW defaults to the selected window.\n\
1473 Optional second arg MINIBUF t means count the minibuffer window even\n\
1474 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1475 it is active. MINIBUF neither t nor nil means not to count the\n\
1476 minibuffer even if it is active.\n\
1478 Several frames may share a single minibuffer; if the minibuffer\n\
1479 counts, all windows on all frames that share that minibuffer count\n\
1480 too. Therefore, `previous-window' can be used to iterate through\n\
1481 the set of windows even when the minibuffer is on another frame. If\n\
1482 the minibuffer does not count, only windows from WINDOW's frame count\n\
1484 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1485 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1486 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1487 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1488 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1489 Anything else means restrict to WINDOW's frame.\n\
1491 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1492 `previous-window' to iterate through the entire cycle of acceptable\n\
1493 windows, eventually ending up back at the window you started with.\n\
1494 `next-window' traverses the same cycle, in the reverse order.")
1495 (window, minibuf, all_frames) */
1498 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1500 (window, minibuf, all_frames)
1501 Lisp_Object window, minibuf, all_frames;
1503 return next_window (window, minibuf, all_frames, 0);
1507 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1508 "Select the ARG'th different window on this frame.\n\
1509 All windows on current frame are arranged in a cyclic order.\n\
1510 This command selects the window ARG steps away in that order.\n\
1511 A negative ARG moves in the opposite order. If the optional second\n\
1512 argument ALL_FRAMES is non-nil, cycle through all frames.")
1513 (arg, all_frames)
1514 Lisp_Object arg, all_frames;
1516 Lisp_Object window;
1517 int i;
1519 CHECK_NUMBER (arg, 0);
1520 window = selected_window;
1522 for (i = XINT (arg); i > 0; --i)
1523 window = Fnext_window (window, Qnil, all_frames);
1524 for (; i < 0; ++i)
1525 window = Fprevious_window (window, Qnil, all_frames);
1527 Fselect_window (window);
1528 return Qnil;
1532 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1533 "Return a list of windows in canonical ordering.\n\
1534 Arguments are like for `next-window'.")
1535 (window, minibuf, all_frames)
1536 Lisp_Object window, minibuf, all_frames;
1538 Lisp_Object tail, list;
1540 decode_next_window_args (&window, &minibuf, &all_frames);
1541 list = Qnil;
1543 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1544 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1545 list = Fcons (XCAR (tail), list);
1547 return Fnreverse (list);
1552 /* Look at all windows, performing an operation specified by TYPE
1553 with argument OBJ.
1554 If FRAMES is Qt, look at all frames;
1555 Qnil, look at just the selected frame;
1556 Qvisible, look at visible frames;
1557 a frame, just look at windows on that frame.
1558 If MINI is non-zero, perform the operation on minibuffer windows too.
1561 enum window_loop
1563 WINDOW_LOOP_UNUSED,
1564 GET_BUFFER_WINDOW, /* Arg is buffer */
1565 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1566 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1567 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1568 GET_LARGEST_WINDOW,
1569 UNSHOW_BUFFER, /* Arg is buffer */
1570 CHECK_ALL_WINDOWS
1573 static Lisp_Object
1574 window_loop (type, obj, mini, frames)
1575 enum window_loop type;
1576 Lisp_Object obj, frames;
1577 int mini;
1579 Lisp_Object window, windows, best_window, frame_arg;
1580 struct frame *f;
1581 struct gcpro gcpro1;
1583 /* If we're only looping through windows on a particular frame,
1584 frame points to that frame. If we're looping through windows
1585 on all frames, frame is 0. */
1586 if (FRAMEP (frames))
1587 f = XFRAME (frames);
1588 else if (NILP (frames))
1589 f = SELECTED_FRAME ();
1590 else
1591 f = NULL;
1593 if (f)
1594 frame_arg = Qlambda;
1595 else if (XFASTINT (frames) == 0)
1596 frame_arg = frames;
1597 else if (EQ (frames, Qvisible))
1598 frame_arg = frames;
1599 else
1600 frame_arg = Qt;
1602 /* frame_arg is Qlambda to stick to one frame,
1603 Qvisible to consider all visible frames,
1604 or Qt otherwise. */
1606 /* Pick a window to start with. */
1607 if (WINDOWP (obj))
1608 window = obj;
1609 else if (f)
1610 window = FRAME_SELECTED_WINDOW (f);
1611 else
1612 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1614 /* Figure out the last window we're going to mess with. Since
1615 Fnext_window, given the same options, is guaranteed to go in a
1616 ring, we can just use Fprevious_window to find the last one.
1618 We can't just wait until we hit the first window again, because
1619 it might be deleted. */
1621 windows = Fwindow_list (window, mini ? Qt : Qnil, frame_arg);
1622 GCPRO1 (windows);
1623 best_window = Qnil;
1625 for (; CONSP (windows); windows = CDR (windows))
1627 struct window *w;
1629 window = XCAR (windows);
1630 w = XWINDOW (window);
1632 /* Note that we do not pay attention here to whether the frame
1633 is visible, since Fwindow_list skips non-visible frames if
1634 that is desired, under the control of frame_arg. */
1635 if (!MINI_WINDOW_P (w)
1636 /* For UNSHOW_BUFFER, we must always consider all windows. */
1637 || type == UNSHOW_BUFFER
1638 || (mini && minibuf_level > 0))
1639 switch (type)
1641 case GET_BUFFER_WINDOW:
1642 if (EQ (w->buffer, obj)
1643 /* Don't find any minibuffer window
1644 except the one that is currently in use. */
1645 && (MINI_WINDOW_P (w)
1646 ? EQ (window, minibuf_window)
1647 : 1))
1649 UNGCPRO;
1650 return window;
1652 break;
1654 case GET_LRU_WINDOW:
1655 /* t as arg means consider only full-width windows */
1656 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1657 break;
1658 /* Ignore dedicated windows and minibuffers. */
1659 if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
1660 break;
1661 if (NILP (best_window)
1662 || (XFASTINT (XWINDOW (best_window)->use_time)
1663 > XFASTINT (w->use_time)))
1664 best_window = window;
1665 break;
1667 case DELETE_OTHER_WINDOWS:
1668 if (!EQ (window, obj))
1669 Fdelete_window (window);
1670 break;
1672 case DELETE_BUFFER_WINDOWS:
1673 if (EQ (w->buffer, obj))
1675 struct frame *f = XFRAME (WINDOW_FRAME (w));
1677 /* If this window is dedicated, and in a frame of its own,
1678 kill the frame. */
1679 if (EQ (window, FRAME_ROOT_WINDOW (f))
1680 && !NILP (w->dedicated)
1681 && other_visible_frames (f))
1683 /* Skip the other windows on this frame.
1684 There might be one, the minibuffer! */
1685 while (CONSP (XCDR (windows))
1686 && EQ (XWINDOW (XCAR (windows))->frame,
1687 XWINDOW (XCAR (XCDR (windows)))->frame))
1688 windows = XCDR (windows);
1690 /* Now we can safely delete the frame. */
1691 Fdelete_frame (w->frame, Qnil);
1693 else if (NILP (w->parent))
1695 /* If we're deleting the buffer displayed in the
1696 only window on the frame, find a new buffer to
1697 display there. */
1698 Lisp_Object buffer;
1699 buffer = Fother_buffer (obj, Qnil, w->frame);
1700 if (NILP (buffer))
1701 buffer = Fget_buffer_create (build_string ("*scratch*"));
1702 Fset_window_buffer (window, buffer);
1703 if (EQ (window, selected_window))
1704 Fset_buffer (w->buffer);
1706 else
1707 Fdelete_window (window);
1709 break;
1711 case GET_LARGEST_WINDOW:
1713 struct window *b;
1715 /* Ignore dedicated windows and minibuffers. */
1716 if (MINI_WINDOW_P (w)
1717 || !NILP (w->dedicated)
1718 || NILP (best_window))
1719 break;
1721 b = XWINDOW (best_window);
1722 if (NILP (best_window)
1723 || (XFASTINT (w->height) * XFASTINT (w->width)
1724 > (XFASTINT (b->height) * XFASTINT (b->width))))
1725 best_window = window;
1727 break;
1729 case UNSHOW_BUFFER:
1730 if (EQ (w->buffer, obj))
1732 Lisp_Object buffer;
1733 struct frame *f = XFRAME (w->frame);
1735 /* Find another buffer to show in this window. */
1736 buffer = Fother_buffer (obj, Qnil, w->frame);
1737 if (NILP (buffer))
1738 buffer = Fget_buffer_create (build_string ("*scratch*"));
1740 /* If this window is dedicated, and in a frame of its own,
1741 kill the frame. */
1742 if (EQ (window, FRAME_ROOT_WINDOW (f))
1743 && !NILP (w->dedicated)
1744 && other_visible_frames (f))
1746 /* Skip the other windows on this frame.
1747 There might be one, the minibuffer! */
1748 while (CONSP (XCDR (windows))
1749 && EQ (XWINDOW (XCAR (windows))->frame,
1750 XWINDOW (XCAR (XCDR (windows)))->frame))
1751 windows = XCDR (windows);
1753 /* Now we can safely delete the frame. */
1754 Fdelete_frame (w->frame, Qnil);
1756 else
1758 /* Otherwise show a different buffer in the window. */
1759 w->dedicated = Qnil;
1760 Fset_window_buffer (window, buffer);
1761 if (EQ (window, selected_window))
1762 Fset_buffer (w->buffer);
1765 break;
1767 /* Check for a window that has a killed buffer. */
1768 case CHECK_ALL_WINDOWS:
1769 if (! NILP (w->buffer)
1770 && NILP (XBUFFER (w->buffer)->name))
1771 abort ();
1772 break;
1776 UNGCPRO;
1777 return best_window;
1780 /* Used for debugging. Abort if any window has a dead buffer. */
1782 void
1783 check_all_windows ()
1785 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1788 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1789 "Return the window least recently selected or used for display.\n\
1790 If optional argument FRAME is `visible', search all visible frames.\n\
1791 If FRAME is 0, search all visible and iconified frames.\n\
1792 If FRAME is t, search all frames.\n\
1793 If FRAME is nil, search only the selected frame.\n\
1794 If FRAME is a frame, search only that frame.")
1795 (frame)
1796 Lisp_Object frame;
1798 register Lisp_Object w;
1799 /* First try for a window that is full-width */
1800 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1801 if (!NILP (w) && !EQ (w, selected_window))
1802 return w;
1803 /* If none of them, try the rest */
1804 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1807 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1808 "Return the largest window in area.\n\
1809 If optional argument FRAME is `visible', search all visible frames.\n\
1810 If FRAME is 0, search all visible and iconified frames.\n\
1811 If FRAME is t, search all frames.\n\
1812 If FRAME is nil, search only the selected frame.\n\
1813 If FRAME is a frame, search only that frame.")
1814 (frame)
1815 Lisp_Object frame;
1817 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1818 frame);
1821 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1822 "Return a window currently displaying BUFFER, or nil if none.\n\
1823 If optional argument FRAME is `visible', search all visible frames.\n\
1824 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1825 If FRAME is t, search all frames.\n\
1826 If FRAME is nil, search only the selected frame.\n\
1827 If FRAME is a frame, search only that frame.")
1828 (buffer, frame)
1829 Lisp_Object buffer, frame;
1831 buffer = Fget_buffer (buffer);
1832 if (BUFFERP (buffer))
1833 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1834 else
1835 return Qnil;
1838 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1839 0, 1, "",
1840 "Make WINDOW (or the selected window) fill its frame.\n\
1841 Only the frame WINDOW is on is affected.\n\
1842 This function tries to reduce display jumps\n\
1843 by keeping the text previously visible in WINDOW\n\
1844 in the same place on the frame. Doing this depends on\n\
1845 the value of (window-start WINDOW), so if calling this function\n\
1846 in a program gives strange scrolling, make sure the window-start\n\
1847 value is reasonable when this function is called.")
1848 (window)
1849 Lisp_Object window;
1851 struct window *w;
1852 int startpos;
1853 int top;
1855 if (NILP (window))
1856 window = selected_window;
1857 else
1858 CHECK_LIVE_WINDOW (window, 0);
1860 w = XWINDOW (window);
1862 startpos = marker_position (w->start);
1863 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
1865 if (MINI_WINDOW_P (w) && top > 0)
1866 error ("Can't expand minibuffer to full frame");
1868 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1870 /* Try to minimize scrolling, by setting the window start to the point
1871 will cause the text at the old window start to be at the same place
1872 on the frame. But don't try to do this if the window start is
1873 outside the visible portion (as might happen when the display is
1874 not current, due to typeahead). */
1875 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1876 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1878 struct position pos;
1879 struct buffer *obuf = current_buffer;
1881 Fset_buffer (w->buffer);
1882 /* This computation used to temporarily move point, but that can
1883 have unwanted side effects due to text properties. */
1884 pos = *vmotion (startpos, -top, w);
1886 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
1887 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
1888 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
1889 : Qnil);
1890 /* We need to do this, so that the window-scroll-functions
1891 get called. */
1892 w->optional_new_start = Qt;
1894 set_buffer_internal (obuf);
1897 return Qnil;
1900 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1901 1, 2, "bDelete windows on (buffer): ",
1902 "Delete all windows showing BUFFER.\n\
1903 Optional second argument FRAME controls which frames are affected.\n\
1904 If optional argument FRAME is `visible', search all visible frames.\n\
1905 If FRAME is 0, search all visible and iconified frames.\n\
1906 If FRAME is nil, search all frames.\n\
1907 If FRAME is t, search only the selected frame.\n\
1908 If FRAME is a frame, search only that frame.")
1909 (buffer, frame)
1910 Lisp_Object buffer, frame;
1912 /* FRAME uses t and nil to mean the opposite of what window_loop
1913 expects. */
1914 if (NILP (frame))
1915 frame = Qt;
1916 else if (EQ (frame, Qt))
1917 frame = Qnil;
1919 if (!NILP (buffer))
1921 buffer = Fget_buffer (buffer);
1922 CHECK_BUFFER (buffer, 0);
1923 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1926 return Qnil;
1929 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1930 Sreplace_buffer_in_windows,
1931 1, 1, "bReplace buffer in windows: ",
1932 "Replace BUFFER with some other buffer in all windows showing it.")
1933 (buffer)
1934 Lisp_Object buffer;
1936 if (!NILP (buffer))
1938 buffer = Fget_buffer (buffer);
1939 CHECK_BUFFER (buffer, 0);
1940 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1942 return Qnil;
1945 /* Replace BUFFER with some other buffer in all windows
1946 of all frames, even those on other keyboards. */
1948 void
1949 replace_buffer_in_all_windows (buffer)
1950 Lisp_Object buffer;
1952 #ifdef MULTI_KBOARD
1953 Lisp_Object tail, frame;
1955 /* A single call to window_loop won't do the job
1956 because it only considers frames on the current keyboard.
1957 So loop manually over frames, and handle each one. */
1958 FOR_EACH_FRAME (tail, frame)
1959 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
1960 #else
1961 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
1962 #endif
1965 /* Set the height of WINDOW and all its inferiors. */
1967 /* The smallest acceptable dimensions for a window. Anything smaller
1968 might crash Emacs. */
1970 #define MIN_SAFE_WINDOW_WIDTH (2)
1971 #define MIN_SAFE_WINDOW_HEIGHT (2)
1973 /* Make sure that window_min_height and window_min_width are
1974 not too small; if they are, set them to safe minima. */
1976 static void
1977 check_min_window_sizes ()
1979 /* Smaller values might permit a crash. */
1980 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1981 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1982 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1983 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1986 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1987 minimum allowable size. */
1989 void
1990 check_frame_size (frame, rows, cols)
1991 FRAME_PTR frame;
1992 int *rows, *cols;
1994 /* For height, we have to see:
1995 whether the frame has a minibuffer,
1996 whether it wants a mode line, and
1997 whether it has a menu bar. */
1998 int min_height =
1999 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2000 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2001 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2003 if (FRAME_TOP_MARGIN (frame) > 0)
2004 min_height += FRAME_TOP_MARGIN (frame);
2006 if (*rows < min_height)
2007 *rows = min_height;
2008 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2009 *cols = MIN_SAFE_WINDOW_WIDTH;
2013 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2014 check if W's width can be changed, otherwise check W's height.
2015 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2016 siblings, too. If none of the siblings is resizable, WINDOW isn't
2017 either. */
2019 static int
2020 window_fixed_size_p (w, width_p, check_siblings_p)
2021 struct window *w;
2022 int width_p, check_siblings_p;
2024 int fixed_p;
2025 struct window *c;
2027 if (!NILP (w->hchild))
2029 c = XWINDOW (w->hchild);
2031 if (width_p)
2033 /* A horiz. combination is fixed-width if all of if its
2034 children are. */
2035 while (c && window_fixed_size_p (c, width_p, 0))
2036 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2037 fixed_p = c == NULL;
2039 else
2041 /* A horiz. combination is fixed-height if one of if its
2042 children is. */
2043 while (c && !window_fixed_size_p (c, width_p, 0))
2044 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2045 fixed_p = c != NULL;
2048 else if (!NILP (w->vchild))
2050 c = XWINDOW (w->vchild);
2052 if (width_p)
2054 /* A vert. combination is fixed-width if one of if its
2055 children is. */
2056 while (c && !window_fixed_size_p (c, width_p, 0))
2057 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2058 fixed_p = c != NULL;
2060 else
2062 /* A vert. combination is fixed-height if all of if its
2063 children are. */
2064 while (c && window_fixed_size_p (c, width_p, 0))
2065 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2066 fixed_p = c == NULL;
2069 else if (BUFFERP (w->buffer))
2071 if (w->height_fixed_p && !width_p)
2072 fixed_p = 1;
2073 else
2075 struct buffer *old = current_buffer;
2076 Lisp_Object val;
2078 current_buffer = XBUFFER (w->buffer);
2079 val = find_symbol_value (Qwindow_size_fixed);
2080 current_buffer = old;
2082 fixed_p = 0;
2083 if (!EQ (val, Qunbound))
2085 fixed_p = !NILP (val);
2087 if (fixed_p
2088 && ((EQ (val, Qheight) && width_p)
2089 || (EQ (val, Qwidth) && !width_p)))
2090 fixed_p = 0;
2094 /* Can't tell if this one is resizable without looking at
2095 siblings. If all siblings are fixed-size this one is too. */
2096 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2098 Lisp_Object child;
2100 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2101 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2102 break;
2104 if (NILP (child))
2105 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2106 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2107 break;
2109 if (NILP (child))
2110 fixed_p = 1;
2113 else
2114 fixed_p = 1;
2116 return fixed_p;
2120 /* Return the minimum size of window W, not taking fixed-width windows
2121 into account. WIDTH_P non-zero means return the minimum width,
2122 otherwise return the minimum height. If W is a combination window,
2123 compute the minimum size from the minimum sizes of W's children. */
2125 static int
2126 window_min_size_1 (w, width_p)
2127 struct window *w;
2128 int width_p;
2130 struct window *c;
2131 int size;
2133 if (!NILP (w->hchild))
2135 c = XWINDOW (w->hchild);
2136 size = 0;
2138 if (width_p)
2140 /* The min width of a horizontal combination is
2141 the sum of the min widths of its children. */
2142 while (c)
2144 size += window_min_size_1 (c, width_p);
2145 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2148 else
2150 /* The min height a horizontal combination equals
2151 the maximum of all min height of its children. */
2152 while (c)
2154 int min_size = window_min_size_1 (c, width_p);
2155 size = max (min_size, size);
2156 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2160 else if (!NILP (w->vchild))
2162 c = XWINDOW (w->vchild);
2163 size = 0;
2165 if (width_p)
2167 /* The min width of a vertical combination is
2168 the maximum of the min widths of its children. */
2169 while (c)
2171 int min_size = window_min_size_1 (c, width_p);
2172 size = max (min_size, size);
2173 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2176 else
2178 /* The min height of a vertical combination equals
2179 the sum of the min height of its children. */
2180 while (c)
2182 size += window_min_size_1 (c, width_p);
2183 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2187 else
2189 if (width_p)
2190 size = window_min_width;
2191 else
2193 if (MINI_WINDOW_P (w)
2194 || (!WINDOW_WANTS_MODELINE_P (w)
2195 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2196 size = 1;
2197 else
2198 size = window_min_height;
2202 return size;
2206 /* Return the minimum size of window W, taking fixed-size windows into
2207 account. WIDTH_P non-zero means return the minimum width,
2208 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2209 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2210 unless FIXED is null. */
2212 static int
2213 window_min_size (w, width_p, ignore_fixed_p, fixed)
2214 struct window *w;
2215 int width_p, ignore_fixed_p, *fixed;
2217 int size, fixed_p;
2219 if (ignore_fixed_p)
2220 fixed_p = 0;
2221 else
2222 fixed_p = window_fixed_size_p (w, width_p, 1);
2224 if (fixed)
2225 *fixed = fixed_p;
2227 if (fixed_p)
2228 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2229 else
2230 size = window_min_size_1 (w, width_p);
2232 return size;
2236 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2237 WINDOW's width. Resize WINDOW's children, if any, so that they
2238 keep their proportionate size relative to WINDOW. Propagate
2239 WINDOW's top or left edge position to children. Delete windows
2240 that become too small unless NODELETE_P is non-zero. */
2242 static void
2243 size_window (window, size, width_p, nodelete_p)
2244 Lisp_Object window;
2245 int size, width_p, nodelete_p;
2247 struct window *w = XWINDOW (window);
2248 struct window *c;
2249 Lisp_Object child, *forward, *sideward;
2250 int old_size, min_size;
2252 check_min_window_sizes ();
2254 /* If the window has been "too small" at one point,
2255 don't delete it for being "too small" in the future.
2256 Preserve it as long as that is at all possible. */
2257 if (width_p)
2259 old_size = XFASTINT (w->width);
2260 min_size = window_min_width;
2262 else
2264 old_size = XFASTINT (w->height);
2265 min_size = window_min_height;
2268 if (old_size < window_min_width)
2269 w->too_small_ok = Qt;
2271 /* Maybe delete WINDOW if it's too small. */
2272 if (!nodelete_p && !NILP (w->parent))
2274 int min_size;
2276 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2277 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2278 else
2279 min_size = width_p ? window_min_width : window_min_height;
2281 if (size < min_size)
2283 delete_window (window);
2284 return;
2288 /* Set redisplay hints. */
2289 XSETFASTINT (w->last_modified, 0);
2290 XSETFASTINT (w->last_overlay_modified, 0);
2291 windows_or_buffers_changed++;
2292 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
2294 if (width_p)
2296 sideward = &w->vchild;
2297 forward = &w->hchild;
2298 XSETFASTINT (w->width, size);
2300 else
2302 sideward = &w->hchild;
2303 forward = &w->vchild;
2304 XSETFASTINT (w->height, size);
2307 if (!NILP (*sideward))
2309 for (child = *sideward; !NILP (child); child = c->next)
2311 c = XWINDOW (child);
2312 if (width_p)
2313 c->left = w->left;
2314 else
2315 c->top = w->top;
2316 size_window (child, size, width_p, nodelete_p);
2319 else if (!NILP (*forward))
2321 int fixed_size, each, extra, n;
2322 int resize_fixed_p, nfixed;
2323 int last_pos, first_pos, nchildren;
2325 /* Determine the fixed-size portion of the this window, and the
2326 number of child windows. */
2327 fixed_size = nchildren = nfixed = 0;
2328 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2330 c = XWINDOW (child);
2331 if (window_fixed_size_p (c, width_p, 0))
2333 fixed_size += (width_p
2334 ? XFASTINT (c->width) : XFASTINT (c->height));
2335 ++nfixed;
2339 /* If the new size is smaller than fixed_size, or if there
2340 aren't any resizable windows, allow resizing fixed-size
2341 windows. */
2342 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2344 /* Compute how many lines/columns to add to each child. The
2345 value of extra takes care of rounding errors. */
2346 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2347 each = (size - old_size) / n;
2348 extra = (size - old_size) - n * each;
2350 /* Compute new children heights and edge positions. */
2351 first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
2352 last_pos = first_pos;
2353 for (child = *forward; !NILP (child); child = c->next)
2355 int new_size, old_size;
2357 c = XWINDOW (child);
2358 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2359 new_size = old_size;
2361 /* The top or left edge position of this child equals the
2362 bottom or right edge of its predecessor. */
2363 if (width_p)
2364 c->left = make_number (last_pos);
2365 else
2366 c->top = make_number (last_pos);
2368 /* If this child can be resized, do it. */
2369 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2371 new_size = old_size + each + extra;
2372 extra = 0;
2375 /* Set new height. Note that size_window also propagates
2376 edge positions to children, so it's not a no-op if we
2377 didn't change the child's size. */
2378 size_window (child, new_size, width_p, 1);
2380 /* Remember the bottom/right edge position of this child; it
2381 will be used to set the top/left edge of the next child. */
2382 last_pos += new_size;
2385 /* We should have covered the parent exactly with child windows. */
2386 xassert (size == last_pos - first_pos);
2388 /* Now delete any children that became too small. */
2389 if (!nodelete_p)
2390 for (child = *forward; !NILP (child); child = c->next)
2392 int child_size;
2393 c = XWINDOW (child);
2394 child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2395 size_window (child, child_size, width_p, 0);
2400 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2401 WINDOW's children. NODELETE non-zero means don't delete windows
2402 that become too small in the process. (The caller should check
2403 later and do so if appropriate.) */
2405 void
2406 set_window_height (window, height, nodelete)
2407 Lisp_Object window;
2408 int height;
2409 int nodelete;
2411 size_window (window, height, 0, nodelete);
2415 /* Set WINDOW's width to WIDTH, and recursively change the width of
2416 WINDOW's children. NODELETE non-zero means don't delete windows
2417 that become too small in the process. (The caller should check
2418 later and do so if appropriate.) */
2420 void
2421 set_window_width (window, width, nodelete)
2422 Lisp_Object window;
2423 int width;
2424 int nodelete;
2426 size_window (window, width, 1, nodelete);
2430 int window_select_count;
2432 Lisp_Object
2433 Fset_window_buffer_unwind (obuf)
2434 Lisp_Object obuf;
2436 Fset_buffer (obuf);
2437 return Qnil;
2441 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2442 means it's allowed to run hooks. See make_frame for a case where
2443 it's not allowed. */
2445 void
2446 set_window_buffer (window, buffer, run_hooks_p)
2447 Lisp_Object window, buffer;
2448 int run_hooks_p;
2450 struct window *w = XWINDOW (window);
2451 struct buffer *b = XBUFFER (buffer);
2452 int count = specpdl_ptr - specpdl;
2454 w->buffer = buffer;
2456 if (EQ (window, selected_window))
2457 b->last_selected_window = window;
2459 /* Update time stamps of buffer display. */
2460 if (INTEGERP (b->display_count))
2461 XSETINT (b->display_count, XINT (b->display_count) + 1);
2462 b->display_time = Fcurrent_time ();
2464 XSETFASTINT (w->window_end_pos, 0);
2465 XSETFASTINT (w->window_end_vpos, 0);
2466 bzero (&w->last_cursor, sizeof w->last_cursor);
2467 w->window_end_valid = Qnil;
2468 XSETFASTINT (w->hscroll, 0);
2469 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2470 set_marker_restricted (w->start,
2471 make_number (b->last_window_start),
2472 buffer);
2473 w->start_at_line_beg = Qnil;
2474 w->force_start = Qnil;
2475 XSETFASTINT (w->last_modified, 0);
2476 XSETFASTINT (w->last_overlay_modified, 0);
2477 windows_or_buffers_changed++;
2479 /* We must select BUFFER for running the window-scroll-functions.
2480 If WINDOW is selected, switch permanently.
2481 Otherwise, switch but go back to the ambient buffer afterward. */
2482 if (EQ (window, selected_window))
2483 Fset_buffer (buffer);
2484 /* We can't check ! NILP (Vwindow_scroll_functions) here
2485 because that might itself be a local variable. */
2486 else if (window_initialized)
2488 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2489 Fset_buffer (buffer);
2492 /* Set left and right marginal area width from buffer. */
2493 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
2495 if (run_hooks_p)
2497 if (! NILP (Vwindow_scroll_functions))
2498 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2499 Fmarker_position (w->start));
2501 if (! NILP (Vwindow_configuration_change_hook)
2502 && ! NILP (Vrun_hooks))
2503 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2506 unbind_to (count, Qnil);
2510 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2511 "Make WINDOW display BUFFER as its contents.\n\
2512 BUFFER can be a buffer or buffer name.")
2513 (window, buffer)
2514 register Lisp_Object window, buffer;
2516 register Lisp_Object tem;
2517 register struct window *w = decode_window (window);
2519 XSETWINDOW (window, w);
2520 buffer = Fget_buffer (buffer);
2521 CHECK_BUFFER (buffer, 1);
2523 if (NILP (XBUFFER (buffer)->name))
2524 error ("Attempt to display deleted buffer");
2526 tem = w->buffer;
2527 if (NILP (tem))
2528 error ("Window is deleted");
2529 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2530 is first being set up. */
2532 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2533 error ("Window is dedicated to `%s'",
2534 XSTRING (XBUFFER (tem)->name)->data);
2536 unshow_buffer (w);
2539 set_window_buffer (window, buffer, 1);
2540 return Qnil;
2543 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2544 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
2545 If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2546 Note that the main editor command loop\n\
2547 selects the buffer of the selected window before each command.")
2548 (window)
2549 register Lisp_Object window;
2551 return select_window_1 (window, 1);
2554 /* Note that selected_window can be nil
2555 when this is called from Fset_window_configuration. */
2557 static Lisp_Object
2558 select_window_1 (window, recordflag)
2559 register Lisp_Object window;
2560 int recordflag;
2562 register struct window *w;
2563 register struct window *ow;
2564 struct frame *sf;
2566 CHECK_LIVE_WINDOW (window, 0);
2568 w = XWINDOW (window);
2570 if (NILP (w->buffer))
2571 error ("Trying to select deleted window or non-leaf window");
2573 XSETFASTINT (w->use_time, ++window_select_count);
2574 if (EQ (window, selected_window))
2575 return window;
2577 if (!NILP (selected_window))
2579 ow = XWINDOW (selected_window);
2580 if (! NILP (ow->buffer))
2581 set_marker_both (ow->pointm, ow->buffer,
2582 BUF_PT (XBUFFER (ow->buffer)),
2583 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2586 selected_window = window;
2587 sf = SELECTED_FRAME ();
2588 if (XFRAME (WINDOW_FRAME (w)) != sf)
2590 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2591 /* Use this rather than Fhandle_switch_frame
2592 so that FRAME_FOCUS_FRAME is moved appropriately as we
2593 move around in the state where a minibuffer in a separate
2594 frame is active. */
2595 Fselect_frame (WINDOW_FRAME (w), Qnil);
2597 else
2598 sf->selected_window = window;
2600 if (recordflag)
2601 record_buffer (w->buffer);
2602 Fset_buffer (w->buffer);
2604 XBUFFER (w->buffer)->last_selected_window = window;
2606 /* Go to the point recorded in the window.
2607 This is important when the buffer is in more
2608 than one window. It also matters when
2609 redisplay_window has altered point after scrolling,
2610 because it makes the change only in the window. */
2612 register int new_point = marker_position (w->pointm);
2613 if (new_point < BEGV)
2614 SET_PT (BEGV);
2615 else if (new_point > ZV)
2616 SET_PT (ZV);
2617 else
2618 SET_PT (new_point);
2621 windows_or_buffers_changed++;
2622 return window;
2625 /* Deiconify the frame containing the window WINDOW,
2626 unless it is the selected frame;
2627 then return WINDOW.
2629 The reason for the exception for the selected frame
2630 is that it seems better not to change the selected frames visibility
2631 merely because of displaying a different buffer in it.
2632 The deiconification is useful when a buffer gets shown in
2633 another frame that you were not using lately. */
2635 static Lisp_Object
2636 display_buffer_1 (window)
2637 Lisp_Object window;
2639 Lisp_Object frame = XWINDOW (window)->frame;
2640 FRAME_PTR f = XFRAME (frame);
2642 FRAME_SAMPLE_VISIBILITY (f);
2644 if (!EQ (frame, selected_frame))
2646 if (FRAME_ICONIFIED_P (f))
2647 Fmake_frame_visible (frame);
2648 else if (FRAME_VISIBLE_P (f))
2649 Fraise_frame (frame);
2652 return window;
2655 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2656 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2657 The value is actually t if the frame should be called with default frame\n\
2658 parameters, and a list of frame parameters if they were specified.\n\
2659 See `special-display-buffer-names', and `special-display-regexps'.")
2660 (buffer_name)
2661 Lisp_Object buffer_name;
2663 Lisp_Object tem;
2665 CHECK_STRING (buffer_name, 1);
2667 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2668 if (!NILP (tem))
2669 return Qt;
2671 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2672 if (!NILP (tem))
2673 return XCDR (tem);
2675 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2677 Lisp_Object car = XCAR (tem);
2678 if (STRINGP (car)
2679 && fast_string_match (car, buffer_name) >= 0)
2680 return Qt;
2681 else if (CONSP (car)
2682 && STRINGP (XCAR (car))
2683 && fast_string_match (XCAR (car), buffer_name) >= 0)
2684 return XCDR (car);
2686 return Qnil;
2689 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2690 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
2691 See `same-window-buffer-names' and `same-window-regexps'.")
2692 (buffer_name)
2693 Lisp_Object buffer_name;
2695 Lisp_Object tem;
2697 CHECK_STRING (buffer_name, 1);
2699 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2700 if (!NILP (tem))
2701 return Qt;
2703 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2704 if (!NILP (tem))
2705 return Qt;
2707 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2709 Lisp_Object car = XCAR (tem);
2710 if (STRINGP (car)
2711 && fast_string_match (car, buffer_name) >= 0)
2712 return Qt;
2713 else if (CONSP (car)
2714 && STRINGP (XCAR (car))
2715 && fast_string_match (XCAR (car), buffer_name) >= 0)
2716 return Qt;
2718 return Qnil;
2721 /* Use B so the default is (other-buffer). */
2722 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2723 "BDisplay buffer: \nP",
2724 "Make BUFFER appear in some window but don't select it.\n\
2725 BUFFER can be a buffer or a buffer name.\n\
2726 If BUFFER is shown already in some window, just use that one,\n\
2727 unless the window is the selected window and the optional second\n\
2728 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
2729 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
2730 Returns the window displaying BUFFER.\n\
2731 If `display-reuse-frames' is non-nil, and another frame is currently\n\
2732 displaying BUFFER, then simply raise that frame.\n\
2734 The variables `special-display-buffer-names', `special-display-regexps',\n\
2735 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
2736 buffer names are handled.\n\
2738 If optional argument FRAME is `visible', search all visible frames.\n\
2739 If FRAME is 0, search all visible and iconified frames.\n\
2740 If FRAME is t, search all frames.\n\
2741 If FRAME is a frame, search only that frame.\n\
2742 If FRAME is nil, search only the selected frame\n\
2743 (actually the last nonminibuffer frame),\n\
2744 unless `pop-up-frames' or `display-reuse-frames' is non-nil,\n\
2745 which means search visible and iconified frames.")
2746 (buffer, not_this_window, frame)
2747 register Lisp_Object buffer, not_this_window, frame;
2749 register Lisp_Object window, tem, swp;
2750 struct frame *f;
2752 swp = Qnil;
2753 buffer = Fget_buffer (buffer);
2754 CHECK_BUFFER (buffer, 0);
2756 if (!NILP (Vdisplay_buffer_function))
2757 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2759 if (NILP (not_this_window)
2760 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
2761 return display_buffer_1 (selected_window);
2763 /* See if the user has specified this buffer should appear
2764 in the selected window. */
2765 if (NILP (not_this_window))
2767 swp = Fsame_window_p (XBUFFER (buffer)->name);
2768 if (!NILP (swp) && !no_switch_window (selected_window))
2770 Fswitch_to_buffer (buffer, Qnil);
2771 return display_buffer_1 (selected_window);
2775 /* If the user wants pop-up-frames or display-reuse-frames, then
2776 look for a window showing BUFFER on any visible or iconified frame.
2777 Otherwise search only the current frame. */
2778 if (! NILP (frame))
2779 tem = frame;
2780 else if (pop_up_frames
2781 || display_buffer_reuse_frames
2782 || last_nonminibuf_frame == 0)
2783 XSETFASTINT (tem, 0);
2784 else
2785 XSETFRAME (tem, last_nonminibuf_frame);
2787 window = Fget_buffer_window (buffer, tem);
2788 if (!NILP (window)
2789 && (NILP (not_this_window) || !EQ (window, selected_window)))
2790 return display_buffer_1 (window);
2792 /* Certain buffer names get special handling. */
2793 if (!NILP (Vspecial_display_function) && NILP (swp))
2795 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2796 if (EQ (tem, Qt))
2797 return call1 (Vspecial_display_function, buffer);
2798 if (CONSP (tem))
2799 return call2 (Vspecial_display_function, buffer, tem);
2802 /* If there are no frames open that have more than a minibuffer,
2803 we need to create a new frame. */
2804 if (pop_up_frames || last_nonminibuf_frame == 0)
2806 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2807 Fset_window_buffer (window, buffer);
2808 return display_buffer_1 (window);
2811 f = SELECTED_FRAME ();
2812 if (pop_up_windows
2813 || FRAME_MINIBUF_ONLY_P (f)
2814 /* If the current frame is a special display frame,
2815 don't try to reuse its windows. */
2816 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
2818 Lisp_Object frames;
2820 frames = Qnil;
2821 if (FRAME_MINIBUF_ONLY_P (f))
2822 XSETFRAME (frames, last_nonminibuf_frame);
2823 /* Don't try to create a window if would get an error */
2824 if (split_height_threshold < window_min_height << 1)
2825 split_height_threshold = window_min_height << 1;
2827 /* Note that both Fget_largest_window and Fget_lru_window
2828 ignore minibuffers and dedicated windows.
2829 This means they can return nil. */
2831 /* If the frame we would try to split cannot be split,
2832 try other frames. */
2833 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
2835 /* Try visible frames first. */
2836 window = Fget_largest_window (Qvisible);
2837 /* If that didn't work, try iconified frames. */
2838 if (NILP (window))
2839 window = Fget_largest_window (make_number (0));
2840 if (NILP (window))
2841 window = Fget_largest_window (Qt);
2843 else
2844 window = Fget_largest_window (frames);
2846 /* If we got a tall enough full-width window that can be split,
2847 split it. */
2848 if (!NILP (window)
2849 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2850 && window_height (window) >= split_height_threshold
2851 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
2852 window = Fsplit_window (window, Qnil, Qnil);
2853 else
2855 Lisp_Object upper, lower, other;
2857 window = Fget_lru_window (frames);
2858 /* If the LRU window is selected, and big enough,
2859 and can be split, split it. */
2860 if (!NILP (window)
2861 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2862 && (EQ (window, selected_window)
2863 || EQ (XWINDOW (window)->parent, Qnil))
2864 && window_height (window) >= window_min_height << 1)
2865 window = Fsplit_window (window, Qnil, Qnil);
2866 /* If Fget_lru_window returned nil, try other approaches. */
2868 /* Try visible frames first. */
2869 if (NILP (window))
2870 window = Fget_buffer_window (buffer, Qvisible);
2871 if (NILP (window))
2872 window = Fget_largest_window (Qvisible);
2873 /* If that didn't work, try iconified frames. */
2874 if (NILP (window))
2875 window = Fget_buffer_window (buffer, make_number (0));
2876 if (NILP (window))
2877 window = Fget_largest_window (make_number (0));
2878 /* Try invisible frames. */
2879 if (NILP (window))
2880 window = Fget_buffer_window (buffer, Qt);
2881 if (NILP (window))
2882 window = Fget_largest_window (Qt);
2883 /* As a last resort, make a new frame. */
2884 if (NILP (window))
2885 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2886 /* If window appears above or below another,
2887 even out their heights. */
2888 other = upper = lower = Qnil;
2889 if (!NILP (XWINDOW (window)->prev))
2890 other = upper = XWINDOW (window)->prev, lower = window;
2891 if (!NILP (XWINDOW (window)->next))
2892 other = lower = XWINDOW (window)->next, upper = window;
2893 if (!NILP (other)
2894 /* Check that OTHER and WINDOW are vertically arrayed. */
2895 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2896 && (XFASTINT (XWINDOW (other)->height)
2897 > XFASTINT (XWINDOW (window)->height)))
2899 int total = (XFASTINT (XWINDOW (other)->height)
2900 + XFASTINT (XWINDOW (window)->height));
2901 enlarge_window (upper,
2902 total / 2 - XFASTINT (XWINDOW (upper)->height),
2907 else
2908 window = Fget_lru_window (Qnil);
2910 Fset_window_buffer (window, buffer);
2911 return display_buffer_1 (window);
2914 void
2915 temp_output_buffer_show (buf)
2916 register Lisp_Object buf;
2918 register struct buffer *old = current_buffer;
2919 register Lisp_Object window;
2920 register struct window *w;
2922 XBUFFER (buf)->directory = current_buffer->directory;
2924 Fset_buffer (buf);
2925 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
2926 BEGV = BEG;
2927 ZV = Z;
2928 SET_PT (BEG);
2929 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
2930 set_buffer_internal (old);
2932 if (!EQ (Vtemp_buffer_show_function, Qnil))
2933 call1 (Vtemp_buffer_show_function, buf);
2934 else
2936 window = Fdisplay_buffer (buf, Qnil, Qnil);
2938 if (!EQ (XWINDOW (window)->frame, selected_frame))
2939 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2940 Vminibuf_scroll_window = window;
2941 w = XWINDOW (window);
2942 XSETFASTINT (w->hscroll, 0);
2943 set_marker_restricted_both (w->start, buf, 1, 1);
2944 set_marker_restricted_both (w->pointm, buf, 1, 1);
2946 /* Run temp-buffer-show-hook, with the chosen window selected
2947 and it sbuffer current. */
2948 if (!NILP (Vrun_hooks))
2950 Lisp_Object tem;
2951 tem = Fboundp (Qtemp_buffer_show_hook);
2952 if (!NILP (tem))
2954 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2955 if (!NILP (tem))
2957 int count = specpdl_ptr - specpdl;
2958 Lisp_Object prev_window;
2959 prev_window = selected_window;
2961 /* Select the window that was chosen, for running the hook. */
2962 record_unwind_protect (Fselect_window, prev_window);
2963 select_window_1 (window, 0);
2964 Fset_buffer (w->buffer);
2965 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2966 select_window_1 (prev_window, 0);
2967 unbind_to (count, Qnil);
2974 static void
2975 make_dummy_parent (window)
2976 Lisp_Object window;
2978 Lisp_Object new;
2979 register struct window *o, *p;
2980 register struct Lisp_Vector *vec;
2981 int i;
2983 o = XWINDOW (window);
2984 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2985 for (i = 0; i < VECSIZE (struct window); ++i)
2986 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2987 vec->size = VECSIZE (struct window);
2988 p = (struct window *)vec;
2989 XSETWINDOW (new, p);
2991 XSETFASTINT (p->sequence_number, ++sequence_number);
2993 /* Put new into window structure in place of window */
2994 replace_window (window, new);
2996 o->next = Qnil;
2997 o->prev = Qnil;
2998 o->vchild = Qnil;
2999 o->hchild = Qnil;
3000 o->parent = new;
3002 p->start = Qnil;
3003 p->pointm = Qnil;
3004 p->buffer = Qnil;
3007 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3008 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
3009 WINDOW defaults to selected one and SIZE to half its size.\n\
3010 If optional third arg HORFLAG is non-nil, split side by side\n\
3011 and put SIZE columns in the first of the pair. In that case,\n\
3012 SIZE includes that window's scroll bar, or the divider column to its right.")
3013 (window, size, horflag)
3014 Lisp_Object window, size, horflag;
3016 register Lisp_Object new;
3017 register struct window *o, *p;
3018 FRAME_PTR fo;
3019 register int size_int;
3021 if (NILP (window))
3022 window = selected_window;
3023 else
3024 CHECK_LIVE_WINDOW (window, 0);
3026 o = XWINDOW (window);
3027 fo = XFRAME (WINDOW_FRAME (o));
3029 if (NILP (size))
3031 if (!NILP (horflag))
3032 /* Calculate the size of the left-hand window, by dividing
3033 the usable space in columns by two.
3034 We round up, since the left-hand window may include
3035 a dividing line, while the right-hand may not. */
3036 size_int = (XFASTINT (o->width) + 1) >> 1;
3037 else
3038 size_int = XFASTINT (o->height) >> 1;
3040 else
3042 CHECK_NUMBER (size, 1);
3043 size_int = XINT (size);
3046 if (MINI_WINDOW_P (o))
3047 error ("Attempt to split minibuffer window");
3048 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3049 error ("Attempt to split fixed-size window");
3051 check_min_window_sizes ();
3053 if (NILP (horflag))
3055 if (size_int < window_min_height)
3056 error ("Window height %d too small (after splitting)", size_int);
3057 if (size_int + window_min_height > XFASTINT (o->height))
3058 error ("Window height %d too small (after splitting)",
3059 XFASTINT (o->height) - size_int);
3060 if (NILP (o->parent)
3061 || NILP (XWINDOW (o->parent)->vchild))
3063 make_dummy_parent (window);
3064 new = o->parent;
3065 XWINDOW (new)->vchild = window;
3068 else
3070 if (size_int < window_min_width)
3071 error ("Window width %d too small (after splitting)", size_int);
3073 if (size_int + window_min_width > XFASTINT (o->width))
3074 error ("Window width %d too small (after splitting)",
3075 XFASTINT (o->width) - size_int);
3076 if (NILP (o->parent)
3077 || NILP (XWINDOW (o->parent)->hchild))
3079 make_dummy_parent (window);
3080 new = o->parent;
3081 XWINDOW (new)->hchild = window;
3085 /* Now we know that window's parent is a vertical combination
3086 if we are dividing vertically, or a horizontal combination
3087 if we are making side-by-side windows */
3089 windows_or_buffers_changed++;
3090 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3091 new = make_window ();
3092 p = XWINDOW (new);
3094 p->frame = o->frame;
3095 p->next = o->next;
3096 if (!NILP (p->next))
3097 XWINDOW (p->next)->prev = new;
3098 p->prev = window;
3099 o->next = new;
3100 p->parent = o->parent;
3101 p->buffer = Qt;
3102 p->window_end_valid = Qnil;
3103 bzero (&p->last_cursor, sizeof p->last_cursor);
3105 /* Apportion the available frame space among the two new windows */
3107 if (!NILP (horflag))
3109 p->height = o->height;
3110 p->top = o->top;
3111 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
3112 XSETFASTINT (o->width, size_int);
3113 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
3115 else
3117 p->left = o->left;
3118 p->width = o->width;
3119 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3120 XSETFASTINT (o->height, size_int);
3121 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
3124 /* Adjust glyph matrices. */
3125 adjust_glyphs (fo);
3126 Fset_window_buffer (new, o->buffer);
3127 return new;
3130 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3131 "Make current window ARG lines bigger.\n\
3132 From program, optional second arg non-nil means grow sideways ARG columns.")
3133 (arg, side)
3134 register Lisp_Object arg, side;
3136 CHECK_NUMBER (arg, 0);
3137 enlarge_window (selected_window, XINT (arg), !NILP (side));
3139 if (! NILP (Vwindow_configuration_change_hook))
3140 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3142 return Qnil;
3145 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3146 "Make current window ARG lines smaller.\n\
3147 From program, optional second arg non-nil means shrink sideways arg columns.")
3148 (arg, side)
3149 register Lisp_Object arg, side;
3151 CHECK_NUMBER (arg, 0);
3152 enlarge_window (selected_window, -XINT (arg), !NILP (side));
3154 if (! NILP (Vwindow_configuration_change_hook))
3155 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3157 return Qnil;
3161 window_height (window)
3162 Lisp_Object window;
3164 register struct window *p = XWINDOW (window);
3165 return XFASTINT (p->height);
3169 window_width (window)
3170 Lisp_Object window;
3172 register struct window *p = XWINDOW (window);
3173 return XFASTINT (p->width);
3177 #define CURBEG(w) \
3178 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3180 #define CURSIZE(w) \
3181 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3184 /* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3185 increase its width. Siblings of the selected window are resized to
3186 fullfil the size request. If they become too small in the process,
3187 they will be deleted. */
3189 static void
3190 enlarge_window (window, delta, widthflag)
3191 Lisp_Object window;
3192 int delta, widthflag;
3194 Lisp_Object parent, next, prev;
3195 struct window *p;
3196 Lisp_Object *sizep;
3197 int maximum;
3198 int (*sizefun) P_ ((Lisp_Object))
3199 = widthflag ? window_width : window_height;
3200 void (*setsizefun) P_ ((Lisp_Object, int, int))
3201 = (widthflag ? set_window_width : set_window_height);
3203 /* Check values of window_min_width and window_min_height for
3204 validity. */
3205 check_min_window_sizes ();
3207 /* Give up if this window cannot be resized. */
3208 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3209 error ("Window is not resizable");
3211 /* Find the parent of the selected window. */
3212 while (1)
3214 p = XWINDOW (window);
3215 parent = p->parent;
3217 if (NILP (parent))
3219 if (widthflag)
3220 error ("No other window to side of this one");
3221 break;
3224 if (widthflag
3225 ? !NILP (XWINDOW (parent)->hchild)
3226 : !NILP (XWINDOW (parent)->vchild))
3227 break;
3229 window = parent;
3232 sizep = &CURSIZE (window);
3235 register int maxdelta;
3237 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3238 : !NILP (p->next) ? ((*sizefun) (p->next)
3239 - window_min_size (XWINDOW (p->next),
3240 widthflag, 0, 0))
3241 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3242 - window_min_size (XWINDOW (p->prev),
3243 widthflag, 0, 0))
3244 /* This is a frame with only one window, a minibuffer-only
3245 or a minibufferless frame. */
3246 : (delta = 0));
3248 if (delta > maxdelta)
3249 /* This case traps trying to make the minibuffer
3250 the full frame, or make the only window aside from the
3251 minibuffer the full frame. */
3252 delta = maxdelta;
3255 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3257 delete_window (window);
3258 return;
3261 if (delta == 0)
3262 return;
3264 /* Find the total we can get from other siblings. */
3265 maximum = 0;
3266 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3267 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3268 widthflag, 0, 0);
3269 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3270 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3271 widthflag, 0, 0);
3273 /* If we can get it all from them, do so. */
3274 if (delta <= maximum)
3276 Lisp_Object first_unaffected;
3277 Lisp_Object first_affected;
3278 int fixed_p;
3280 next = p->next;
3281 prev = p->prev;
3282 first_affected = window;
3283 /* Look at one sibling at a time,
3284 moving away from this window in both directions alternately,
3285 and take as much as we can get without deleting that sibling. */
3286 while (delta != 0 && (!NILP (next) || !NILP (prev)))
3288 if (! NILP (next))
3290 int this_one = ((*sizefun) (next)
3291 - window_min_size (XWINDOW (next),
3292 widthflag, 0, &fixed_p));
3293 if (!fixed_p)
3295 if (this_one > delta)
3296 this_one = delta;
3298 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3299 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3301 delta -= this_one;
3304 next = XWINDOW (next)->next;
3307 if (delta == 0)
3308 break;
3310 if (! NILP (prev))
3312 int this_one = ((*sizefun) (prev)
3313 - window_min_size (XWINDOW (prev),
3314 widthflag, 0, &fixed_p));
3315 if (!fixed_p)
3317 if (this_one > delta)
3318 this_one = delta;
3320 first_affected = prev;
3322 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3323 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3325 delta -= this_one;
3328 prev = XWINDOW (prev)->prev;
3332 xassert (delta == 0);
3334 /* Now recalculate the edge positions of all the windows affected,
3335 based on the new sizes. */
3336 first_unaffected = next;
3337 prev = first_affected;
3338 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3339 prev = next, next = XWINDOW (next)->next)
3341 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3342 /* This does not change size of NEXT,
3343 but it propagates the new top edge to its children */
3344 (*setsizefun) (next, (*sizefun) (next), 0);
3347 else
3349 register int delta1;
3350 register int opht = (*sizefun) (parent);
3352 /* If trying to grow this window to or beyond size of the parent,
3353 make delta1 so big that, on shrinking back down,
3354 all the siblings end up with less than one line and are deleted. */
3355 if (opht <= XINT (*sizep) + delta)
3356 delta1 = opht * opht * 2;
3357 else
3359 /* Otherwise, make delta1 just right so that if we add
3360 delta1 lines to this window and to the parent, and then
3361 shrink the parent back to its original size, the new
3362 proportional size of this window will increase by delta.
3364 The function size_window will compute the new height h'
3365 of the window from delta1 as:
3367 e = delta1/n
3368 x = delta1 - delta1/n * n for the 1st resizable child
3369 h' = h + e + x
3371 where n is the number of children that can be resized.
3372 We can ignore x by choosing a delta1 that is a multiple of
3373 n. We want the height of this window to come out as
3375 h' = h + delta
3377 So, delta1 must be
3379 h + e = h + delta
3380 delta1/n = delta
3381 delta1 = n * delta.
3383 The number of children n rquals the number of resizable
3384 children of this window + 1 because we know window itself
3385 is resizable (otherwise we would have signalled an error. */
3387 struct window *w = XWINDOW (window);
3388 Lisp_Object s;
3389 int n = 1;
3391 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3392 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3393 ++n;
3394 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3395 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3396 ++n;
3398 delta1 = n * delta;
3401 /* Add delta1 lines or columns to this window, and to the parent,
3402 keeping things consistent while not affecting siblings. */
3403 XSETINT (CURSIZE (parent), opht + delta1);
3404 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3406 /* Squeeze out delta1 lines or columns from our parent,
3407 shriking this window and siblings proportionately.
3408 This brings parent back to correct size.
3409 Delta1 was calculated so this makes this window the desired size,
3410 taking it all out of the siblings. */
3411 (*setsizefun) (parent, opht, 0);
3414 XSETFASTINT (p->last_modified, 0);
3415 XSETFASTINT (p->last_overlay_modified, 0);
3417 /* Adjust glyph matrices. */
3418 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3421 #undef CURBEG
3422 #undef CURSIZE
3426 /***********************************************************************
3427 Resizing Mini-Windows
3428 ***********************************************************************/
3430 static void shrink_window_lowest_first P_ ((struct window *, int));
3432 enum save_restore_action
3434 CHECK_ORIG_SIZES,
3435 SAVE_ORIG_SIZES,
3436 RESTORE_ORIG_SIZES
3439 static int save_restore_orig_size P_ ((struct window *,
3440 enum save_restore_action));
3442 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3443 from lowest windows first. */
3445 static void
3446 shrink_window_lowest_first (w, height)
3447 struct window *w;
3448 int height;
3450 struct window *c;
3451 Lisp_Object child;
3452 int old_height;
3454 xassert (!MINI_WINDOW_P (w));
3456 /* Set redisplay hints. */
3457 XSETFASTINT (w->last_modified, 0);
3458 XSETFASTINT (w->last_overlay_modified, 0);
3459 windows_or_buffers_changed++;
3460 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3462 old_height = XFASTINT (w->height);
3463 XSETFASTINT (w->height, height);
3465 if (!NILP (w->hchild))
3467 for (child = w->hchild; !NILP (child); child = c->next)
3469 c = XWINDOW (child);
3470 c->top = w->top;
3471 shrink_window_lowest_first (c, height);
3474 else if (!NILP (w->vchild))
3476 Lisp_Object last_child;
3477 int delta = old_height - height;
3478 int last_top;
3480 /* Find the last child. We are taking space from lowest windows
3481 first, so we iterate over children from the last child
3482 backwards. */
3483 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3484 last_child = child;
3486 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3487 for (child = last_child; delta && !NILP (child); child = c->prev)
3489 int this_one;
3491 c = XWINDOW (child);
3492 this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
3494 if (this_one > delta)
3495 this_one = delta;
3497 shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
3498 delta -= this_one;
3501 /* Compute new positions. */
3502 last_top = XINT (w->top);
3503 for (child = w->vchild; !NILP (child); child = c->next)
3505 c = XWINDOW (child);
3506 c->top = make_number (last_top);
3507 shrink_window_lowest_first (c, XFASTINT (c->height));
3508 last_top += XFASTINT (c->height);
3514 /* Save, restore, or check positions and sizes in the window tree
3515 rooted at W. ACTION says what to do.
3517 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3518 members are valid for all windows in the window tree. Value is
3519 non-zero if they are valid.
3521 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3522 orig_top and orig_height for all windows in the tree.
3524 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3525 values stored in orig_top and orig_height for all windows. */
3527 static int
3528 save_restore_orig_size (w, action)
3529 struct window *w;
3530 enum save_restore_action action;
3532 int success_p = 1;
3534 while (w)
3536 if (!NILP (w->hchild))
3538 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
3539 success_p = 0;
3541 else if (!NILP (w->vchild))
3543 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
3544 success_p = 0;
3547 switch (action)
3549 case CHECK_ORIG_SIZES:
3550 if (!INTEGERP (w->orig_top) || !INTEGERP (w->orig_height))
3551 return 0;
3552 break;
3554 case SAVE_ORIG_SIZES:
3555 w->orig_top = w->top;
3556 w->orig_height = w->height;
3557 XSETFASTINT (w->last_modified, 0);
3558 XSETFASTINT (w->last_overlay_modified, 0);
3559 break;
3561 case RESTORE_ORIG_SIZES:
3562 xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
3563 w->top = w->orig_top;
3564 w->height = w->orig_height;
3565 w->orig_height = w->orig_top = Qnil;
3566 XSETFASTINT (w->last_modified, 0);
3567 XSETFASTINT (w->last_overlay_modified, 0);
3568 break;
3570 default:
3571 abort ();
3574 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3577 return success_p;
3581 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3582 without deleting other windows. */
3584 void
3585 grow_mini_window (w, delta)
3586 struct window *w;
3587 int delta;
3589 struct frame *f = XFRAME (w->frame);
3590 struct window *root;
3592 xassert (MINI_WINDOW_P (w));
3593 xassert (delta >= 0);
3595 /* Check values of window_min_width and window_min_height for
3596 validity. */
3597 check_min_window_sizes ();
3599 /* Compute how much we can enlarge the mini-window without deleting
3600 other windows. */
3601 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3602 if (delta)
3604 int min_height = window_min_size (root, 0, 0, 0);
3605 if (XFASTINT (root->height) - delta < min_height)
3606 delta = XFASTINT (root->height) - min_height;
3609 if (delta)
3611 /* Save original window sizes and positions, if not already done. */
3612 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
3613 save_restore_orig_size (root, SAVE_ORIG_SIZES);
3615 /* Shrink other windows. */
3616 shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
3618 /* Grow the mini-window. */
3619 w->top = make_number (XFASTINT (root->top) + XFASTINT (root->height));
3620 w->height = make_number (XFASTINT (w->height) + delta);
3621 XSETFASTINT (w->last_modified, 0);
3622 XSETFASTINT (w->last_overlay_modified, 0);
3624 adjust_glyphs (f);
3629 /* Shrink mini-window W. If there is recorded info about window sizes
3630 before a call to grow_mini_window, restore recorded window sizes.
3631 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3632 line. */
3634 void
3635 shrink_mini_window (w)
3636 struct window *w;
3638 struct frame *f = XFRAME (w->frame);
3639 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
3641 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
3643 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
3644 adjust_glyphs (f);
3645 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3646 windows_or_buffers_changed = 1;
3648 else if (XFASTINT (w->height) > 1)
3650 Lisp_Object window;
3651 XSETWINDOW (window, w);
3652 enlarge_window (window, 1 - XFASTINT (w->height), 0);
3658 /* Mark window cursors off for all windows in the window tree rooted
3659 at W by setting their phys_cursor_on_p flag to zero. Called from
3660 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3661 the frame are cleared. */
3663 void
3664 mark_window_cursors_off (w)
3665 struct window *w;
3667 while (w)
3669 if (!NILP (w->hchild))
3670 mark_window_cursors_off (XWINDOW (w->hchild));
3671 else if (!NILP (w->vchild))
3672 mark_window_cursors_off (XWINDOW (w->vchild));
3673 else
3674 w->phys_cursor_on_p = 0;
3676 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3681 /* Return number of lines of text (not counting mode line) in W. */
3684 window_internal_height (w)
3685 struct window *w;
3687 int ht = XFASTINT (w->height);
3689 if (MINI_WINDOW_P (w))
3690 return ht;
3692 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
3693 || !NILP (w->next) || !NILP (w->prev)
3694 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
3695 return ht - 1;
3697 return ht;
3701 /* Return the number of columns in W.
3702 Don't count columns occupied by scroll bars or the vertical bar
3703 separating W from the sibling to its right. */
3706 window_internal_width (w)
3707 struct window *w;
3709 struct frame *f = XFRAME (WINDOW_FRAME (w));
3710 int width = XINT (w->width);
3712 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3713 /* Scroll bars occupy a few columns. */
3714 width -= FRAME_SCROLL_BAR_COLS (f);
3715 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3716 /* The column of `|' characters separating side-by-side windows
3717 occupies one column only. */
3718 width -= 1;
3720 /* On window-systems, areas to the left and right of the window
3721 are used to display bitmaps there. */
3722 if (FRAME_WINDOW_P (f))
3723 width -= FRAME_FLAGS_AREA_COLS (f);
3725 return width;
3729 /************************************************************************
3730 Window Scrolling
3731 ***********************************************************************/
3733 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3734 one screen-full, which is defined as the height of the window minus
3735 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3736 instead. Negative values of N mean scroll down. NOERROR non-zero
3737 means don't signal an error if we try to move over BEGV or ZV,
3738 respectively. */
3740 static void
3741 window_scroll (window, n, whole, noerror)
3742 Lisp_Object window;
3743 int n;
3744 int whole;
3745 int noerror;
3747 /* If we must, use the pixel-based version which is much slower than
3748 the line-based one but can handle varying line heights. */
3749 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
3750 window_scroll_pixel_based (window, n, whole, noerror);
3751 else
3752 window_scroll_line_based (window, n, whole, noerror);
3756 /* Implementation of window_scroll that works based on pixel line
3757 heights. See the comment of window_scroll for parameter
3758 descriptions. */
3760 static void
3761 window_scroll_pixel_based (window, n, whole, noerror)
3762 Lisp_Object window;
3763 int n;
3764 int whole;
3765 int noerror;
3767 struct it it;
3768 struct window *w = XWINDOW (window);
3769 struct text_pos start;
3770 Lisp_Object tem;
3771 int this_scroll_margin;
3772 int preserve_y;
3774 SET_TEXT_POS_FROM_MARKER (start, w->start);
3776 /* If PT is not visible in WINDOW, move back one half of
3777 the screen. */
3778 XSETFASTINT (tem, PT);
3779 tem = Fpos_visible_in_window_p (tem, window);
3780 if (NILP (tem))
3782 /* Move backward half the height of the window. Performance note:
3783 vmotion used here is about 10% faster, but would give wrong
3784 results for variable height lines. */
3785 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3786 it.current_y = it.last_visible_y;
3787 move_it_vertically (&it, -it.last_visible_y / 2);
3789 /* The function move_iterator_vertically may move over more than
3790 the specified y-distance. If it->w is small, e.g. a
3791 mini-buffer window, we may end up in front of the window's
3792 display area. This is the case when Start displaying at the
3793 start of the line containing PT in this case. */
3794 if (it.current_y <= 0)
3796 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3797 move_it_vertically (&it, 0);
3798 it.current_y = 0;
3801 start = it.current.pos;
3804 /* If scroll_preserve_screen_position is non-zero, we try to set
3805 point in the same window line as it is now, so get that line. */
3806 if (!NILP (Vscroll_preserve_screen_position))
3808 start_display (&it, w, start);
3809 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3810 preserve_y = it.current_y;
3812 else
3813 preserve_y = -1;
3815 /* Move iterator it from start the specified distance forward or
3816 backward. The result is the new window start. */
3817 start_display (&it, w, start);
3818 if (whole)
3820 int screen_full = (it.last_visible_y
3821 - next_screen_context_lines * CANON_Y_UNIT (it.f));
3822 int direction = n < 0 ? -1 : 1;
3823 move_it_vertically (&it, direction * screen_full);
3825 else
3826 move_it_by_lines (&it, n, 1);
3828 /* End if we end up at ZV or BEGV. */
3829 if ((n > 0 && IT_CHARPOS (it) == ZV)
3830 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
3832 if (noerror)
3833 return;
3834 else if (IT_CHARPOS (it) == ZV)
3835 Fsignal (Qend_of_buffer, Qnil);
3836 else
3837 Fsignal (Qbeginning_of_buffer, Qnil);
3840 /* Set the window start, and set up the window for redisplay. */
3841 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)), w->buffer);
3842 w->start_at_line_beg = Fbolp ();
3843 w->update_mode_line = Qt;
3844 XSETFASTINT (w->last_modified, 0);
3845 XSETFASTINT (w->last_overlay_modified, 0);
3846 /* Set force_start so that redisplay_window will run the
3847 window-scroll-functions. */
3848 w->force_start = Qt;
3850 it.current_y = it.vpos = 0;
3852 /* Preserve the screen position if we must. */
3853 if (preserve_y >= 0)
3855 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
3856 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3858 else
3860 /* Move PT out of scroll margins. */
3861 this_scroll_margin = max (0, scroll_margin);
3862 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
3863 this_scroll_margin *= CANON_Y_UNIT (it.f);
3865 if (n > 0)
3867 /* We moved the window start towards ZV, so PT may be now
3868 in the scroll margin at the top. */
3869 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3870 while (it.current_y < this_scroll_margin)
3871 move_it_by_lines (&it, 1, 1);
3872 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3874 else if (n < 0)
3876 /* We moved the window start towards BEGV, so PT may be now
3877 in the scroll margin at the bottom. */
3878 move_it_to (&it, PT, -1,
3879 it.last_visible_y - this_scroll_margin - 1, -1,
3880 MOVE_TO_POS | MOVE_TO_Y);
3882 /* Don't put point on a partially visible line at the end. */
3883 if (it.current_y + it.max_ascent + it.max_descent
3884 > it.last_visible_y)
3885 move_it_by_lines (&it, -1, 0);
3887 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3893 /* Implementation of window_scroll that works based on screen lines.
3894 See the comment of window_scroll for parameter descriptions. */
3896 static void
3897 window_scroll_line_based (window, n, whole, noerror)
3898 Lisp_Object window;
3899 int n;
3900 int whole;
3901 int noerror;
3903 register struct window *w = XWINDOW (window);
3904 register int opoint = PT, opoint_byte = PT_BYTE;
3905 register int pos, pos_byte;
3906 register int ht = window_internal_height (w);
3907 register Lisp_Object tem;
3908 int lose;
3909 Lisp_Object bolp;
3910 int startpos;
3911 struct position posit;
3912 int original_vpos;
3914 startpos = marker_position (w->start);
3916 posit = *compute_motion (startpos, 0, 0, 0,
3917 PT, ht, 0,
3918 window_internal_width (w), XINT (w->hscroll),
3919 0, w);
3920 original_vpos = posit.vpos;
3922 XSETFASTINT (tem, PT);
3923 tem = Fpos_visible_in_window_p (tem, window);
3925 if (NILP (tem))
3927 Fvertical_motion (make_number (- (ht / 2)), window);
3928 startpos = PT;
3931 SET_PT (startpos);
3932 lose = n < 0 && PT == BEGV;
3933 Fvertical_motion (make_number (n), window);
3934 pos = PT;
3935 pos_byte = PT_BYTE;
3936 bolp = Fbolp ();
3937 SET_PT_BOTH (opoint, opoint_byte);
3939 if (lose)
3941 if (noerror)
3942 return;
3943 else
3944 Fsignal (Qbeginning_of_buffer, Qnil);
3947 if (pos < ZV)
3949 int this_scroll_margin = scroll_margin;
3951 /* Don't use a scroll margin that is negative or too large. */
3952 if (this_scroll_margin < 0)
3953 this_scroll_margin = 0;
3955 if (XINT (w->height) < 4 * scroll_margin)
3956 this_scroll_margin = XINT (w->height) / 4;
3958 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
3959 w->start_at_line_beg = bolp;
3960 w->update_mode_line = Qt;
3961 XSETFASTINT (w->last_modified, 0);
3962 XSETFASTINT (w->last_overlay_modified, 0);
3963 /* Set force_start so that redisplay_window will run
3964 the window-scroll-functions. */
3965 w->force_start = Qt;
3967 if (whole && !NILP (Vscroll_preserve_screen_position))
3969 SET_PT_BOTH (pos, pos_byte);
3970 Fvertical_motion (make_number (original_vpos), window);
3972 /* If we scrolled forward, put point enough lines down
3973 that it is outside the scroll margin. */
3974 else if (n > 0)
3976 int top_margin;
3978 if (this_scroll_margin > 0)
3980 SET_PT_BOTH (pos, pos_byte);
3981 Fvertical_motion (make_number (this_scroll_margin), window);
3982 top_margin = PT;
3984 else
3985 top_margin = pos;
3987 if (top_margin <= opoint)
3988 SET_PT_BOTH (opoint, opoint_byte);
3989 else if (!NILP (Vscroll_preserve_screen_position))
3991 SET_PT_BOTH (pos, pos_byte);
3992 Fvertical_motion (make_number (original_vpos), window);
3994 else
3995 SET_PT (top_margin);
3997 else if (n < 0)
3999 int bottom_margin;
4001 /* If we scrolled backward, put point near the end of the window
4002 but not within the scroll margin. */
4003 SET_PT_BOTH (pos, pos_byte);
4004 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4005 if (XFASTINT (tem) == ht - this_scroll_margin)
4006 bottom_margin = PT;
4007 else
4008 bottom_margin = PT + 1;
4010 if (bottom_margin > opoint)
4011 SET_PT_BOTH (opoint, opoint_byte);
4012 else
4014 if (!NILP (Vscroll_preserve_screen_position))
4016 SET_PT_BOTH (pos, pos_byte);
4017 Fvertical_motion (make_number (original_vpos), window);
4019 else
4020 Fvertical_motion (make_number (-1), window);
4024 else
4026 if (noerror)
4027 return;
4028 else
4029 Fsignal (Qend_of_buffer, Qnil);
4034 /* Scroll selected_window up or down. If N is nil, scroll a
4035 screen-full which is defined as the height of the window minus
4036 next_screen_context_lines. If N is the symbol `-', scroll.
4037 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4038 up. This is the guts of Fscroll_up and Fscroll_down. */
4040 static void
4041 scroll_command (n, direction)
4042 Lisp_Object n;
4043 int direction;
4045 register int defalt;
4046 int count = specpdl_ptr - specpdl;
4048 xassert (abs (direction) == 1);
4050 /* If selected window's buffer isn't current, make it current for
4051 the moment. But don't screw up if window_scroll gets an error. */
4052 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4054 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4055 Fset_buffer (XWINDOW (selected_window)->buffer);
4057 /* Make redisplay consider other windows than just selected_window. */
4058 ++windows_or_buffers_changed;
4061 defalt = (window_internal_height (XWINDOW (selected_window))
4062 - next_screen_context_lines);
4063 defalt = direction * (defalt < 1 ? 1 : defalt);
4065 if (NILP (n))
4066 window_scroll (selected_window, defalt, 1, 0);
4067 else if (EQ (n, Qminus))
4068 window_scroll (selected_window, - defalt, 1, 0);
4069 else
4071 n = Fprefix_numeric_value (n);
4072 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4075 unbind_to (count, Qnil);
4078 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4079 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
4080 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4081 Negative ARG means scroll downward.\n\
4082 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4083 When calling from a program, supply as argument a number, nil, or `-'.")
4084 (arg)
4085 Lisp_Object arg;
4087 scroll_command (arg, 1);
4088 return Qnil;
4091 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4092 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
4093 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4094 Negative ARG means scroll upward.\n\
4095 If ARG is the atom `-', scroll upward by nearly full screen.\n\
4096 When calling from a program, supply as argument a number, nil, or `-'.")
4097 (arg)
4098 Lisp_Object arg;
4100 scroll_command (arg, -1);
4101 return Qnil;
4104 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4105 "Return the other window for \"other window scroll\" commands.\n\
4106 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4107 specifies the window.\n\
4108 If `other-window-scroll-buffer' is non-nil, a window\n\
4109 showing that buffer is used.")
4112 Lisp_Object window;
4114 if (MINI_WINDOW_P (XWINDOW (selected_window))
4115 && !NILP (Vminibuf_scroll_window))
4116 window = Vminibuf_scroll_window;
4117 /* If buffer is specified, scroll that buffer. */
4118 else if (!NILP (Vother_window_scroll_buffer))
4120 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4121 if (NILP (window))
4122 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4124 else
4126 /* Nothing specified; look for a neighboring window on the same
4127 frame. */
4128 window = Fnext_window (selected_window, Qnil, Qnil);
4130 if (EQ (window, selected_window))
4131 /* That didn't get us anywhere; look for a window on another
4132 visible frame. */
4134 window = Fnext_window (window, Qnil, Qt);
4135 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4136 && ! EQ (window, selected_window));
4139 CHECK_LIVE_WINDOW (window, 0);
4141 if (EQ (window, selected_window))
4142 error ("There is no other window");
4144 return window;
4147 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4148 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
4149 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4150 The next window is the one below the current one; or the one at the top\n\
4151 if the current one is at the bottom. Negative ARG means scroll downward.\n\
4152 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4153 When calling from a program, supply as argument a number, nil, or `-'.\n\
4155 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4156 specifies the window to scroll.\n\
4157 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
4158 showing that buffer, popping the buffer up if necessary.")
4159 (arg)
4160 register Lisp_Object arg;
4162 register Lisp_Object window;
4163 register int defalt;
4164 register struct window *w;
4165 register int count = specpdl_ptr - specpdl;
4167 window = Fother_window_for_scrolling ();
4169 w = XWINDOW (window);
4170 defalt = window_internal_height (w) - next_screen_context_lines;
4171 if (defalt < 1) defalt = 1;
4173 /* Don't screw up if window_scroll gets an error. */
4174 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4175 ++windows_or_buffers_changed;
4177 Fset_buffer (w->buffer);
4178 SET_PT (marker_position (w->pointm));
4180 if (NILP (arg))
4181 window_scroll (window, defalt, 1, 1);
4182 else if (EQ (arg, Qminus))
4183 window_scroll (window, -defalt, 1, 1);
4184 else
4186 if (CONSP (arg))
4187 arg = Fcar (arg);
4188 CHECK_NUMBER (arg, 0);
4189 window_scroll (window, XINT (arg), 0, 1);
4192 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4193 unbind_to (count, Qnil);
4195 return Qnil;
4198 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4199 "Scroll selected window display ARG columns left.\n\
4200 Default for ARG is window width minus 2.")
4201 (arg)
4202 register Lisp_Object arg;
4205 if (NILP (arg))
4206 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4207 else
4208 arg = Fprefix_numeric_value (arg);
4210 return
4211 Fset_window_hscroll (selected_window,
4212 make_number (XINT (XWINDOW (selected_window)->hscroll)
4213 + XINT (arg)));
4216 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4217 "Scroll selected window display ARG columns right.\n\
4218 Default for ARG is window width minus 2.")
4219 (arg)
4220 register Lisp_Object arg;
4222 if (NILP (arg))
4223 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4224 else
4225 arg = Fprefix_numeric_value (arg);
4227 return
4228 Fset_window_hscroll (selected_window,
4229 make_number (XINT (XWINDOW (selected_window)->hscroll)
4230 - XINT (arg)));
4233 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4234 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
4235 The desired position of point is always relative to the current window.\n\
4236 Just C-u as prefix means put point in the center of the window.\n\
4237 If ARG is omitted or nil, erases the entire frame and then\n\
4238 redraws with point in the center of the current window.")
4239 (arg)
4240 register Lisp_Object arg;
4242 register struct window *w = XWINDOW (selected_window);
4243 register int ht = window_internal_height (w);
4244 struct position pos;
4245 struct buffer *buf = XBUFFER (w->buffer);
4246 struct buffer *obuf = current_buffer;
4248 if (NILP (arg))
4250 extern int frame_garbaged;
4251 int i;
4253 /* Invalidate pixel data calculated for all compositions. */
4254 for (i = 0; i < n_compositions; i++)
4255 composition_table[i]->font = NULL;
4257 Fredraw_frame (w->frame);
4258 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4259 XSETFASTINT (arg, ht / 2);
4261 else if (CONSP (arg)) /* Just C-u. */
4263 XSETFASTINT (arg, ht / 2);
4265 else
4267 arg = Fprefix_numeric_value (arg);
4268 CHECK_NUMBER (arg, 0);
4271 if (XINT (arg) < 0)
4272 XSETINT (arg, XINT (arg) + ht);
4274 set_buffer_internal (buf);
4275 pos = *vmotion (PT, - XINT (arg), w);
4277 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
4278 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
4279 || FETCH_BYTE (pos.bytepos - 1) == '\n')
4280 ? Qt : Qnil);
4281 w->force_start = Qt;
4282 set_buffer_internal (obuf);
4284 return Qnil;
4288 /* Value is the number of lines actually displayed in window W,
4289 as opposed to its height. */
4291 static int
4292 displayed_window_lines (w)
4293 struct window *w;
4295 struct it it;
4296 struct text_pos start;
4297 int height = window_box_height (w);
4299 SET_TEXT_POS_FROM_MARKER (start, w->start);
4300 start_display (&it, w, start);
4301 move_it_vertically (&it, height);
4303 /* Add in empty lines at the bottom of the window. */
4304 if (it.current_y < height)
4306 struct frame *f = XFRAME (w->frame);
4307 int rest = height - it.current_y;
4308 int lines = (rest + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4309 it.vpos += lines;
4312 return it.vpos;
4317 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4318 1, 1, "P",
4319 "Position point relative to window.\n\
4320 With no argument, position point at center of window.\n\
4321 An argument specifies vertical position within the window;\n\
4322 zero means top of window, negative means relative to bottom of window.")
4323 (arg)
4324 Lisp_Object arg;
4326 struct window *w = XWINDOW (selected_window);
4327 int lines, start;
4328 Lisp_Object window;
4330 window = selected_window;
4331 start = marker_position (w->start);
4332 if (start < BEGV || start > ZV)
4334 int height = window_internal_height (w);
4335 Fvertical_motion (make_number (- (height / 2)), window);
4336 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4337 w->start_at_line_beg = Fbolp ();
4338 w->force_start = Qt;
4340 else
4341 Fgoto_char (w->start);
4343 lines = displayed_window_lines (w);
4344 if (NILP (arg))
4345 XSETFASTINT (arg, lines / 2);
4346 else
4348 arg = Fprefix_numeric_value (arg);
4349 if (XINT (arg) < 0)
4350 XSETINT (arg, XINT (arg) + lines);
4353 return Fvertical_motion (arg, window);
4358 /***********************************************************************
4359 Window Configuration
4360 ***********************************************************************/
4362 struct save_window_data
4364 EMACS_INT size_from_Lisp_Vector_struct;
4365 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4366 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4367 Lisp_Object frame_tool_bar_lines;
4368 Lisp_Object selected_frame;
4369 Lisp_Object current_window;
4370 Lisp_Object current_buffer;
4371 Lisp_Object minibuf_scroll_window;
4372 Lisp_Object root_window;
4373 Lisp_Object focus_frame;
4374 /* Record the values of window-min-width and window-min-height
4375 so that window sizes remain consistent with them. */
4376 Lisp_Object min_width, min_height;
4377 /* A vector, each of whose elements is a struct saved_window
4378 for one window. */
4379 Lisp_Object saved_windows;
4382 /* This is saved as a Lisp_Vector */
4383 struct saved_window
4385 /* these first two must agree with struct Lisp_Vector in lisp.h */
4386 EMACS_INT size_from_Lisp_Vector_struct;
4387 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4389 Lisp_Object window;
4390 Lisp_Object buffer, start, pointm, mark;
4391 Lisp_Object left, top, width, height, hscroll;
4392 Lisp_Object parent, prev;
4393 Lisp_Object start_at_line_beg;
4394 Lisp_Object display_table;
4396 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
4398 #define SAVED_WINDOW_N(swv,n) \
4399 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4401 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4402 "Return t if OBJECT is a window-configuration object.")
4403 (object)
4404 Lisp_Object object;
4406 if (WINDOW_CONFIGURATIONP (object))
4407 return Qt;
4408 return Qnil;
4411 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4412 "Return the frame that CONFIG, a window-configuration object, is about.")
4413 (config)
4414 Lisp_Object config;
4416 register struct save_window_data *data;
4417 struct Lisp_Vector *saved_windows;
4419 if (! WINDOW_CONFIGURATIONP (config))
4420 wrong_type_argument (Qwindow_configuration_p, config);
4422 data = (struct save_window_data *) XVECTOR (config);
4423 saved_windows = XVECTOR (data->saved_windows);
4424 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4427 DEFUN ("set-window-configuration", Fset_window_configuration,
4428 Sset_window_configuration, 1, 1, 0,
4429 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4430 CONFIGURATION must be a value previously returned\n\
4431 by `current-window-configuration' (which see).\n\
4432 If CONFIGURATION was made from a frame that is now deleted,\n\
4433 only frame-independent values can be restored. In this case,\n\
4434 the return value is nil. Otherwise the value is t.")
4435 (configuration)
4436 Lisp_Object configuration;
4438 register struct save_window_data *data;
4439 struct Lisp_Vector *saved_windows;
4440 Lisp_Object new_current_buffer;
4441 Lisp_Object frame;
4442 FRAME_PTR f;
4443 int old_point = -1;
4445 while (!WINDOW_CONFIGURATIONP (configuration))
4446 wrong_type_argument (Qwindow_configuration_p, configuration);
4448 data = (struct save_window_data *) XVECTOR (configuration);
4449 saved_windows = XVECTOR (data->saved_windows);
4451 new_current_buffer = data->current_buffer;
4452 if (NILP (XBUFFER (new_current_buffer)->name))
4453 new_current_buffer = Qnil;
4454 else
4456 if (XBUFFER (new_current_buffer) == current_buffer)
4457 old_point = PT;
4461 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4462 f = XFRAME (frame);
4464 /* If f is a dead frame, don't bother rebuilding its window tree.
4465 However, there is other stuff we should still try to do below. */
4466 if (FRAME_LIVE_P (f))
4468 register struct window *w;
4469 register struct saved_window *p;
4470 struct window *root_window;
4471 struct window **leaf_windows;
4472 int n_leaf_windows;
4473 int k, i;
4475 /* If the frame has been resized since this window configuration was
4476 made, we change the frame to the size specified in the
4477 configuration, restore the configuration, and then resize it
4478 back. We keep track of the prevailing height in these variables. */
4479 int previous_frame_height = FRAME_HEIGHT (f);
4480 int previous_frame_width = FRAME_WIDTH (f);
4481 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
4482 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
4484 /* The mouse highlighting code could get screwed up
4485 if it runs during this. */
4486 BLOCK_INPUT;
4488 if (XFASTINT (data->frame_height) != previous_frame_height
4489 || XFASTINT (data->frame_width) != previous_frame_width)
4490 change_frame_size (f, XFASTINT (data->frame_height),
4491 XFASTINT (data->frame_width), 0, 0, 0);
4492 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4493 if (XFASTINT (data->frame_menu_bar_lines)
4494 != previous_frame_menu_bar_lines)
4495 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4496 #ifdef HAVE_WINDOW_SYSTEM
4497 if (XFASTINT (data->frame_tool_bar_lines)
4498 != previous_frame_tool_bar_lines)
4499 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4500 #endif
4501 #endif
4503 /* "Swap out" point from the selected window
4504 into its buffer. We do this now, before
4505 restoring the window contents, and prevent it from
4506 being done later on when we select a new window. */
4507 if (! NILP (XWINDOW (selected_window)->buffer))
4509 w = XWINDOW (selected_window);
4510 set_marker_both (w->pointm,
4511 w->buffer,
4512 BUF_PT (XBUFFER (w->buffer)),
4513 BUF_PT_BYTE (XBUFFER (w->buffer)));
4516 windows_or_buffers_changed++;
4517 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4519 /* Problem: Freeing all matrices and later allocating them again
4520 is a serious redisplay flickering problem. What we would
4521 really like to do is to free only those matrices not reused
4522 below. */
4523 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4524 leaf_windows
4525 = (struct window **) alloca (count_windows (root_window)
4526 * sizeof (struct window *));
4527 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4529 /* Temporarily avoid any problems with windows that are smaller
4530 than they are supposed to be. */
4531 window_min_height = 1;
4532 window_min_width = 1;
4534 /* Kludge Alert!
4535 Mark all windows now on frame as "deleted".
4536 Restoring the new configuration "undeletes" any that are in it.
4538 Save their current buffers in their height fields, since we may
4539 need it later, if a buffer saved in the configuration is now
4540 dead. */
4541 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4543 for (k = 0; k < saved_windows->size; k++)
4545 p = SAVED_WINDOW_N (saved_windows, k);
4546 w = XWINDOW (p->window);
4547 w->next = Qnil;
4549 if (!NILP (p->parent))
4550 w->parent = SAVED_WINDOW_N (saved_windows,
4551 XFASTINT (p->parent))->window;
4552 else
4553 w->parent = Qnil;
4555 if (!NILP (p->prev))
4557 w->prev = SAVED_WINDOW_N (saved_windows,
4558 XFASTINT (p->prev))->window;
4559 XWINDOW (w->prev)->next = p->window;
4561 else
4563 w->prev = Qnil;
4564 if (!NILP (w->parent))
4566 if (EQ (p->width, XWINDOW (w->parent)->width))
4568 XWINDOW (w->parent)->vchild = p->window;
4569 XWINDOW (w->parent)->hchild = Qnil;
4571 else
4573 XWINDOW (w->parent)->hchild = p->window;
4574 XWINDOW (w->parent)->vchild = Qnil;
4579 /* If we squirreled away the buffer in the window's height,
4580 restore it now. */
4581 if (BUFFERP (w->height))
4582 w->buffer = w->height;
4583 w->left = p->left;
4584 w->top = p->top;
4585 w->width = p->width;
4586 w->height = p->height;
4587 w->hscroll = p->hscroll;
4588 w->display_table = p->display_table;
4589 XSETFASTINT (w->last_modified, 0);
4590 XSETFASTINT (w->last_overlay_modified, 0);
4592 /* Reinstall the saved buffer and pointers into it. */
4593 if (NILP (p->buffer))
4594 w->buffer = p->buffer;
4595 else
4597 if (!NILP (XBUFFER (p->buffer)->name))
4598 /* If saved buffer is alive, install it. */
4600 w->buffer = p->buffer;
4601 w->start_at_line_beg = p->start_at_line_beg;
4602 set_marker_restricted (w->start, p->start, w->buffer);
4603 set_marker_restricted (w->pointm, p->pointm, w->buffer);
4604 Fset_marker (XBUFFER (w->buffer)->mark,
4605 p->mark, w->buffer);
4607 /* As documented in Fcurrent_window_configuration, don't
4608 save the location of point in the buffer which was current
4609 when the window configuration was recorded. */
4610 if (!EQ (p->buffer, new_current_buffer)
4611 && XBUFFER (p->buffer) == current_buffer)
4612 Fgoto_char (w->pointm);
4614 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4615 /* Else unless window has a live buffer, get one. */
4617 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4618 /* This will set the markers to beginning of visible
4619 range. */
4620 set_marker_restricted (w->start, make_number (0), w->buffer);
4621 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4622 w->start_at_line_beg = Qt;
4624 else
4625 /* Keeping window's old buffer; make sure the markers
4626 are real. */
4628 /* Set window markers at start of visible range. */
4629 if (XMARKER (w->start)->buffer == 0)
4630 set_marker_restricted (w->start, make_number (0),
4631 w->buffer);
4632 if (XMARKER (w->pointm)->buffer == 0)
4633 set_marker_restricted_both (w->pointm, w->buffer,
4634 BUF_PT (XBUFFER (w->buffer)),
4635 BUF_PT_BYTE (XBUFFER (w->buffer)));
4636 w->start_at_line_beg = Qt;
4641 FRAME_ROOT_WINDOW (f) = data->root_window;
4642 /* Prevent "swapping out point" in the old selected window
4643 using the buffer that has been restored into it.
4644 That swapping out has already been done,
4645 near the beginning of this function. */
4646 selected_window = Qnil;
4647 Fselect_window (data->current_window);
4648 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4649 = selected_window;
4651 if (NILP (data->focus_frame)
4652 || (FRAMEP (data->focus_frame)
4653 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4654 Fredirect_frame_focus (frame, data->focus_frame);
4656 #if 0 /* I don't understand why this is needed, and it causes problems
4657 when the frame's old selected window has been deleted. */
4658 if (f != selected_frame && FRAME_WINDOW_P (f))
4659 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4660 Qnil, 0);
4661 #endif
4663 /* Set the screen height to the value it had before this function. */
4664 if (previous_frame_height != FRAME_HEIGHT (f)
4665 || previous_frame_width != FRAME_WIDTH (f))
4666 change_frame_size (f, previous_frame_height, previous_frame_width,
4667 0, 0, 0);
4668 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4669 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
4670 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4671 make_number (0));
4672 #ifdef HAVE_WINDOW_SYSTEM
4673 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4674 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4675 make_number (0));
4676 #endif
4677 #endif
4679 /* Now, free glyph matrices in windows that were not reused. */
4680 for (i = 0; i < n_leaf_windows; ++i)
4681 if (NILP (leaf_windows[i]->buffer))
4683 /* Assert it's not reused as a combination. */
4684 xassert (NILP (leaf_windows[i]->hchild)
4685 && NILP (leaf_windows[i]->vchild));
4686 free_window_matrices (leaf_windows[i]);
4687 SET_FRAME_GARBAGED (f);
4690 adjust_glyphs (f);
4692 UNBLOCK_INPUT;
4694 /* Fselect_window will have made f the selected frame, so we
4695 reselect the proper frame here. Fhandle_switch_frame will change the
4696 selected window too, but that doesn't make the call to
4697 Fselect_window above totally superfluous; it still sets f's
4698 selected window. */
4699 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
4700 do_switch_frame (data->selected_frame, Qnil, 0);
4702 if (! NILP (Vwindow_configuration_change_hook)
4703 && ! NILP (Vrun_hooks))
4704 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4707 if (!NILP (new_current_buffer))
4709 Fset_buffer (new_current_buffer);
4711 /* If the buffer that is current now is the same
4712 that was current before setting the window configuration,
4713 don't alter its PT. */
4714 if (old_point >= 0)
4715 SET_PT (old_point);
4718 /* Restore the minimum heights recorded in the configuration. */
4719 window_min_height = XINT (data->min_height);
4720 window_min_width = XINT (data->min_width);
4722 Vminibuf_scroll_window = data->minibuf_scroll_window;
4724 return (FRAME_LIVE_P (f) ? Qt : Qnil);
4727 /* Mark all windows now on frame as deleted
4728 by setting their buffers to nil. */
4730 void
4731 delete_all_subwindows (w)
4732 register struct window *w;
4734 if (!NILP (w->next))
4735 delete_all_subwindows (XWINDOW (w->next));
4736 if (!NILP (w->vchild))
4737 delete_all_subwindows (XWINDOW (w->vchild));
4738 if (!NILP (w->hchild))
4739 delete_all_subwindows (XWINDOW (w->hchild));
4741 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
4743 if (!NILP (w->buffer))
4744 unshow_buffer (w);
4746 /* We set all three of these fields to nil, to make sure that we can
4747 distinguish this dead window from any live window. Live leaf
4748 windows will have buffer set, and combination windows will have
4749 vchild or hchild set. */
4750 w->buffer = Qnil;
4751 w->vchild = Qnil;
4752 w->hchild = Qnil;
4754 Vwindow_list = Qnil;
4757 static int
4758 count_windows (window)
4759 register struct window *window;
4761 register int count = 1;
4762 if (!NILP (window->next))
4763 count += count_windows (XWINDOW (window->next));
4764 if (!NILP (window->vchild))
4765 count += count_windows (XWINDOW (window->vchild));
4766 if (!NILP (window->hchild))
4767 count += count_windows (XWINDOW (window->hchild));
4768 return count;
4772 /* Fill vector FLAT with leaf windows under W, starting at index I.
4773 Value is last index + 1. */
4775 static int
4776 get_leaf_windows (w, flat, i)
4777 struct window *w;
4778 struct window **flat;
4779 int i;
4781 while (w)
4783 if (!NILP (w->hchild))
4784 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
4785 else if (!NILP (w->vchild))
4786 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
4787 else
4788 flat[i++] = w;
4790 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4793 return i;
4797 /* Return a pointer to the glyph W's physical cursor is on. Value is
4798 null if W's current matrix is invalid, so that no meaningfull glyph
4799 can be returned. */
4801 struct glyph *
4802 get_phys_cursor_glyph (w)
4803 struct window *w;
4805 struct glyph_row *row;
4806 struct glyph *glyph;
4808 if (w->phys_cursor.vpos >= 0
4809 && w->phys_cursor.vpos < w->current_matrix->nrows
4810 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
4811 row->enabled_p)
4812 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
4813 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
4814 else
4815 glyph = NULL;
4817 return glyph;
4821 static int
4822 save_window_save (window, vector, i)
4823 Lisp_Object window;
4824 struct Lisp_Vector *vector;
4825 int i;
4827 register struct saved_window *p;
4828 register struct window *w;
4829 register Lisp_Object tem;
4831 for (;!NILP (window); window = w->next)
4833 p = SAVED_WINDOW_N (vector, i);
4834 w = XWINDOW (window);
4836 XSETFASTINT (w->temslot, i++);
4837 p->window = window;
4838 p->buffer = w->buffer;
4839 p->left = w->left;
4840 p->top = w->top;
4841 p->width = w->width;
4842 p->height = w->height;
4843 p->hscroll = w->hscroll;
4844 p->display_table = w->display_table;
4845 if (!NILP (w->buffer))
4847 /* Save w's value of point in the window configuration.
4848 If w is the selected window, then get the value of point
4849 from the buffer; pointm is garbage in the selected window. */
4850 if (EQ (window, selected_window))
4852 p->pointm = Fmake_marker ();
4853 set_marker_both (p->pointm, w->buffer,
4854 BUF_PT (XBUFFER (w->buffer)),
4855 BUF_PT_BYTE (XBUFFER (w->buffer)));
4857 else
4858 p->pointm = Fcopy_marker (w->pointm, Qnil);
4860 p->start = Fcopy_marker (w->start, Qnil);
4861 p->start_at_line_beg = w->start_at_line_beg;
4863 tem = XBUFFER (w->buffer)->mark;
4864 p->mark = Fcopy_marker (tem, Qnil);
4866 else
4868 p->pointm = Qnil;
4869 p->start = Qnil;
4870 p->mark = Qnil;
4871 p->start_at_line_beg = Qnil;
4874 if (NILP (w->parent))
4875 p->parent = Qnil;
4876 else
4877 p->parent = XWINDOW (w->parent)->temslot;
4879 if (NILP (w->prev))
4880 p->prev = Qnil;
4881 else
4882 p->prev = XWINDOW (w->prev)->temslot;
4884 if (!NILP (w->vchild))
4885 i = save_window_save (w->vchild, vector, i);
4886 if (!NILP (w->hchild))
4887 i = save_window_save (w->hchild, vector, i);
4890 return i;
4893 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
4894 Scurrent_window_configuration, 0, 1, 0,
4895 "Return an object representing the current window configuration of FRAME.\n\
4896 If FRAME is nil or omitted, use the selected frame.\n\
4897 This describes the number of windows, their sizes and current buffers,\n\
4898 and for each displayed buffer, where display starts, and the positions of\n\
4899 point and mark. An exception is made for point in the current buffer:\n\
4900 its value is -not- saved.\n\
4901 This also records the currently selected frame, and FRAME's focus\n\
4902 redirection (see `redirect-frame-focus').")
4903 (frame)
4904 Lisp_Object frame;
4906 register Lisp_Object tem;
4907 register int n_windows;
4908 register struct save_window_data *data;
4909 register struct Lisp_Vector *vec;
4910 register int i;
4911 FRAME_PTR f;
4913 if (NILP (frame))
4914 frame = selected_frame;
4915 CHECK_LIVE_FRAME (frame, 0);
4916 f = XFRAME (frame);
4918 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4919 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
4920 for (i = 0; i < VECSIZE (struct save_window_data); i++)
4921 vec->contents[i] = Qnil;
4922 vec->size = VECSIZE (struct save_window_data);
4923 data = (struct save_window_data *)vec;
4925 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
4926 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
4927 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
4928 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
4929 data->selected_frame = selected_frame;
4930 data->current_window = FRAME_SELECTED_WINDOW (f);
4931 XSETBUFFER (data->current_buffer, current_buffer);
4932 data->minibuf_scroll_window = Vminibuf_scroll_window;
4933 data->root_window = FRAME_ROOT_WINDOW (f);
4934 data->focus_frame = FRAME_FOCUS_FRAME (f);
4935 XSETINT (data->min_height, window_min_height);
4936 XSETINT (data->min_width, window_min_width);
4937 tem = Fmake_vector (make_number (n_windows), Qnil);
4938 data->saved_windows = tem;
4939 for (i = 0; i < n_windows; i++)
4940 XVECTOR (tem)->contents[i]
4941 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
4942 save_window_save (FRAME_ROOT_WINDOW (f),
4943 XVECTOR (tem), 0);
4944 XSETWINDOW_CONFIGURATION (tem, data);
4945 return (tem);
4948 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
4949 0, UNEVALLED, 0,
4950 "Execute body, preserving window sizes and contents.\n\
4951 Restore which buffer appears in which window, where display starts,\n\
4952 and the value of point and mark for each window.\n\
4953 Also restore the choice of selected window.\n\
4954 Also restore which buffer is current.\n\
4955 Does not restore the value of point in current buffer.")
4956 (args)
4957 Lisp_Object args;
4959 register Lisp_Object val;
4960 register int count = specpdl_ptr - specpdl;
4962 record_unwind_protect (Fset_window_configuration,
4963 Fcurrent_window_configuration (Qnil));
4964 val = Fprogn (args);
4965 return unbind_to (count, val);
4969 /***********************************************************************
4970 Marginal Areas
4971 ***********************************************************************/
4973 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
4974 2, 3, 0,
4975 "Set width of marginal areas of window WINDOW.\n\
4976 If window is nil, set margins of the currently selected window.\n\
4977 First parameter LEFT-WIDTH specifies the number of character\n\
4978 cells to reserve for the left marginal area. Second parameter\n\
4979 RIGHT-WIDTH does the same for the right marginal area.\n\
4980 A nil width parameter means no margin.")
4981 (window, left, right)
4982 Lisp_Object window, left, right;
4984 struct window *w = decode_window (window);
4986 if (!NILP (left))
4987 CHECK_NUMBER_OR_FLOAT (left, 1);
4988 if (!NILP (right))
4989 CHECK_NUMBER_OR_FLOAT (right, 2);
4991 /* Check widths < 0 and translate a zero width to nil.
4992 Margins that are too wide have to be checked elsewhere. */
4993 if ((INTEGERP (left) && XINT (left) < 0)
4994 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
4995 XSETFASTINT (left, 0);
4996 if (INTEGERP (left) && XFASTINT (left) == 0)
4997 left = Qnil;
4999 if ((INTEGERP (right) && XINT (right) < 0)
5000 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5001 XSETFASTINT (right, 0);
5002 if (INTEGERP (right) && XFASTINT (right) == 0)
5003 right = Qnil;
5005 w->left_margin_width = left;
5006 w->right_margin_width = right;
5008 ++windows_or_buffers_changed;
5009 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5010 return Qnil;
5014 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5015 0, 1, 0,
5016 "Get width of marginal areas of window WINDOW.\n\
5017 If WINDOW is omitted or nil, use the currently selected window.\n\
5018 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
5019 If a marginal area does not exist, its width will be returned\n\
5020 as nil.")
5021 (window)
5022 Lisp_Object window;
5024 struct window *w = decode_window (window);
5025 return Fcons (w->left_margin_width, w->right_margin_width);
5030 /***********************************************************************
5031 Smooth scrolling
5032 ***********************************************************************/
5034 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
5035 "Return the amount by which WINDOW is scrolled vertically.\n\
5036 Use the selected window if WINDOW is nil or omitted.\n\
5037 Value is a multiple of the canonical character height of WINDOW.")
5038 (window)
5039 Lisp_Object window;
5041 Lisp_Object result;
5042 struct frame *f;
5043 struct window *w;
5045 if (NILP (window))
5046 window = selected_window;
5047 else
5048 CHECK_WINDOW (window, 0);
5049 w = XWINDOW (window);
5050 f = XFRAME (w->frame);
5052 if (FRAME_WINDOW_P (f))
5053 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5054 else
5055 result = make_number (0);
5056 return result;
5060 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
5061 2, 2, 0,
5062 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5063 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
5064 non-negative multiple of the canonical character height of WINDOW.")
5065 (window, vscroll)
5066 Lisp_Object window, vscroll;
5068 struct window *w;
5069 struct frame *f;
5071 if (NILP (window))
5072 window = selected_window;
5073 else
5074 CHECK_WINDOW (window, 0);
5075 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
5077 w = XWINDOW (window);
5078 f = XFRAME (w->frame);
5080 if (FRAME_WINDOW_P (f))
5082 int old_dy = w->vscroll;
5084 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
5085 w->vscroll = min (w->vscroll, 0);
5087 /* Adjust glyph matrix of the frame if the virtual display
5088 area becomes larger than before. */
5089 if (w->vscroll < 0 && w->vscroll < old_dy)
5090 adjust_glyphs (f);
5092 /* Prevent redisplay shortcuts. */
5093 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5096 return Fwindow_vscroll (window);
5100 /* Call FN for all leaf windows on frame F. FN is called with the
5101 first argument being a pointer to the leaf window, and with
5102 additional argument USER_DATA. Stops when FN returns 0. */
5104 void
5105 foreach_window (f, fn, user_data)
5106 struct frame *f;
5107 int (* fn) P_ ((struct window *, void *));
5108 void *user_data;
5110 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
5114 /* Helper function for foreach_window. Call FN for all leaf windows
5115 reachable from W. FN is called with the first argument being a
5116 pointer to the leaf window, and with additional argument USER_DATA.
5117 Stop when FN returns 0. Value is 0 if stopped by FN. */
5119 static int
5120 foreach_window_1 (w, fn, user_data)
5121 struct window *w;
5122 int (* fn) P_ ((struct window *, void *));
5123 void *user_data;
5125 int cont;
5127 for (cont = 1; w && cont;)
5129 if (!NILP (w->hchild))
5130 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
5131 else if (!NILP (w->vchild))
5132 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
5133 else
5134 cont = fn (w, user_data);
5136 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5139 return cont;
5143 /* Freeze or unfreeze the window start of W if unless it is a
5144 mini-window or the selected window. FREEZE_P non-null means freeze
5145 the window start. */
5147 static int
5148 freeze_window_start (w, freeze_p)
5149 struct window *w;
5150 void *freeze_p;
5152 if (w == XWINDOW (selected_window)
5153 || MINI_WINDOW_P (w)
5154 || (MINI_WINDOW_P (XWINDOW (selected_window))
5155 && ! NILP (Vminibuf_scroll_window)
5156 && w == XWINDOW (Vminibuf_scroll_window)))
5157 freeze_p = NULL;
5159 w->frozen_window_start_p = freeze_p != NULL;
5160 return 1;
5164 /* Freeze or unfreeze the window starts of all leaf windows on frame
5165 F, except the selected window and a mini-window. FREEZE_P non-zero
5166 means freeze the window start. */
5168 void
5169 freeze_window_starts (f, freeze_p)
5170 struct frame *f;
5171 int freeze_p;
5173 foreach_window (f, freeze_window_start, (void *) freeze_p);
5177 /***********************************************************************
5178 Initialization
5179 ***********************************************************************/
5181 /* Return 1 if window configurations C1 and C2
5182 describe the same state of affairs. This is used by Fequal. */
5185 compare_window_configurations (c1, c2, ignore_positions)
5186 Lisp_Object c1, c2;
5187 int ignore_positions;
5189 register struct save_window_data *d1, *d2;
5190 struct Lisp_Vector *sw1, *sw2;
5191 int i;
5193 if (!WINDOW_CONFIGURATIONP (c1))
5194 wrong_type_argument (Qwindow_configuration_p, c1);
5195 if (!WINDOW_CONFIGURATIONP (c2))
5196 wrong_type_argument (Qwindow_configuration_p, c2);
5198 d1 = (struct save_window_data *) XVECTOR (c1);
5199 d2 = (struct save_window_data *) XVECTOR (c2);
5200 sw1 = XVECTOR (d1->saved_windows);
5201 sw2 = XVECTOR (d2->saved_windows);
5203 if (! EQ (d1->frame_width, d2->frame_width))
5204 return 0;
5205 if (! EQ (d1->frame_height, d2->frame_height))
5206 return 0;
5207 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5208 return 0;
5209 if (! EQ (d1->selected_frame, d2->selected_frame))
5210 return 0;
5211 /* Don't compare the current_window field directly.
5212 Instead see w1_is_current and w2_is_current, below. */
5213 if (! EQ (d1->current_buffer, d2->current_buffer))
5214 return 0;
5215 if (! ignore_positions)
5216 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5217 return 0;
5218 /* Don't compare the root_window field.
5219 We don't require the two configurations
5220 to use the same window object,
5221 and the two root windows must be equivalent
5222 if everything else compares equal. */
5223 if (! EQ (d1->focus_frame, d2->focus_frame))
5224 return 0;
5225 if (! EQ (d1->min_width, d2->min_width))
5226 return 0;
5227 if (! EQ (d1->min_height, d2->min_height))
5228 return 0;
5230 /* Verify that the two confis have the same number of windows. */
5231 if (sw1->size != sw2->size)
5232 return 0;
5234 for (i = 0; i < sw1->size; i++)
5236 struct saved_window *p1, *p2;
5237 int w1_is_current, w2_is_current;
5239 p1 = SAVED_WINDOW_N (sw1, i);
5240 p2 = SAVED_WINDOW_N (sw2, i);
5242 /* Verify that the current windows in the two
5243 configurations correspond to each other. */
5244 w1_is_current = EQ (d1->current_window, p1->window);
5245 w2_is_current = EQ (d2->current_window, p2->window);
5247 if (w1_is_current != w2_is_current)
5248 return 0;
5250 /* Verify that the corresponding windows do match. */
5251 if (! EQ (p1->buffer, p2->buffer))
5252 return 0;
5253 if (! EQ (p1->left, p2->left))
5254 return 0;
5255 if (! EQ (p1->top, p2->top))
5256 return 0;
5257 if (! EQ (p1->width, p2->width))
5258 return 0;
5259 if (! EQ (p1->height, p2->height))
5260 return 0;
5261 if (! EQ (p1->display_table, p2->display_table))
5262 return 0;
5263 if (! EQ (p1->parent, p2->parent))
5264 return 0;
5265 if (! EQ (p1->prev, p2->prev))
5266 return 0;
5267 if (! ignore_positions)
5269 if (! EQ (p1->hscroll, p2->hscroll))
5270 return 0;
5271 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5272 return 0;
5273 if (NILP (Fequal (p1->start, p2->start)))
5274 return 0;
5275 if (NILP (Fequal (p1->pointm, p2->pointm)))
5276 return 0;
5277 if (NILP (Fequal (p1->mark, p2->mark)))
5278 return 0;
5282 return 1;
5285 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5286 Scompare_window_configurations, 2, 2, 0,
5287 "Compare two window configurations as regards the structure of windows.\n\
5288 This function ignores details such as the values of point and mark\n\
5289 and scrolling positions.")
5290 (x, y)
5291 Lisp_Object x, y;
5293 if (compare_window_configurations (x, y, 1))
5294 return Qt;
5295 return Qnil;
5298 void
5299 init_window_once ()
5301 struct frame *f = make_terminal_frame ();
5302 XSETFRAME (selected_frame, f);
5303 Vterminal_frame = selected_frame;
5304 minibuf_window = f->minibuffer_window;
5305 selected_window = f->selected_window;
5306 last_nonminibuf_frame = f;
5308 window_initialized = 1;
5311 void
5312 init_window ()
5314 Vwindow_list = Qnil;
5317 void
5318 syms_of_window ()
5320 Qleft_bitmap_area = intern ("left-bitmap-area");
5321 staticpro (&Qleft_bitmap_area);
5322 Qright_bitmap_area = intern ("right-bitmap-area");
5323 staticpro (&Qright_bitmap_area);
5325 Qwindow_size_fixed = intern ("window-size-fixed");
5326 staticpro (&Qwindow_size_fixed);
5328 staticpro (&Qwindow_configuration_change_hook);
5329 Qwindow_configuration_change_hook
5330 = intern ("window-configuration-change-hook");
5332 Qwindowp = intern ("windowp");
5333 staticpro (&Qwindowp);
5335 Qwindow_configuration_p = intern ("window-configuration-p");
5336 staticpro (&Qwindow_configuration_p);
5338 Qwindow_live_p = intern ("window-live-p");
5339 staticpro (&Qwindow_live_p);
5341 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5342 staticpro (&Qtemp_buffer_show_hook);
5344 staticpro (&Vwindow_list);
5346 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5347 "Non-nil means call as function to display a help buffer.\n\
5348 The function is called with one argument, the buffer to be displayed.\n\
5349 Used by `with-output-to-temp-buffer'.\n\
5350 If this function is used, then it must do the entire job of showing\n\
5351 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5352 Vtemp_buffer_show_function = Qnil;
5354 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5355 "If non-nil, function to call to handle `display-buffer'.\n\
5356 It will receive two args, the buffer and a flag which if non-nil means\n\
5357 that the currently selected window is not acceptable.\n\
5358 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5359 work using this function.");
5360 Vdisplay_buffer_function = Qnil;
5362 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5363 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5364 Vminibuf_scroll_window = Qnil;
5366 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5367 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5368 Vother_window_scroll_buffer = Qnil;
5370 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5371 "*Non-nil means `display-buffer' should make a separate frame.");
5372 pop_up_frames = 0;
5374 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
5375 "*Non-nil means `display-buffer' should reuse frames.\n\
5376 If the buffer in question is already displayed in a frame, raise that frame.");
5377 display_buffer_reuse_frames = 0;
5379 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5380 "Function to call to handle automatic new frame creation.\n\
5381 It is called with no arguments and should return a newly created frame.\n\
5383 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5384 where `pop-up-frame-alist' would hold the default frame parameters.");
5385 Vpop_up_frame_function = Qnil;
5387 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5388 "*List of buffer names that should have their own special frames.\n\
5389 Displaying a buffer whose name is in this list makes a special frame for it\n\
5390 using `special-display-function'. See also `special-display-regexps'.\n\
5392 An element of the list can be a list instead of just a string.\n\
5393 There are two ways to use a list as an element:\n\
5394 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5395 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5396 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5397 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5398 All this is done by the function found in `special-display-function'.\n\
5400 If this variable appears \"not to work\", because you add a name to it\n\
5401 but that buffer still appears in the selected window, look at the\n\
5402 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5403 Those variables take precedence over this one.");
5404 Vspecial_display_buffer_names = Qnil;
5406 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5407 "*List of regexps saying which buffers should have their own special frames.\n\
5408 If a buffer name matches one of these regexps, it gets its own frame.\n\
5409 Displaying a buffer whose name is in this list makes a special frame for it\n\
5410 using `special-display-function'.\n\
5412 An element of the list can be a list instead of just a string.\n\
5413 There are two ways to use a list as an element:\n\
5414 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5415 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5416 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5417 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5418 All this is done by the function found in `special-display-function'.\n\
5420 If this variable appears \"not to work\", because you add a regexp to it\n\
5421 but the matching buffers still appear in the selected window, look at the\n\
5422 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5423 Those variables take precedence over this one.");
5424 Vspecial_display_regexps = Qnil;
5426 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5427 "Function to call to make a new frame for a special buffer.\n\
5428 It is called with two arguments, the buffer and optional buffer specific\n\
5429 data, and should return a window displaying that buffer.\n\
5430 The default value makes a separate frame for the buffer,\n\
5431 using `special-display-frame-alist' to specify the frame parameters.\n\
5433 A buffer is special if its is listed in `special-display-buffer-names'\n\
5434 or matches a regexp in `special-display-regexps'.");
5435 Vspecial_display_function = Qnil;
5437 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5438 "*List of buffer names that should appear in the selected window.\n\
5439 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5440 switches to it in the selected window, rather than making it appear\n\
5441 in some other window.\n\
5443 An element of the list can be a cons cell instead of just a string.\n\
5444 Then the car must be a string, which specifies the buffer name.\n\
5445 This is for compatibility with `special-display-buffer-names';\n\
5446 the cdr of the cons cell is ignored.\n\
5448 See also `same-window-regexps'.");
5449 Vsame_window_buffer_names = Qnil;
5451 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5452 "*List of regexps saying which buffers should appear in the selected window.\n\
5453 If a buffer name matches one of these regexps, then displaying it\n\
5454 using `display-buffer' or `pop-to-buffer' switches to it\n\
5455 in the selected window, rather than making it appear in some other window.\n\
5457 An element of the list can be a cons cell instead of just a string.\n\
5458 Then the car must be a string, which specifies the buffer name.\n\
5459 This is for compatibility with `special-display-buffer-names';\n\
5460 the cdr of the cons cell is ignored.\n\
5462 See also `same-window-buffer-names'.");
5463 Vsame_window_regexps = Qnil;
5465 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5466 "*Non-nil means display-buffer should make new windows.");
5467 pop_up_windows = 1;
5469 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5470 "*Number of lines of continuity when scrolling by screenfuls.");
5471 next_screen_context_lines = 2;
5473 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5474 "*display-buffer would prefer to split the largest window if this large.\n\
5475 If there is only one window, it is split regardless of this value.");
5476 split_height_threshold = 500;
5478 DEFVAR_INT ("window-min-height", &window_min_height,
5479 "*Delete any window less than this tall (including its mode line).");
5480 window_min_height = 4;
5482 DEFVAR_INT ("window-min-width", &window_min_width,
5483 "*Delete any window less than this wide.");
5484 window_min_width = 10;
5486 DEFVAR_LISP ("scroll-preserve-screen-position",
5487 &Vscroll_preserve_screen_position,
5488 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
5489 Vscroll_preserve_screen_position = Qnil;
5491 DEFVAR_LISP ("window-configuration-change-hook",
5492 &Vwindow_configuration_change_hook,
5493 "Functions to call when window configuration changes.\n\
5494 The selected frame is the one whose configuration has changed.");
5495 Vwindow_configuration_change_hook = Qnil;
5497 defsubr (&Sselected_window);
5498 defsubr (&Sminibuffer_window);
5499 defsubr (&Swindow_minibuffer_p);
5500 defsubr (&Swindowp);
5501 defsubr (&Swindow_live_p);
5502 defsubr (&Spos_visible_in_window_p);
5503 defsubr (&Swindow_buffer);
5504 defsubr (&Swindow_height);
5505 defsubr (&Swindow_width);
5506 defsubr (&Swindow_hscroll);
5507 defsubr (&Sset_window_hscroll);
5508 defsubr (&Swindow_redisplay_end_trigger);
5509 defsubr (&Sset_window_redisplay_end_trigger);
5510 defsubr (&Swindow_edges);
5511 defsubr (&Scoordinates_in_window_p);
5512 defsubr (&Swindow_at);
5513 defsubr (&Swindow_point);
5514 defsubr (&Swindow_start);
5515 defsubr (&Swindow_end);
5516 defsubr (&Sset_window_point);
5517 defsubr (&Sset_window_start);
5518 defsubr (&Swindow_dedicated_p);
5519 defsubr (&Sset_window_dedicated_p);
5520 defsubr (&Swindow_display_table);
5521 defsubr (&Sset_window_display_table);
5522 defsubr (&Snext_window);
5523 defsubr (&Sprevious_window);
5524 defsubr (&Sother_window);
5525 defsubr (&Sget_lru_window);
5526 defsubr (&Sget_largest_window);
5527 defsubr (&Sget_buffer_window);
5528 defsubr (&Sdelete_other_windows);
5529 defsubr (&Sdelete_windows_on);
5530 defsubr (&Sreplace_buffer_in_windows);
5531 defsubr (&Sdelete_window);
5532 defsubr (&Sset_window_buffer);
5533 defsubr (&Sselect_window);
5534 defsubr (&Sspecial_display_p);
5535 defsubr (&Ssame_window_p);
5536 defsubr (&Sdisplay_buffer);
5537 defsubr (&Ssplit_window);
5538 defsubr (&Senlarge_window);
5539 defsubr (&Sshrink_window);
5540 defsubr (&Sscroll_up);
5541 defsubr (&Sscroll_down);
5542 defsubr (&Sscroll_left);
5543 defsubr (&Sscroll_right);
5544 defsubr (&Sother_window_for_scrolling);
5545 defsubr (&Sscroll_other_window);
5546 defsubr (&Srecenter);
5547 defsubr (&Smove_to_window_line);
5548 defsubr (&Swindow_configuration_p);
5549 defsubr (&Swindow_configuration_frame);
5550 defsubr (&Sset_window_configuration);
5551 defsubr (&Scurrent_window_configuration);
5552 defsubr (&Ssave_window_excursion);
5553 defsubr (&Sset_window_margins);
5554 defsubr (&Swindow_margins);
5555 defsubr (&Swindow_vscroll);
5556 defsubr (&Sset_window_vscroll);
5557 defsubr (&Scompare_window_configurations);
5558 defsubr (&Swindow_list);
5561 void
5562 keys_of_window ()
5564 initial_define_key (control_x_map, '1', "delete-other-windows");
5565 initial_define_key (control_x_map, '2', "split-window");
5566 initial_define_key (control_x_map, '0', "delete-window");
5567 initial_define_key (control_x_map, 'o', "other-window");
5568 initial_define_key (control_x_map, '^', "enlarge-window");
5569 initial_define_key (control_x_map, '<', "scroll-left");
5570 initial_define_key (control_x_map, '>', "scroll-right");
5572 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5573 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5574 initial_define_key (meta_map, 'v', "scroll-down");
5576 initial_define_key (global_map, Ctl('L'), "recenter");
5577 initial_define_key (meta_map, 'r', "move-to-window-line");