(x_consider_frame_title, decode_mode_spec): Use assignment, not initialization.
[emacs.git] / src / window.c
blob12cdca006cdb08fc5e00770f112c395952db5fa7
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1993, 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include <config.h>
22 #include "lisp.h"
23 #include "buffer.h"
24 #include "frame.h"
25 #include "window.h"
26 #include "commands.h"
27 #include "indent.h"
28 #include "termchar.h"
29 #include "disptab.h"
30 #include "keyboard.h"
32 Lisp_Object Qwindowp, Qwindow_live_p;
34 Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
35 Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
37 void delete_all_subwindows ();
38 static struct window *decode_window();
40 /* This is the window in which the terminal's cursor should
41 be left when nothing is being done with it. This must
42 always be a leaf window, and its buffer is selected by
43 the top level editing loop at the end of each command.
45 This value is always the same as
46 FRAME_SELECTED_WINDOW (selected_frame). */
48 Lisp_Object selected_window;
50 /* The minibuffer window of the selected frame.
51 Note that you cannot test for minibufferness of an arbitrary window
52 by comparing against this; but you can test for minibufferness of
53 the selected window. */
54 Lisp_Object minibuf_window;
56 /* Non-nil means it is the window for C-M-v to scroll
57 when the minibuffer is selected. */
58 Lisp_Object Vminibuf_scroll_window;
60 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
61 Lisp_Object Vother_window_scroll_buffer;
63 /* Non-nil means it's function to call to display temp buffers. */
64 Lisp_Object Vtemp_buffer_show_function;
66 /* If a window gets smaller than either of these, it is removed. */
67 int window_min_height;
68 int window_min_width;
70 /* Nonzero implies Fdisplay_buffer should create windows. */
71 int pop_up_windows;
73 /* Nonzero implies make new frames for Fdisplay_buffer. */
74 int pop_up_frames;
76 /* Non-nil means use this function instead of default */
77 Lisp_Object Vpop_up_frame_function;
79 /* Function to call to handle Fdisplay_buffer. */
80 Lisp_Object Vdisplay_buffer_function;
82 /* Fdisplay_buffer always splits the largest window
83 if that window is more than this high. */
84 int split_height_threshold;
86 /* Number of lines of continuity in scrolling by screenfuls. */
87 int next_screen_context_lines;
89 /* Incremented for each window created. */
90 static int sequence_number;
92 #define min(a, b) ((a) < (b) ? (a) : (b))
94 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
95 "Returns t if OBJ is a window.")
96 (obj)
97 Lisp_Object obj;
99 return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
102 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
103 "Returns t if OBJ is a window which is currently visible.")
104 (obj)
105 Lisp_Object obj;
107 return ((XTYPE (obj) == Lisp_Window
108 && ! NILP (XWINDOW (obj)->buffer))
109 ? Qt : Qnil);
112 Lisp_Object
113 make_window ()
115 register Lisp_Object val;
116 register struct window *p;
118 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
119 includes the first element. */
120 val = Fmake_vector (
121 make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)
122 + sizeof (Lisp_Object))
123 / sizeof (Lisp_Object)),
124 Qnil);
125 XSETTYPE (val, Lisp_Window);
126 p = XWINDOW (val);
127 XFASTINT (p->sequence_number) = ++sequence_number;
128 XFASTINT (p->left) = XFASTINT (p->top)
129 = XFASTINT (p->height) = XFASTINT (p->width)
130 = XFASTINT (p->hscroll) = 0;
131 XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
132 p->start = Fmake_marker ();
133 p->pointm = Fmake_marker ();
134 XFASTINT (p->use_time) = 0;
135 p->frame = Qnil;
136 p->display_table = Qnil;
137 p->dedicated = Qnil;
138 return val;
141 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
142 "Return the window that the cursor now appears in and commands apply to.")
145 return selected_window;
148 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
149 "Return the window used now for minibuffers.\n\
150 If the optional argument FRAME is specified, return the minibuffer window\n\
151 used by that frame.")
152 (frame)
153 Lisp_Object frame;
155 #ifdef MULTI_FRAME
156 if (NILP (frame))
157 XSET (frame, Lisp_Frame, selected_frame);
158 else
159 CHECK_LIVE_FRAME (frame, 0);
160 #endif
162 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
165 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
166 "Returns non-nil if WINDOW is a minibuffer window.")
167 (window)
168 Lisp_Object window;
170 struct window *w = decode_window (window);
171 return (MINI_WINDOW_P (w) ? Qt : Qnil);
174 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
175 Spos_visible_in_window_p, 0, 2, 0,
176 "Return t if position POS is currently on the frame in WINDOW.\n\
177 Returns nil if that position is scrolled vertically out of view.\n\
178 POS defaults to point; WINDOW, to the selected window.")
179 (pos, window)
180 Lisp_Object pos, window;
182 register struct window *w;
183 register int top;
184 register int height;
185 register int posint;
186 register struct buffer *buf;
187 struct position posval;
188 int hscroll;
190 if (NILP (pos))
191 posint = point;
192 else
194 CHECK_NUMBER_COERCE_MARKER (pos, 0);
195 posint = XINT (pos);
198 w = decode_window (window);
199 top = marker_position (w->start);
200 hscroll = XINT (w->hscroll);
202 if (posint < top)
203 return Qnil;
205 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
207 buf = XBUFFER (w->buffer);
208 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
210 /* If frame is up to date,
211 use the info recorded about how much text fit on it. */
212 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
213 || (XFASTINT (w->window_end_vpos) < height))
214 return Qt;
215 return Qnil;
217 else
219 if (posint > BUF_ZV (buf))
220 return Qnil;
222 /* If that info is not correct, calculate afresh */
223 posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0),
224 posint, height, 0,
225 window_internal_width (w) - 1,
226 hscroll, 0);
228 return posval.vpos < height ? Qt : Qnil;
232 static struct window *
233 decode_window (window)
234 register Lisp_Object window;
236 if (NILP (window))
237 return XWINDOW (selected_window);
239 CHECK_LIVE_WINDOW (window, 0);
240 return XWINDOW (window);
243 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
244 "Return the buffer that WINDOW is displaying.")
245 (window)
246 Lisp_Object window;
248 return decode_window (window)->buffer;
251 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
252 "Return the number of lines in WINDOW (including its mode line).")
253 (window)
254 Lisp_Object window;
256 return decode_window (window)->height;
259 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
260 "Return the number of display columns in WINDOW.\n\
261 This is the width that is usable columns available for text in WINDOW.\n\
262 If you want to find out how many columns WINDOW takes up,\n\
263 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
264 (window)
265 Lisp_Object window;
267 register struct window *w = decode_window (window);
268 register int width = XFASTINT (w->width);
270 return make_number (window_internal_width (w));
273 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
274 "Return the number of columns by which WINDOW is scrolled from left margin.")
275 (window)
276 Lisp_Object window;
278 return decode_window (window)->hscroll;
281 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
282 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
283 NCOL should be zero or positive.")
284 (window, ncol)
285 register Lisp_Object window, ncol;
287 register struct window *w;
289 CHECK_NUMBER (ncol, 1);
290 if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
291 if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
292 args_out_of_range (ncol, Qnil);
293 w = decode_window (window);
294 if (XINT (w->hscroll) != XINT (ncol))
295 clip_changed = 1; /* Prevent redisplay shortcuts */
296 w->hscroll = ncol;
297 return ncol;
300 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
301 "Return a list of the edge coordinates of WINDOW.\n\
302 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
303 RIGHT is one more than the rightmost column used by WINDOW,\n\
304 and BOTTOM is one more than the bottommost row used by WINDOW\n\
305 and its mode-line.")
306 (window)
307 Lisp_Object window;
309 register struct window *w = decode_window (window);
311 return Fcons (w->left, Fcons (w->top,
312 Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
313 Fcons (make_number (XFASTINT (w->top)
314 + XFASTINT (w->height)),
315 Qnil))));
318 /* Test if the character at column *x, row *y is within window *w.
319 If it is not, return 0;
320 if it is in the window's text area,
321 set *x and *y to its location relative to the upper left corner
322 of the window, and
323 return 1;
324 if it is on the window's modeline, return 2;
325 if it is on the border between the window and its right sibling,
326 return 3. */
327 static int
328 coordinates_in_window (w, x, y)
329 register struct window *w;
330 register int *x, *y;
332 register int left = XINT (w->left);
333 register int width = XINT (w->width);
334 register int window_height = XINT (w->height);
335 register int top = XFASTINT (w->top);
337 if ( *x < left || *x >= left + width
338 || *y < top || *y >= top + window_height)
339 return 0;
341 /* Is the character is the mode line? */
342 if (*y == top + window_height - 1
343 && ! MINI_WINDOW_P (w))
344 return 2;
346 /* Is the character in the right border? */
347 if (*x == left + width - 1
348 && left + width != FRAME_WIDTH (XFRAME (w->frame)))
349 return 3;
351 *x -= left;
352 *y -= top;
353 return 1;
356 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
357 Scoordinates_in_window_p, 2, 2, 0,
358 "Return non-nil if COORDINATES are in WINDOW.\n\
359 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
360 measured in characters from the upper-left corner of the frame.\n\
361 (0 . 0) denotes the character in the upper left corner of the\n\
362 frame.\n\
363 If COORDINATES are in the text portion of WINDOW,\n\
364 the coordinates relative to the window are returned.\n\
365 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
366 If they are on the border between WINDOW and its right sibling,\n\
367 `vertical-line' is returned.")
368 (coordinates, window)
369 register Lisp_Object coordinates, window;
371 int x, y;
373 CHECK_LIVE_WINDOW (window, 0);
374 CHECK_CONS (coordinates, 1);
375 x = XINT (Fcar (coordinates));
376 y = XINT (Fcdr (coordinates));
378 switch (coordinates_in_window (XWINDOW (window), &x, &y))
380 case 0: /* NOT in window at all. */
381 return Qnil;
383 case 1: /* In text part of window. */
384 return Fcons (x, y);
386 case 2: /* In mode line of window. */
387 return Qmode_line;
389 case 3: /* On right border of window. */
390 return Qvertical_line;
392 default:
393 abort ();
397 /* Find the window containing column x, row y, and return it as a
398 Lisp_Object. If x, y is on the window's modeline, set *part
399 to 1; if it is on the separating line between the window and its
400 right sibling, set it to 2; otherwise set it to 0. If there is no
401 window under x, y return nil and leave *part unmodified. */
402 Lisp_Object
403 window_from_coordinates (frame, x, y, part)
404 FRAME_PTR frame;
405 int x, y;
406 int *part;
408 register Lisp_Object tem, first;
410 tem = first = FRAME_SELECTED_WINDOW (frame);
414 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
416 if (found)
418 *part = found - 1;
419 return tem;
422 tem = Fnext_window (tem, Qt, Qlambda);
424 while (! EQ (tem, first));
426 return Qnil;
429 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
430 "Return window containing coordinates X and Y on FRAME.\n\
431 If omitted, FRAME defaults to the currently selected frame.\n\
432 The top left corner of the frame is considered to be row 0,\n\
433 column 0.")
434 (x, y, frame)
435 Lisp_Object x, y, frame;
437 int part;
439 #ifdef MULTI_FRAME
440 if (NILP (frame))
441 XSET (frame, Lisp_Frame, selected_frame);
442 else
443 CHECK_LIVE_FRAME (frame, 2);
444 #endif
445 CHECK_NUMBER (x, 0);
446 CHECK_NUMBER (y, 1);
448 return window_from_coordinates (XFRAME (frame),
449 XINT (x), XINT (y),
450 &part);
453 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
454 "Return current value of point in WINDOW.\n\
455 For a nonselected window, this is the value point would have\n\
456 if that window were selected.\n\
458 Note that, when WINDOW is the selected window and its buffer\n\
459 is also currently selected, the value returned is the same as (point).\n\
460 It would be more strictly correct to return the `top-level' value\n\
461 of point, outside of any save-excursion forms.\n\
462 But that is hard to define.")
463 (window)
464 Lisp_Object window;
466 register struct window *w = decode_window (window);
468 if (w == XWINDOW (selected_window)
469 && current_buffer == XBUFFER (w->buffer))
470 return Fpoint ();
471 return Fmarker_position (w->pointm);
474 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
475 "Return position at which display currently starts in WINDOW.")
476 (window)
477 Lisp_Object window;
479 return Fmarker_position (decode_window (window)->start);
482 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
483 "Return position at which display currently ends in WINDOW.")
484 (window)
485 Lisp_Object window;
487 Lisp_Object value;
488 struct window *w = decode_window (window);
489 Lisp_Object buf;
491 buf = w->buffer;
492 CHECK_BUFFER (buf, 0);
494 XSET (value, Lisp_Int,
495 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
497 return value;
500 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
501 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
502 (window, pos)
503 Lisp_Object window, pos;
505 register struct window *w = decode_window (window);
507 CHECK_NUMBER_COERCE_MARKER (pos, 1);
508 if (w == XWINDOW (selected_window))
509 Fgoto_char (pos);
510 else
511 set_marker_restricted (w->pointm, pos, w->buffer);
513 return pos;
516 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
517 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
518 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
519 from overriding motion of point in order to display at this exact start.")
520 (window, pos, noforce)
521 Lisp_Object window, pos, noforce;
523 register struct window *w = decode_window (window);
525 CHECK_NUMBER_COERCE_MARKER (pos, 1);
526 set_marker_restricted (w->start, pos, w->buffer);
527 /* this is not right, but much easier than doing what is right. */
528 w->start_at_line_beg = Qnil;
529 if (NILP (noforce))
530 w->force_start = Qt;
531 w->update_mode_line = Qt;
532 XFASTINT (w->last_modified) = 0;
533 if (!EQ (window, selected_window))
534 windows_or_buffers_changed++;
535 return pos;
538 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
539 1, 1, 0,
540 "Return WINDOW's dedicated object, usually t or nil.\n\
541 See also `set-window-dedicated-p'.")
542 (window)
543 Lisp_Object window;
545 return decode_window (window)->dedicated;
548 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
549 Sset_window_dedicated_p, 2, 2, 0,
550 "Control whether WINDOW is dedicated to the buffer it displays.\n\
551 If it is dedicated, Emacs will not automatically change\n\
552 which buffer appears in it.\n\
553 The second argument is the new value for the dedication flag;\n\
554 non-nil means yes.")
555 (window, arg)
556 Lisp_Object window, arg;
558 register struct window *w = decode_window (window);
560 if (NILP (arg))
561 w->dedicated = Qnil;
562 else
563 w->dedicated = Qt;
565 return w->dedicated;
568 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
569 0, 1, 0,
570 "Return the display-table that WINDOW is using.")
571 (window)
572 Lisp_Object window;
574 return decode_window (window)->display_table;
577 /* Get the display table for use currently on window W.
578 This is either W's display table or W's buffer's display table.
579 Ignore the specified tables if they are not valid;
580 if no valid table is specified, return 0. */
582 struct Lisp_Vector *
583 window_display_table (w)
584 struct window *w;
586 Lisp_Object tem;
587 tem = w->display_table;
588 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
589 return XVECTOR (tem);
590 tem = XBUFFER (w->buffer)->display_table;
591 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
592 return XVECTOR (tem);
593 tem = Vstandard_display_table;
594 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
595 return XVECTOR (tem);
596 return 0;
599 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
600 "Set WINDOW's display-table to TABLE.")
601 (window, table)
602 register Lisp_Object window, table;
604 register struct window *w;
605 register Lisp_Object z; /* Return value. */
607 w = decode_window (window);
608 w->display_table = table;
609 return table;
612 /* Record info on buffer window w is displaying
613 when it is about to cease to display that buffer. */
614 static
615 unshow_buffer (w)
616 register struct window *w;
618 Lisp_Object buf;
620 buf = w->buffer;
621 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
622 abort ();
624 #if 0
625 if (w == XWINDOW (selected_window)
626 || ! EQ (buf, XWINDOW (selected_window)->buffer))
627 /* Do this except when the selected window's buffer
628 is being removed from some other window. */
629 #endif
630 /* last_window_start records the start position that this buffer
631 had in the last window to be disconnected from it.
632 Now that this statement is unconditional,
633 it is possible for the buffer to be displayed in the
634 selected window, while last_window_start reflects another
635 window which was recently showing the same buffer.
636 Some people might say that might be a good thing. Let's see. */
637 XBUFFER (buf)->last_window_start = marker_position (w->start);
639 /* Point in the selected window's buffer
640 is actually stored in that buffer, and the window's pointm isn't used.
641 So don't clobber point in that buffer. */
642 if (! EQ (buf, XWINDOW (selected_window)->buffer))
643 BUF_PT (XBUFFER (buf))
644 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
645 marker_position (w->pointm),
646 BUF_ZV (XBUFFER (buf)));
649 /* Put replacement into the window structure in place of old. */
650 static
651 replace_window (old, replacement)
652 Lisp_Object old, replacement;
654 register Lisp_Object tem;
655 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
657 /* If OLD is its frame's root_window, then replacement is the new
658 root_window for that frame. */
660 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
661 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
663 p->left = o->left;
664 p->top = o->top;
665 p->width = o->width;
666 p->height = o->height;
668 p->next = tem = o->next;
669 if (!NILP (tem))
670 XWINDOW (tem)->prev = replacement;
672 p->prev = tem = o->prev;
673 if (!NILP (tem))
674 XWINDOW (tem)->next = replacement;
676 p->parent = tem = o->parent;
677 if (!NILP (tem))
679 if (EQ (XWINDOW (tem)->vchild, old))
680 XWINDOW (tem)->vchild = replacement;
681 if (EQ (XWINDOW (tem)->hchild, old))
682 XWINDOW (tem)->hchild = replacement;
685 /*** Here, if replacement is a vertical combination
686 and so is its new parent, we should make replacement's
687 children be children of that parent instead. ***/
690 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
691 "Remove WINDOW from the display. Default is selected window.")
692 (window)
693 register Lisp_Object window;
695 register Lisp_Object tem, parent, sib;
696 register struct window *p;
697 register struct window *par;
699 /* Because this function is called by other C code on non-leaf
700 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
701 so we can't decode_window here. */
702 if (NILP (window))
703 window = selected_window;
704 else
705 CHECK_WINDOW (window, 0);
706 p = XWINDOW (window);
708 /* It's okay to delete an already-deleted window. */
709 if (NILP (p->buffer)
710 && NILP (p->hchild)
711 && NILP (p->vchild))
712 return Qnil;
714 parent = p->parent;
715 if (NILP (parent))
716 error ("Attempt to delete minibuffer or sole ordinary window");
717 par = XWINDOW (parent);
719 windows_or_buffers_changed++;
721 /* Are we trying to delete any frame's selected window? */
723 Lisp_Object frame, pwindow;
725 /* See if the frame's selected window is either WINDOW
726 or any subwindow of it, by finding all that window's parents
727 and comparing each one with WINDOW. */
728 frame = WINDOW_FRAME (XWINDOW (window));
729 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
731 while (!NILP (pwindow))
733 if (EQ (window, pwindow))
734 break;
735 pwindow = XWINDOW (pwindow)->parent;
738 if (EQ (window, pwindow))
740 Lisp_Object alternative;
741 alternative = Fnext_window (window, Qlambda, Qnil);
743 /* If we're about to delete the selected window on the
744 selected frame, then we should use Fselect_window to select
745 the new window. On the other hand, if we're about to
746 delete the selected window on any other frame, we shouldn't do
747 anything but set the frame's selected_window slot. */
748 if (EQ (window, selected_window))
749 Fselect_window (alternative);
750 else
751 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
755 tem = p->buffer;
756 /* tem is null for dummy parent windows
757 (which have inferiors but not any contents themselves) */
758 if (!NILP (tem))
760 unshow_buffer (p);
761 unchain_marker (p->pointm);
762 unchain_marker (p->start);
765 tem = p->next;
766 if (!NILP (tem))
767 XWINDOW (tem)->prev = p->prev;
769 tem = p->prev;
770 if (!NILP (tem))
771 XWINDOW (tem)->next = p->next;
773 if (EQ (window, par->hchild))
774 par->hchild = p->next;
775 if (EQ (window, par->vchild))
776 par->vchild = p->next;
778 /* Find one of our siblings to give our space to. */
779 sib = p->prev;
780 if (NILP (sib))
782 /* If p gives its space to its next sibling, that sibling needs
783 to have its top/left side pulled back to where p's is.
784 set_window_{height,width} will re-position the sibling's
785 children. */
786 sib = p->next;
787 XWINDOW (sib)->top = p->top;
788 XWINDOW (sib)->left = p->left;
791 /* Stretch that sibling. */
792 if (!NILP (par->vchild))
793 set_window_height (sib,
794 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
796 if (!NILP (par->hchild))
797 set_window_width (sib,
798 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
801 /* If parent now has only one child,
802 put the child into the parent's place. */
803 tem = par->hchild;
804 if (NILP (tem))
805 tem = par->vchild;
806 if (NILP (XWINDOW (tem)->next))
807 replace_window (parent, tem);
809 /* Since we may be deleting combination windows, we must make sure that
810 not only p but all its children have been marked as deleted. */
811 if (! NILP (p->hchild))
812 delete_all_subwindows (XWINDOW (p->hchild));
813 else if (! NILP (p->vchild))
814 delete_all_subwindows (XWINDOW (p->vchild));
816 /* Mark this window as deleted. */
817 p->buffer = p->hchild = p->vchild = Qnil;
819 return Qnil;
823 extern Lisp_Object next_frame (), prev_frame ();
825 /* This comment supplies the doc string for `next-window',
826 for make-docfile to see. We cannot put this in the real DEFUN
827 due to limits in the Unix cpp.
829 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
830 "Return next window after WINDOW in canonical ordering of windows.\n\
831 If omitted, WINDOW defaults to the selected window.\n\
833 Optional second arg MINIBUF t means count the minibuffer window even\n\
834 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
835 it is active. MINIBUF neither t nor nil means not to count the\n\
836 minibuffer even if it is active.\n\
838 Several frames may share a single minibuffer; if the minibuffer\n\
839 counts, all windows on all frames that share that minibuffer count\n\
840 too. This means that next-window may be used to iterate through the\n\
841 set of windows even when the minibuffer is on another frame. If the\n\
842 minibuffer does not count, only windows from WINDOW's frame count.\n\
844 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
845 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
846 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
847 Anything else means restrict to WINDOW's frame.\n\
849 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
850 `next-window' to iterate through the entire cycle of acceptable\n\
851 windows, eventually ending up back at the window you started with.\n\
852 `previous-window' traverses the same cycle, in the reverse order.")
853 (window, minibuf, all_frames) */
855 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
857 (window, minibuf, all_frames)
858 register Lisp_Object window, minibuf, all_frames;
860 register Lisp_Object tem;
861 Lisp_Object start_window;
863 if (NILP (window))
864 window = selected_window;
865 else
866 CHECK_LIVE_WINDOW (window, 0);
868 start_window = window;
870 /* minibuf == nil may or may not include minibuffers.
871 Decide if it does. */
872 if (NILP (minibuf))
873 minibuf = (minibuf_level ? Qt : Qlambda);
875 /* all_frames == nil doesn't specify which frames to include.
876 Decide which frames it includes. */
877 if (NILP (all_frames))
878 all_frames = (EQ (minibuf, Qt)
879 ? (FRAME_MINIBUF_WINDOW
880 (XFRAME
881 (WINDOW_FRAME
882 (XWINDOW (window)))))
883 : Qnil);
884 else if (EQ (all_frames, Qvisible))
886 else if (! EQ (all_frames, Qt))
887 all_frames = Qnil;
888 /* Now all_frames is t meaning search all frames,
889 nil meaning search just current frame,
890 or a window, meaning search the frame that window belongs to. */
892 /* Do this loop at least once, to get the next window, and perhaps
893 again, if we hit the minibuffer and that is not acceptable. */
896 /* Find a window that actually has a next one. This loop
897 climbs up the tree. */
898 while (tem = XWINDOW (window)->next, NILP (tem))
899 if (tem = XWINDOW (window)->parent, !NILP (tem))
900 window = tem;
901 else
903 /* We've reached the end of this frame.
904 Which other frames are acceptable? */
905 tem = WINDOW_FRAME (XWINDOW (window));
906 #ifdef MULTI_FRAME
907 if (! NILP (all_frames))
908 tem = next_frame (tem, all_frames);
909 #endif
910 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
912 break;
915 window = tem;
917 /* If we're in a combination window, find its first child and
918 recurse on that. Otherwise, we've found the window we want. */
919 while (1)
921 if (!NILP (XWINDOW (window)->hchild))
922 window = XWINDOW (window)->hchild;
923 else if (!NILP (XWINDOW (window)->vchild))
924 window = XWINDOW (window)->vchild;
925 else break;
928 /* Which windows are acceptible?
929 Exit the loop and accept this window if
930 this isn't a minibuffer window, or
931 we're accepting minibuffer windows, or
932 we've come all the way around and we're back at the original window. */
933 while (MINI_WINDOW_P (XWINDOW (window))
934 && ! EQ (minibuf, Qt)
935 && ! EQ (window, start_window));
937 return window;
940 /* This comment supplies the doc string for `previous-window',
941 for make-docfile to see. We cannot put this in the real DEFUN
942 due to limits in the Unix cpp.
944 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
945 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
946 If omitted, WINDOW defaults to the selected window.\n\
948 Optional second arg MINIBUF t means count the minibuffer window even\n\
949 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
950 it is active. MINIBUF neither t nor nil means not to count the\n\
951 minibuffer even if it is active.\n\
953 Several frames may share a single minibuffer; if the minibuffer\n\
954 counts, all windows on all frames that share that minibuffer count\n\
955 too. This means that previous-window may be used to iterate through\n\
956 the set of windows even when the minibuffer is on another frame. If\n\
957 the minibuffer does not count, only windows from WINDOW's frame\n\
958 count.\n\
960 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
961 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
962 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
963 Anything else means restrict to WINDOW's frame.\n\
965 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
966 `previous-window' to iterate through the entire cycle of acceptable\n\
967 windows, eventually ending up back at the window you started with.\n\
968 `next-window' traverses the same cycle, in the reverse order.")
969 (window, minibuf, all_frames) */
972 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
974 (window, minibuf, all_frames)
975 register Lisp_Object window, minibuf, all_frames;
977 register Lisp_Object tem;
978 Lisp_Object start_window;
980 if (NILP (window))
981 window = selected_window;
982 else
983 CHECK_LIVE_WINDOW (window, 0);
985 start_window = window;
987 /* minibuf == nil may or may not include minibuffers.
988 Decide if it does. */
989 if (NILP (minibuf))
990 minibuf = (minibuf_level ? Qt : Qlambda);
992 /* all_frames == nil doesn't specify which frames to include.
993 Decide which frames it includes. */
994 if (NILP (all_frames))
995 all_frames = (EQ (minibuf, Qt)
996 ? (FRAME_MINIBUF_WINDOW
997 (XFRAME
998 (WINDOW_FRAME
999 (XWINDOW (window)))))
1000 : Qnil);
1001 else if (EQ (all_frames, Qvisible))
1003 else if (! EQ (all_frames, Qt))
1004 all_frames = Qnil;
1005 /* Now all_frames is t meaning search all frames,
1006 nil meaning search just current frame,
1007 or a window, meaning search the frame that window belongs to. */
1009 /* Do this loop at least once, to get the previous window, and perhaps
1010 again, if we hit the minibuffer and that is not acceptable. */
1013 /* Find a window that actually has a previous one. This loop
1014 climbs up the tree. */
1015 while (tem = XWINDOW (window)->prev, NILP (tem))
1016 if (tem = XWINDOW (window)->parent, !NILP (tem))
1017 window = tem;
1018 else
1020 /* We have found the top window on the frame.
1021 Which frames are acceptable? */
1022 tem = WINDOW_FRAME (XWINDOW (window));
1023 #ifdef MULTI_FRAME
1024 if (! NILP (all_frames))
1025 /* It's actually important that we use prev_frame here,
1026 rather than next_frame. All the windows acceptable
1027 according to the given parameters should form a ring;
1028 Fnext_window and Fprevious_window should go back and
1029 forth around the ring. If we use next_frame here,
1030 then Fnext_window and Fprevious_window take different
1031 paths through the set of acceptable windows.
1032 window_loop assumes that these `ring' requirement are
1033 met. */
1034 tem = prev_frame (tem, all_frames);
1035 #endif
1036 /* If this frame has a minibuffer, find that window first,
1037 because it is conceptually the last window in that frame. */
1038 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1039 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1040 else
1041 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1043 break;
1046 window = tem;
1047 /* If we're in a combination window, find its last child and
1048 recurse on that. Otherwise, we've found the window we want. */
1049 while (1)
1051 if (!NILP (XWINDOW (window)->hchild))
1052 window = XWINDOW (window)->hchild;
1053 else if (!NILP (XWINDOW (window)->vchild))
1054 window = XWINDOW (window)->vchild;
1055 else break;
1056 while (tem = XWINDOW (window)->next, !NILP (tem))
1057 window = tem;
1060 /* Which windows are acceptable?
1061 Exit the loop and accept this window if
1062 this isn't a minibuffer window, or
1063 we're accepting minibuffer windows, or
1064 we've come all the way around and we're back at the original window. */
1065 while (MINI_WINDOW_P (XWINDOW (window))
1066 && !EQ (minibuf, Qt)
1067 && !EQ (window, start_window));
1069 return window;
1072 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1073 "Select the ARG'th different window on this frame.\n\
1074 All windows on current frame are arranged in a cyclic order.\n\
1075 This command selects the window ARG steps away in that order.\n\
1076 A negative ARG moves in the opposite order. If the optional second\n\
1077 argument ALL_FRAMES is non-nil, cycle through all frames.")
1078 (n, all_frames)
1079 register Lisp_Object n, all_frames;
1081 register int i;
1082 register Lisp_Object w;
1084 CHECK_NUMBER (n, 0);
1085 w = selected_window;
1086 i = XINT (n);
1088 while (i > 0)
1090 w = Fnext_window (w, Qnil, all_frames);
1091 i--;
1093 while (i < 0)
1095 w = Fprevious_window (w, Qnil, all_frames);
1096 i++;
1098 Fselect_window (w);
1099 return Qnil;
1102 /* Look at all windows, performing an operation specified by TYPE
1103 with argument OBJ.
1104 If FRAMES is Qt, look at all frames;
1105 Qnil, look at just the selected frame;
1106 Qvisible, look at visible frames;
1107 a frame, just look at windows on that frame.
1108 If MINI is non-zero, perform the operation on minibuffer windows too.
1111 enum window_loop
1113 WINDOW_LOOP_UNUSED,
1114 GET_BUFFER_WINDOW, /* Arg is buffer */
1115 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1116 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1117 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1118 GET_LARGEST_WINDOW,
1119 UNSHOW_BUFFER /* Arg is buffer */
1122 static Lisp_Object
1123 window_loop (type, obj, mini, frames)
1124 enum window_loop type;
1125 register Lisp_Object obj, frames;
1126 int mini;
1128 register Lisp_Object w;
1129 register Lisp_Object best_window;
1130 register Lisp_Object next_window;
1131 register Lisp_Object last_window;
1132 FRAME_PTR frame;
1133 Lisp_Object frame_arg;
1134 frame_arg = Qt;
1136 #ifdef MULTI_FRAME
1137 /* If we're only looping through windows on a particular frame,
1138 frame points to that frame. If we're looping through windows
1139 on all frames, frame is 0. */
1140 if (FRAMEP (frames))
1141 frame = XFRAME (frames);
1142 else if (NILP (frames))
1143 frame = selected_frame;
1144 else
1145 frame = 0;
1146 if (frame)
1147 frame_arg = Qlambda;
1148 else if (EQ (frames, Qvisible))
1149 frame_arg = frames;
1150 #else
1151 frame = 0;
1152 #endif
1154 /* frame_arg is Qlambda to stick to one frame,
1155 Qvisible to consider all visible frames,
1156 or Qt otherwise. */
1158 /* Pick a window to start with. */
1159 if (XTYPE (obj) == Lisp_Window)
1160 w = obj;
1161 else if (frame)
1162 w = FRAME_SELECTED_WINDOW (frame);
1163 else
1164 w = FRAME_SELECTED_WINDOW (selected_frame);
1166 /* Figure out the last window we're going to mess with. Since
1167 Fnext_window, given the same options, is guaranteed to go in a
1168 ring, we can just use Fprevious_window to find the last one.
1170 We can't just wait until we hit the first window again, because
1171 it might be deleted. */
1173 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
1175 best_window = Qnil;
1176 for (;;)
1178 FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1180 /* Pick the next window now, since some operations will delete
1181 the current window. */
1182 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
1184 /* Note that we do not pay attention here to whether
1185 the frame is visible, since Fnext_window skips non-visible frames
1186 if that is desired, under the control of frame_arg. */
1187 if (! MINI_WINDOW_P (XWINDOW (w))
1188 || (mini && minibuf_level > 0))
1189 switch (type)
1191 case GET_BUFFER_WINDOW:
1192 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1193 return w;
1194 break;
1196 case GET_LRU_WINDOW:
1197 /* t as arg means consider only full-width windows */
1198 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
1199 != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1200 break;
1201 /* Ignore dedicated windows and minibuffers. */
1202 if (MINI_WINDOW_P (XWINDOW (w))
1203 || !NILP (XWINDOW (w)->dedicated))
1204 break;
1205 if (NILP (best_window)
1206 || (XFASTINT (XWINDOW (best_window)->use_time)
1207 > XFASTINT (XWINDOW (w)->use_time)))
1208 best_window = w;
1209 break;
1211 case DELETE_OTHER_WINDOWS:
1212 if (XWINDOW (w) != XWINDOW (obj))
1213 Fdelete_window (w);
1214 break;
1216 case DELETE_BUFFER_WINDOWS:
1217 if (EQ (XWINDOW (w)->buffer, obj))
1219 /* If we're deleting the buffer displayed in the only window
1220 on the frame, find a new buffer to display there. */
1221 if (NILP (XWINDOW (w)->parent))
1223 Lisp_Object new_buffer;
1224 new_buffer = Fother_buffer (obj, Qnil);
1225 if (NILP (new_buffer))
1226 new_buffer
1227 = Fget_buffer_create (build_string ("*scratch*"));
1228 Fset_window_buffer (w, new_buffer);
1229 if (EQ (w, selected_window))
1230 Fset_buffer (XWINDOW (w)->buffer);
1232 else
1233 Fdelete_window (w);
1235 break;
1237 case GET_LARGEST_WINDOW:
1238 /* Ignore dedicated windows and minibuffers. */
1239 if (MINI_WINDOW_P (XWINDOW (w))
1240 || !NILP (XWINDOW (w)->dedicated))
1241 break;
1243 struct window *best_window_ptr = XWINDOW (best_window);
1244 struct window *w_ptr = XWINDOW (w);
1245 if (NILP (best_window) ||
1246 (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width))
1247 > (XFASTINT (best_window_ptr->height)
1248 * XFASTINT (best_window_ptr->width)))
1249 best_window = w;
1251 break;
1253 case UNSHOW_BUFFER:
1254 if (EQ (XWINDOW (w)->buffer, obj))
1256 /* Find another buffer to show in this window. */
1257 Lisp_Object another_buffer;
1258 another_buffer = Fother_buffer (obj, Qnil);
1259 if (NILP (another_buffer))
1260 another_buffer
1261 = Fget_buffer_create (build_string ("*scratch*"));
1262 Fset_window_buffer (w, another_buffer);
1263 if (EQ (w, selected_window))
1264 Fset_buffer (XWINDOW (w)->buffer);
1266 break;
1269 if (EQ (w, last_window))
1270 break;
1272 w = next_window;
1275 return best_window;
1278 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1279 "Return the window least recently selected or used for display.\n\
1280 If optional argument FRAME is `visible', search all visible frames.\n\
1281 If FRAME is t, search all frames.\n\
1282 If FRAME is nil, search only the selected frame.\n\
1283 If FRAME is a frame, search only that frame.")
1284 (frame)
1285 Lisp_Object frame;
1287 register Lisp_Object w;
1288 /* First try for a window that is full-width */
1289 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1290 if (!NILP (w) && !EQ (w, selected_window))
1291 return w;
1292 /* If none of them, try the rest */
1293 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1296 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1297 "Return the largest window in area.\n\
1298 If optional argument FRAME is `visible', search all visible frames.\n\
1299 If FRAME is t, search all frames.\n\
1300 If FRAME is nil, search only the selected frame.\n\
1301 If FRAME is a frame, search only that frame.")
1302 (frame)
1303 Lisp_Object frame;
1305 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1306 frame);
1309 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1310 "Return a window currently displaying BUFFER, or nil if none.\n\
1311 If optional argument FRAME is `visible', search all visible frames.\n\
1312 If FRAME is t, search all frames.\n\
1313 If FRAME is nil, search only the selected frame.\n\
1314 If FRAME is a frame, search only that frame.")
1315 (buffer, frame)
1316 Lisp_Object buffer, frame;
1318 buffer = Fget_buffer (buffer);
1319 if (XTYPE (buffer) == Lisp_Buffer)
1320 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1321 else
1322 return Qnil;
1325 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1326 0, 1, "",
1327 "Make WINDOW (or the selected window) fill its frame.\n\
1328 Only the frame WINDOW is on is affected.\n\
1329 This function tries to reduce display jumps\n\
1330 by keeping the text previously visible in WINDOW\n\
1331 in the same place on the frame. Doing this depends on\n\
1332 the value of (window-start WINDOW), so if calling this function\n\
1333 in a program gives strange scrolling, make sure the window-start\n\
1334 value is reasonable when this function is called.")
1335 (window)
1336 Lisp_Object window;
1338 struct window *w;
1339 struct buffer *obuf = current_buffer;
1340 int opoint;
1341 int top;
1343 if (NILP (window))
1344 window = selected_window;
1345 else
1346 CHECK_LIVE_WINDOW (window, 0);
1348 w = XWINDOW (window);
1349 top = XFASTINT (w->top);
1351 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1353 Fset_buffer (w->buffer);
1354 opoint = point;
1355 SET_PT (marker_position (w->start));
1356 /* Like Frecenter but avoid setting w->force_start. */
1357 Fvertical_motion (make_number (- (top - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w))))),
1358 window);
1359 Fset_marker (w->start, make_number (PT), w->buffer);
1360 w->start_at_line_beg = Fbolp ();
1362 SET_PT (opoint);
1363 set_buffer_internal (obuf);
1364 return Qnil;
1367 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1368 1, 2, "bDelete windows on (buffer): ",
1369 "Delete all windows showing BUFFER.\n\
1370 Optional second argument FRAME controls which frames are affected.\n\
1371 If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1372 If t, delete only windows showing BUFFER in the selected frame.\n\
1373 If `visible', delete all windows showing BUFFER in any visible frame.\n\
1374 If a frame, delete only windows showing BUFFER in that frame.")
1375 (buffer, frame)
1376 Lisp_Object buffer, frame;
1378 #ifdef MULTI_FRAME
1379 /* FRAME uses t and nil to mean the opposite of what window_loop
1380 expects. */
1381 if (! FRAMEP (frame))
1382 frame = NILP (frame) ? Qt : Qnil;
1383 #else
1384 frame = Qt;
1385 #endif
1387 if (!NILP (buffer))
1389 buffer = Fget_buffer (buffer);
1390 CHECK_BUFFER (buffer, 0);
1391 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1393 return Qnil;
1396 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1397 Sreplace_buffer_in_windows,
1398 1, 1, "bReplace buffer in windows: ",
1399 "Replace BUFFER with some other buffer in all windows showing it.")
1400 (buffer)
1401 Lisp_Object buffer;
1403 if (!NILP (buffer))
1405 buffer = Fget_buffer (buffer);
1406 CHECK_BUFFER (buffer, 0);
1407 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1409 return Qnil;
1412 /* Set the height of WINDOW and all its inferiors. */
1414 /* The smallest acceptable dimensions for a window. Anything smaller
1415 might crash Emacs. */
1416 #define MIN_SAFE_WINDOW_WIDTH (2)
1417 #define MIN_SAFE_WINDOW_HEIGHT (2)
1419 /* Make sure that window_min_height and window_min_width are
1420 not too small; if they are, set them to safe minima. */
1422 static void
1423 check_min_window_sizes ()
1425 /* Smaller values might permit a crash. */
1426 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1427 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1428 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1429 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1432 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1433 minimum allowable size. */
1434 void
1435 check_frame_size (frame, rows, cols)
1436 FRAME_PTR frame;
1437 int *rows, *cols;
1439 /* For height, we have to see:
1440 whether the frame has a minibuffer,
1441 whether it wants a mode line, and
1442 whether it has a menu bar. */
1443 int min_height =
1444 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1445 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
1446 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1447 if (FRAME_MENU_BAR_LINES (frame) > 0)
1448 min_height += FRAME_MENU_BAR_LINES (frame);
1450 if (*rows < min_height)
1451 *rows = min_height;
1452 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1453 *cols = MIN_SAFE_WINDOW_WIDTH;
1456 /* Normally the window is deleted if it gets too small.
1457 nodelete nonzero means do not do this.
1458 (The caller should check later and do so if appropriate) */
1460 set_window_height (window, height, nodelete)
1461 Lisp_Object window;
1462 int height;
1463 int nodelete;
1465 register struct window *w = XWINDOW (window);
1466 register struct window *c;
1467 int oheight = XFASTINT (w->height);
1468 int top, pos, lastbot, opos, lastobot;
1469 Lisp_Object child;
1471 check_min_window_sizes ();
1473 if (!nodelete
1474 && ! NILP (w->parent)
1475 && height < window_min_height)
1477 Fdelete_window (window);
1478 return;
1481 XFASTINT (w->last_modified) = 0;
1482 windows_or_buffers_changed++;
1483 XFASTINT (w->height) = height;
1484 if (!NILP (w->hchild))
1486 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1488 XWINDOW (child)->top = w->top;
1489 set_window_height (child, height, nodelete);
1492 else if (!NILP (w->vchild))
1494 lastbot = top = XFASTINT (w->top);
1495 lastobot = 0;
1496 for (child = w->vchild; !NILP (child); child = c->next)
1498 c = XWINDOW (child);
1500 opos = lastobot + XFASTINT (c->height);
1502 XFASTINT (c->top) = lastbot;
1504 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1506 /* Avoid confusion: inhibit deletion of child if becomes too small */
1507 set_window_height (child, pos + top - lastbot, 1);
1509 /* Now advance child to next window,
1510 and set lastbot if child was not just deleted. */
1511 lastbot = pos + top;
1512 lastobot = opos;
1514 /* Now delete any children that became too small. */
1515 if (!nodelete)
1516 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1518 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1523 /* Recursively set width of WINDOW and its inferiors. */
1525 set_window_width (window, width, nodelete)
1526 Lisp_Object window;
1527 int width;
1528 int nodelete;
1530 register struct window *w = XWINDOW (window);
1531 register struct window *c;
1532 int owidth = XFASTINT (w->width);
1533 int left, pos, lastright, opos, lastoright;
1534 Lisp_Object child;
1536 if (!nodelete && width < window_min_width)
1538 Fdelete_window (window);
1539 return;
1542 XFASTINT (w->last_modified) = 0;
1543 windows_or_buffers_changed++;
1544 XFASTINT (w->width) = width;
1545 if (!NILP (w->vchild))
1547 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1549 XWINDOW (child)->left = w->left;
1550 set_window_width (child, width, nodelete);
1553 else if (!NILP (w->hchild))
1555 lastright = left = XFASTINT (w->left);
1556 lastoright = 0;
1557 for (child = w->hchild; !NILP (child); child = c->next)
1559 c = XWINDOW (child);
1561 opos = lastoright + XFASTINT (c->width);
1563 XFASTINT (c->left) = lastright;
1565 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1567 /* Inhibit deletion for becoming too small */
1568 set_window_width (child, pos + left - lastright, 1);
1570 /* Now advance child to next window,
1571 and set lastright if child was not just deleted. */
1572 lastright = pos + left, lastoright = opos;
1574 /* Delete children that became too small */
1575 if (!nodelete)
1576 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1578 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1583 int window_select_count;
1585 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1586 "Make WINDOW display BUFFER as its contents.\n\
1587 BUFFER can be a buffer or buffer name.")
1588 (window, buffer)
1589 register Lisp_Object window, buffer;
1591 register Lisp_Object tem;
1592 register struct window *w = decode_window (window);
1594 buffer = Fget_buffer (buffer);
1595 CHECK_BUFFER (buffer, 1);
1597 if (NILP (XBUFFER (buffer)->name))
1598 error ("Attempt to display deleted buffer");
1600 tem = w->buffer;
1601 if (NILP (tem))
1602 error ("Window is deleted");
1603 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1604 is first being set up. */
1606 if (!NILP (w->dedicated) && !EQ (tem, buffer))
1607 error ("Window is dedicated to %s\n", tem);
1609 unshow_buffer (w);
1612 w->buffer = buffer;
1613 w->window_end_pos = 0;
1614 w->window_end_valid = Qnil;
1615 w->hscroll = 0;
1616 Fset_marker (w->pointm,
1617 make_number (BUF_PT (XBUFFER (buffer))),
1618 buffer);
1619 set_marker_restricted (w->start,
1620 make_number (XBUFFER (buffer)->last_window_start),
1621 buffer);
1622 w->start_at_line_beg = Qnil;
1623 w->force_start = Qnil;
1624 XFASTINT (w->last_modified) = 0;
1625 windows_or_buffers_changed++;
1626 if (EQ (window, selected_window))
1627 Fset_buffer (buffer);
1629 return Qnil;
1632 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1633 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1634 The main editor command loop selects the buffer of the selected window\n\
1635 before each command.")
1636 (window)
1637 register Lisp_Object window;
1639 register struct window *w;
1640 register struct window *ow = XWINDOW (selected_window);
1642 CHECK_LIVE_WINDOW (window, 0);
1644 w = XWINDOW (window);
1646 if (NILP (w->buffer))
1647 error ("Trying to select deleted window or non-leaf window");
1649 XFASTINT (w->use_time) = ++window_select_count;
1650 if (EQ (window, selected_window))
1651 return window;
1653 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1654 ow->buffer);
1656 selected_window = window;
1657 #ifdef MULTI_FRAME
1658 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
1660 XFRAME (WINDOW_FRAME (w))->selected_window = window;
1661 Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
1663 else
1664 selected_frame->selected_window = window;
1665 #endif
1667 record_buffer (w->buffer);
1668 Fset_buffer (w->buffer);
1670 /* Go to the point recorded in the window.
1671 This is important when the buffer is in more
1672 than one window. It also matters when
1673 redisplay_window has altered point after scrolling,
1674 because it makes the change only in the window. */
1676 register int new_point = marker_position (w->pointm);
1677 if (new_point < BEGV)
1678 SET_PT (BEGV);
1679 if (new_point > ZV)
1680 SET_PT (ZV);
1681 else
1682 SET_PT (new_point);
1685 windows_or_buffers_changed++;
1686 return window;
1689 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
1690 "BDisplay buffer: \nP",
1691 "Make BUFFER appear in some window but don't select it.\n\
1692 BUFFER can be a buffer or a buffer name.\n\
1693 If BUFFER is shown already in some window, just use that one,\n\
1694 unless the window is the selected window and the optional second\n\
1695 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
1696 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
1697 Returns the window displaying BUFFER.")
1698 (buffer, not_this_window)
1699 register Lisp_Object buffer, not_this_window;
1701 register Lisp_Object window;
1703 buffer = Fget_buffer (buffer);
1704 CHECK_BUFFER (buffer, 0);
1706 if (!NILP (Vdisplay_buffer_function))
1707 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1709 if (NILP (not_this_window)
1710 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1711 return selected_window;
1713 /* If pop_up_frames,
1714 look for a window showing BUFFER on any visible frame. */
1715 window = Fget_buffer_window (buffer, pop_up_frames ? Qvisible : Qnil);
1716 if (!NILP (window)
1717 && (NILP (not_this_window) || !EQ (window, selected_window)))
1718 return window;
1720 #ifdef MULTI_FRAME
1721 /* If there are no frames open that have more than a minibuffer,
1722 we need to create a new frame. */
1723 if (pop_up_frames || last_nonminibuf_frame == 0)
1725 window
1726 = Fframe_selected_window (call0 (Vpop_up_frame_function));
1727 Fset_window_buffer (window, buffer);
1728 #if 0
1729 Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
1730 #endif
1731 return window;
1733 #endif /* MULTI_FRAME */
1735 if (pop_up_windows
1736 #ifdef MULTI_FRAME
1737 || FRAME_MINIBUF_ONLY_P (selected_frame)
1738 #endif
1741 Lisp_Object frames;
1743 frames = Qnil;
1744 #ifdef MULTI_FRAME
1745 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1746 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
1747 #endif
1748 /* Don't try to create a window if would get an error */
1749 if (split_height_threshold < window_min_height << 1)
1750 split_height_threshold = window_min_height << 1;
1752 window = Fget_largest_window (frames);
1754 if (!NILP (window)
1755 && window_height (window) >= split_height_threshold
1756 && (XFASTINT (XWINDOW (window)->width)
1757 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
1758 window = Fsplit_window (window, Qnil, Qnil);
1759 else
1761 window = Fget_lru_window (frames);
1762 if ((EQ (window, selected_window)
1763 || EQ (XWINDOW (window)->parent, Qnil))
1764 && window_height (window) >= window_min_height << 1)
1765 window = Fsplit_window (window, Qnil, Qnil);
1768 else
1769 window = Fget_lru_window (Qnil);
1771 Fset_window_buffer (window, buffer);
1772 return window;
1775 void
1776 temp_output_buffer_show (buf)
1777 register Lisp_Object buf;
1779 register struct buffer *old = current_buffer;
1780 register Lisp_Object window;
1781 register struct window *w;
1783 Fset_buffer (buf);
1784 XBUFFER (buf)->save_modified = MODIFF;
1785 BEGV = BEG;
1786 ZV = Z;
1787 SET_PT (BEG);
1788 clip_changed = 1;
1789 set_buffer_internal (old);
1791 if (!EQ (Vtemp_buffer_show_function, Qnil))
1792 call1 (Vtemp_buffer_show_function, buf);
1793 else
1795 window = Fdisplay_buffer (buf, Qnil);
1797 #ifdef MULTI_FRAME
1798 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1799 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1800 #endif /* MULTI_FRAME */
1801 Vminibuf_scroll_window = window;
1802 w = XWINDOW (window);
1803 XFASTINT (w->hscroll) = 0;
1804 set_marker_restricted (w->start, make_number (1), buf);
1805 set_marker_restricted (w->pointm, make_number (1), buf);
1809 static
1810 make_dummy_parent (window)
1811 Lisp_Object window;
1813 register Lisp_Object old, new;
1814 register struct window *o, *p;
1816 old = window;
1817 XSETTYPE (old, Lisp_Vector);
1818 new = Fcopy_sequence (old);
1819 XSETTYPE (new, Lisp_Window);
1821 o = XWINDOW (old);
1822 p = XWINDOW (new);
1823 XFASTINT (p->sequence_number) = ++sequence_number;
1825 /* Put new into window structure in place of window */
1826 replace_window (window, new);
1828 o->next = Qnil;
1829 o->prev = Qnil;
1830 o->vchild = Qnil;
1831 o->hchild = Qnil;
1832 o->parent = new;
1834 p->start = Qnil;
1835 p->pointm = Qnil;
1836 p->buffer = Qnil;
1839 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1840 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1841 WINDOW defaults to selected one and SIZE to half its size.\n\
1842 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1843 and put SIZE columns in the first of the pair.")
1844 (window, chsize, horflag)
1845 Lisp_Object window, chsize, horflag;
1847 register Lisp_Object new;
1848 register struct window *o, *p;
1849 register int size;
1851 if (NILP (window))
1852 window = selected_window;
1853 else
1854 CHECK_LIVE_WINDOW (window, 0);
1856 o = XWINDOW (window);
1858 if (NILP (chsize))
1860 if (!NILP (horflag))
1861 /* Round odd size up, since this is for the left-hand window,
1862 and it will lose a column for the separators. */
1863 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1864 else
1865 size = XFASTINT (o->height) >> 1;
1867 else
1869 CHECK_NUMBER (chsize, 1);
1870 size = XINT (chsize);
1873 if (MINI_WINDOW_P (o))
1874 error ("Attempt to split minibuffer window");
1875 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1876 error ("Attempt to split unsplittable frame");
1878 check_min_window_sizes ();
1880 if (NILP (horflag))
1882 if (size < window_min_height
1883 || size + window_min_height > XFASTINT (o->height))
1884 args_out_of_range_3 (window, chsize, horflag);
1885 if (NILP (o->parent)
1886 || NILP (XWINDOW (o->parent)->vchild))
1888 make_dummy_parent (window);
1889 new = o->parent;
1890 XWINDOW (new)->vchild = window;
1893 else
1895 if (size < window_min_width
1896 || size + window_min_width > XFASTINT (o->width))
1897 args_out_of_range_3 (window, chsize, horflag);
1898 if (NILP (o->parent)
1899 || NILP (XWINDOW (o->parent)->hchild))
1901 make_dummy_parent (window);
1902 new = o->parent;
1903 XWINDOW (new)->hchild = window;
1907 /* Now we know that window's parent is a vertical combination
1908 if we are dividing vertically, or a horizontal combination
1909 if we are making side-by-side windows */
1911 windows_or_buffers_changed++;
1912 new = make_window ();
1913 p = XWINDOW (new);
1915 p->frame = o->frame;
1916 p->next = o->next;
1917 if (!NILP (p->next))
1918 XWINDOW (p->next)->prev = new;
1919 p->prev = window;
1920 o->next = new;
1921 p->parent = o->parent;
1922 p->buffer = Qt;
1924 Fset_window_buffer (new, o->buffer);
1926 /* Apportion the available frame space among the two new windows */
1928 if (!NILP (horflag))
1930 p->height = o->height;
1931 p->top = o->top;
1932 XFASTINT (p->width) = XFASTINT (o->width) - size;
1933 XFASTINT (o->width) = size;
1934 XFASTINT (p->left) = XFASTINT (o->left) + size;
1936 else
1938 p->left = o->left;
1939 p->width = o->width;
1940 XFASTINT (p->height) = XFASTINT (o->height) - size;
1941 XFASTINT (o->height) = size;
1942 XFASTINT (p->top) = XFASTINT (o->top) + size;
1945 return new;
1948 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1949 "Make current window ARG lines bigger.\n\
1950 From program, optional second arg non-nil means grow sideways ARG columns.")
1951 (n, side)
1952 register Lisp_Object n, side;
1954 CHECK_NUMBER (n, 0);
1955 change_window_height (XINT (n), !NILP (side));
1956 return Qnil;
1959 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1960 "Make current window ARG lines smaller.\n\
1961 From program, optional second arg non-nil means shrink sideways ARG columns.")
1962 (n, side)
1963 register Lisp_Object n, side;
1965 CHECK_NUMBER (n, 0);
1966 change_window_height (-XINT (n), !NILP (side));
1967 return Qnil;
1971 window_height (window)
1972 Lisp_Object window;
1974 register struct window *p = XWINDOW (window);
1975 return XFASTINT (p->height);
1979 window_width (window)
1980 Lisp_Object window;
1982 register struct window *p = XWINDOW (window);
1983 return XFASTINT (p->width);
1986 #define MINSIZE(w) \
1987 (widthflag \
1988 ? window_min_width \
1989 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
1991 #define CURBEG(w) \
1992 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
1994 #define CURSIZE(w) \
1995 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
1997 /* Unlike set_window_height, this function
1998 also changes the heights of the siblings so as to
1999 keep everything consistent. */
2001 change_window_height (delta, widthflag)
2002 register int delta;
2003 int widthflag;
2005 register Lisp_Object parent;
2006 Lisp_Object window;
2007 register struct window *p;
2008 int *sizep;
2009 int (*sizefun) () = widthflag ? window_width : window_height;
2010 register int (*setsizefun) () = (widthflag
2011 ? set_window_width
2012 : set_window_height);
2014 check_min_window_sizes ();
2016 window = selected_window;
2017 while (1)
2019 p = XWINDOW (window);
2020 parent = p->parent;
2021 if (NILP (parent))
2023 if (widthflag)
2024 error ("No other window to side of this one");
2025 break;
2027 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2028 : !NILP (XWINDOW (parent)->vchild))
2029 break;
2030 window = parent;
2033 sizep = &CURSIZE (window);
2035 if (*sizep + delta < MINSIZE (window))
2037 Fdelete_window (window);
2038 return;
2042 register int maxdelta;
2044 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2045 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2046 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
2047 /* This is a frame with only one window, a minibuffer-only
2048 or a minibufferless frame. */
2049 : (delta = 0));
2051 if (delta > maxdelta)
2052 /* This case traps trying to make the minibuffer
2053 the full frame, or make the only window aside from the
2054 minibuffer the full frame. */
2055 delta = maxdelta;
2057 if (delta == 0)
2058 return;
2061 if (!NILP (p->next) &&
2062 (*sizefun) (p->next) - delta >= MINSIZE (p->next))
2064 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
2065 (*setsizefun) (window, *sizep + delta, 0);
2066 CURBEG (p->next) += delta;
2067 /* This does not change size of p->next,
2068 but it propagates the new top edge to its children */
2069 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
2071 else if (!NILP (p->prev) &&
2072 (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
2074 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
2075 CURBEG (window) -= delta;
2076 (*setsizefun) (window, *sizep + delta, 0);
2078 else
2080 register int delta1;
2081 register int opht = (*sizefun) (parent);
2083 /* If trying to grow this window to or beyond size of the parent,
2084 make delta1 so big that, on shrinking back down,
2085 all the siblings end up with less than one line and are deleted. */
2086 if (opht <= *sizep + delta)
2087 delta1 = opht * opht * 2;
2088 /* Otherwise, make delta1 just right so that if we add delta1
2089 lines to this window and to the parent, and then shrink
2090 the parent back to its original size, the new proportional
2091 size of this window will increase by delta. */
2092 else
2093 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2095 /* Add delta1 lines or columns to this window, and to the parent,
2096 keeping things consistent while not affecting siblings. */
2097 CURSIZE (parent) = opht + delta1;
2098 (*setsizefun) (window, *sizep + delta1, 0);
2100 /* Squeeze out delta1 lines or columns from our parent,
2101 shriking this window and siblings proportionately.
2102 This brings parent back to correct size.
2103 Delta1 was calculated so this makes this window the desired size,
2104 taking it all out of the siblings. */
2105 (*setsizefun) (parent, opht, 0);
2108 XFASTINT (p->last_modified) = 0;
2110 #undef MINSIZE
2111 #undef CURBEG
2112 #undef CURSIZE
2115 /* Return number of lines of text (not counting mode line) in W. */
2118 window_internal_height (w)
2119 struct window *w;
2121 int ht = XFASTINT (w->height);
2123 if (MINI_WINDOW_P (w))
2124 return ht;
2126 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2127 || !NILP (w->next) || !NILP (w->prev)
2128 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
2129 return ht - 1;
2131 return ht;
2135 /* Return the number of columns in W.
2136 Don't count columns occupied by scroll bars or the vertical bar
2137 separating W from the sibling to its right. */
2139 window_internal_width (w)
2140 struct window *w;
2142 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2143 int left = XINT (w->left);
2144 int width = XINT (w->width);
2146 /* If this window is flush against the right edge of the frame, its
2147 internal width is its full width. */
2148 if (left + width >= FRAME_WIDTH (f))
2149 return width;
2151 /* If we are not flush right, then our rightmost columns are
2152 occupied by some sort of separator. */
2154 /* Scroll bars occupy a few columns. */
2155 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2156 return width - VERTICAL_SCROLL_BAR_WIDTH;
2158 /* The column of `|' characters separating side-by-side windows
2159 occupies one column only. */
2160 return width - 1;
2164 /* Scroll contents of window WINDOW up N lines. */
2166 void
2167 window_scroll (window, n, noerror)
2168 Lisp_Object window;
2169 int n;
2170 int noerror;
2172 register struct window *w = XWINDOW (window);
2173 register int opoint = point;
2174 register int pos;
2175 register int ht = window_internal_height (w);
2176 register Lisp_Object tem;
2177 int lose;
2178 Lisp_Object bolp, nmoved;
2180 XFASTINT (tem) = point;
2181 tem = Fpos_visible_in_window_p (tem, window);
2183 if (NILP (tem))
2185 Fvertical_motion (make_number (- (ht / 2)), window);
2186 XFASTINT (tem) = point;
2187 Fset_marker (w->start, tem, w->buffer);
2188 w->force_start = Qt;
2191 SET_PT (marker_position (w->start));
2192 lose = n < 0 && point == BEGV;
2193 Fvertical_motion (make_number (n), window);
2194 pos = point;
2195 bolp = Fbolp ();
2196 SET_PT (opoint);
2198 if (lose)
2200 if (noerror)
2201 return;
2202 else
2203 Fsignal (Qbeginning_of_buffer, Qnil);
2206 if (pos < ZV)
2208 set_marker_restricted (w->start, make_number (pos), w->buffer);
2209 w->start_at_line_beg = bolp;
2210 w->update_mode_line = Qt;
2211 XFASTINT (w->last_modified) = 0;
2212 if (pos > opoint)
2213 SET_PT (pos);
2214 if (n < 0)
2216 SET_PT (pos);
2217 tem = Fvertical_motion (make_number (ht), window);
2218 if (point > opoint || XFASTINT (tem) < ht)
2219 SET_PT (opoint);
2220 else
2221 Fvertical_motion (make_number (-1), window);
2224 else
2226 if (noerror)
2227 return;
2228 else
2229 Fsignal (Qend_of_buffer, Qnil);
2233 /* This is the guts of Fscroll_up and Fscroll_down. */
2235 static void
2236 scroll_command (n, direction)
2237 register Lisp_Object n;
2238 int direction;
2240 register int defalt;
2241 int count = specpdl_ptr - specpdl;
2243 /* If selected window's buffer isn't current, make it current for the moment.
2244 But don't screw up if window_scroll gets an error. */
2245 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2247 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2248 Fset_buffer (XWINDOW (selected_window)->buffer);
2251 defalt = (window_internal_height (XWINDOW (selected_window))
2252 - next_screen_context_lines);
2253 defalt = direction * (defalt < 1 ? 1 : defalt);
2255 if (NILP (n))
2256 window_scroll (selected_window, defalt, 0);
2257 else if (EQ (n, Qminus))
2258 window_scroll (selected_window, - defalt, 0);
2259 else
2261 n = Fprefix_numeric_value (n);
2262 window_scroll (selected_window, XINT (n) * direction, 0);
2265 unbind_to (count, Qnil);
2268 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2269 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2270 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2271 Negative ARG means scroll downward.\n\
2272 When calling from a program, supply a number as argument or nil.")
2274 Lisp_Object n;
2276 scroll_command (n, 1);
2277 return Qnil;
2280 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2281 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2282 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2283 Negative ARG means scroll upward.\n\
2284 When calling from a program, supply a number as argument or nil.")
2286 Lisp_Object n;
2288 scroll_command (n, -1);
2289 return Qnil;
2292 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2293 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2294 The next window is the one below the current one; or the one at the top\n\
2295 if the current one is at the bottom. Negative ARG means scroll downward.\n\
2296 When calling from a program, supply a number as argument or nil.\n\
2298 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2299 specifies the window to scroll.\n\
2300 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2301 showing that buffer, popping the buffer up if necessary.")
2303 register Lisp_Object n;
2305 register Lisp_Object window;
2306 register int ht;
2307 register struct window *w;
2308 register int count = specpdl_ptr - specpdl;
2310 if (MINI_WINDOW_P (XWINDOW (selected_window))
2311 && !NILP (Vminibuf_scroll_window))
2312 window = Vminibuf_scroll_window;
2313 /* If buffer is specified, scroll that buffer. */
2314 else if (!NILP (Vother_window_scroll_buffer))
2316 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
2317 if (NILP (window))
2318 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2320 else
2322 /* Nothing specified; look for a neighboring window on the same
2323 frame. */
2324 window = Fnext_window (selected_window, Qnil, Qnil);
2326 if (EQ (window, selected_window))
2327 /* That didn't get us anywhere; look for a window on another
2328 visible frame. */
2330 window = Fnext_window (window, Qnil, Qt);
2331 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2332 && ! EQ (window, selected_window));
2335 CHECK_LIVE_WINDOW (window, 0);
2337 if (EQ (window, selected_window))
2338 error ("There is no other window");
2340 w = XWINDOW (window);
2341 ht = window_internal_height (w);
2343 /* Don't screw up if window_scroll gets an error. */
2344 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2346 Fset_buffer (w->buffer);
2347 SET_PT (marker_position (w->pointm));
2349 if (NILP (n))
2350 window_scroll (window, ht - next_screen_context_lines, 1);
2351 else if (EQ (n, Qminus))
2352 window_scroll (window, next_screen_context_lines - ht, 1);
2353 else
2355 if (XTYPE (n) == Lisp_Cons)
2356 n = Fcar (n);
2357 CHECK_NUMBER (n, 0);
2358 window_scroll (window, XINT (n), 1);
2361 Fset_marker (w->pointm, make_number (point), Qnil);
2362 unbind_to (count, Qnil);
2364 return Qnil;
2367 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
2368 "Scroll selected window display ARG columns left.\n\
2369 Default for ARG is window width minus 2.")
2370 (arg)
2371 register Lisp_Object arg;
2374 if (NILP (arg))
2375 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
2376 else
2377 arg = Fprefix_numeric_value (arg);
2379 return
2380 Fset_window_hscroll (selected_window,
2381 make_number (XINT (XWINDOW (selected_window)->hscroll)
2382 + XINT (arg)));
2385 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
2386 "Scroll selected window display ARG columns right.\n\
2387 Default for ARG is window width minus 2.")
2388 (arg)
2389 register Lisp_Object arg;
2391 if (NILP (arg))
2392 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
2393 else
2394 arg = Fprefix_numeric_value (arg);
2396 return
2397 Fset_window_hscroll (selected_window,
2398 make_number (XINT (XWINDOW (selected_window)->hscroll)
2399 - XINT (arg)));
2402 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
2403 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2404 The desired position of point is always relative to the current window.\n\
2405 Just C-u as prefix means put point in the center of the window.\n\
2406 No arg (i.e., it is nil) erases the entire frame and then\n\
2407 redraws with point in the center of the current window.")
2409 register Lisp_Object n;
2411 register struct window *w = XWINDOW (selected_window);
2412 register int ht = window_internal_height (w);
2413 register int opoint = point;
2414 Lisp_Object window;
2416 if (NILP (n))
2418 extern int frame_garbaged;
2420 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
2421 XFASTINT (n) = ht / 2;
2423 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2425 XFASTINT (n) = ht / 2;
2427 else
2429 n = Fprefix_numeric_value (n);
2430 CHECK_NUMBER (n, 0);
2433 if (XINT (n) < 0)
2434 XSETINT (n, XINT (n) + ht);
2436 XSETINT (n, - XINT (n));
2438 XSET (window, Lisp_Window, w);
2439 Fvertical_motion (n, window);
2440 Fset_marker (w->start, make_number (point), w->buffer);
2441 w->start_at_line_beg = Fbolp ();
2443 SET_PT (opoint);
2444 w->force_start = Qt;
2446 return Qnil;
2449 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2450 1, 1, "P",
2451 "Position point relative to window.\n\
2452 With no argument, position text at center of window.\n\
2453 An argument specifies frame line; zero means top of window,\n\
2454 negative means relative to bottom of window.")
2455 (arg)
2456 register Lisp_Object arg;
2458 register struct window *w = XWINDOW (selected_window);
2459 register int height = window_internal_height (w);
2460 register int start;
2461 Lisp_Object window;
2463 if (NILP (arg))
2464 XFASTINT (arg) = height / 2;
2465 else
2467 arg = Fprefix_numeric_value (arg);
2468 if (XINT (arg) < 0)
2469 XSETINT (arg, XINT (arg) + height);
2472 start = marker_position (w->start);
2473 XSET (window, Lisp_Window, w);
2474 if (start < BEGV || start > ZV)
2476 Fvertical_motion (make_number (- (height / 2)), window);
2477 Fset_marker (w->start, make_number (point), w->buffer);
2478 w->start_at_line_beg = Fbolp ();
2479 w->force_start = Qt;
2481 else
2482 SET_PT (start);
2484 return Fvertical_motion (arg, window);
2487 struct save_window_data
2489 int size_from_Lisp_Vector_struct;
2490 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2491 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
2492 Lisp_Object selected_frame;
2493 Lisp_Object current_window;
2494 Lisp_Object current_buffer;
2495 Lisp_Object minibuf_scroll_window;
2496 Lisp_Object root_window;
2497 Lisp_Object focus_frame;
2498 /* A vector, interpreted as a struct saved_window */
2499 Lisp_Object saved_windows;
2502 /* Arg to Fmake_vector */
2503 #define SAVE_WINDOW_DATA_SIZE \
2504 ((sizeof (struct save_window_data) \
2505 - (sizeof (struct Lisp_Vector) \
2506 /* Don't count the contents member of the struct Lisp_Vector */ \
2507 - sizeof (Lisp_Object))) \
2508 / sizeof (Lisp_Object))
2510 /* This is saved as a Lisp_Vector */
2511 struct saved_window
2513 /* these first two must agree with struct Lisp_Vector in lisp.h */
2514 int size_from_Lisp_Vector_struct;
2515 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2517 Lisp_Object window;
2518 Lisp_Object buffer, start, pointm, mark;
2519 Lisp_Object left, top, width, height, hscroll;
2520 Lisp_Object parent, prev;
2521 Lisp_Object start_at_line_beg;
2522 Lisp_Object display_table;
2524 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2526 #define SAVED_WINDOW_N(swv,n) \
2527 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2529 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2530 "T if OBJECT is a window-configration object.")
2531 (obj)
2532 Lisp_Object obj;
2534 if (XTYPE (obj) == Lisp_Window_Configuration)
2535 return Qt;
2536 return Qnil;
2540 DEFUN ("set-window-configuration", Fset_window_configuration,
2541 Sset_window_configuration, 1, 1, 0,
2542 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2543 CONFIGURATION must be a value previously returned\n\
2544 by `current-window-configuration' (which see).")
2545 (configuration)
2546 Lisp_Object configuration;
2548 register struct save_window_data *data;
2549 struct Lisp_Vector *saved_windows;
2550 Lisp_Object new_current_buffer;
2551 Lisp_Object frame;
2552 FRAME_PTR f;
2554 while (XTYPE (configuration) != Lisp_Window_Configuration)
2556 configuration = wrong_type_argument (intern ("window-configuration-p"),
2557 configuration);
2560 data = (struct save_window_data *) XVECTOR (configuration);
2561 saved_windows = XVECTOR (data->saved_windows);
2563 new_current_buffer = data->current_buffer;
2564 if (NILP (XBUFFER (new_current_buffer)->name))
2565 new_current_buffer = Qnil;
2567 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2568 f = XFRAME (frame);
2570 /* If f is a dead frame, don't bother rebuilding its window tree.
2571 However, there is other stuff we should still try to do below. */
2572 if (FRAME_LIVE_P (f))
2574 register struct window *w;
2575 register struct saved_window *p;
2576 int k;
2578 /* If the frame has been resized since this window configuration was
2579 made, we change the frame to the size specified in the
2580 configuration, restore the configuration, and then resize it
2581 back. We keep track of the prevailing height in these variables. */
2582 int previous_frame_height = FRAME_HEIGHT (f);
2583 int previous_frame_width = FRAME_WIDTH (f);
2584 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
2586 if (XFASTINT (data->frame_height) != previous_frame_height
2587 || XFASTINT (data->frame_width) != previous_frame_width)
2588 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
2589 if (XFASTINT (data->frame_menu_bar_lines)
2590 != previous_frame_menu_bar_lines)
2591 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
2593 windows_or_buffers_changed++;
2595 /* Kludge Alert!
2596 Mark all windows now on frame as "deleted".
2597 Restoring the new configuration "undeletes" any that are in it.
2599 Save their current buffers in their height fields, since we may
2600 need it later, if a buffer saved in the configuration is now
2601 dead. */
2602 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2604 for (k = 0; k < saved_windows->size; k++)
2606 p = SAVED_WINDOW_N (saved_windows, k);
2607 w = XWINDOW (p->window);
2608 w->next = Qnil;
2610 if (!NILP (p->parent))
2611 w->parent = SAVED_WINDOW_N (saved_windows,
2612 XFASTINT (p->parent))->window;
2613 else
2614 w->parent = Qnil;
2616 if (!NILP (p->prev))
2618 w->prev = SAVED_WINDOW_N (saved_windows,
2619 XFASTINT (p->prev))->window;
2620 XWINDOW (w->prev)->next = p->window;
2622 else
2624 w->prev = Qnil;
2625 if (!NILP (w->parent))
2627 if (EQ (p->width, XWINDOW (w->parent)->width))
2629 XWINDOW (w->parent)->vchild = p->window;
2630 XWINDOW (w->parent)->hchild = Qnil;
2632 else
2634 XWINDOW (w->parent)->hchild = p->window;
2635 XWINDOW (w->parent)->vchild = Qnil;
2640 /* If we squirreled away the buffer in the window's height,
2641 restore it now. */
2642 if (XTYPE (w->height) == Lisp_Buffer)
2643 w->buffer = w->height;
2644 w->left = p->left;
2645 w->top = p->top;
2646 w->width = p->width;
2647 w->height = p->height;
2648 w->hscroll = p->hscroll;
2649 w->display_table = p->display_table;
2650 XFASTINT (w->last_modified) = 0;
2652 /* Reinstall the saved buffer and pointers into it. */
2653 if (NILP (p->buffer))
2654 w->buffer = p->buffer;
2655 else
2657 if (!NILP (XBUFFER (p->buffer)->name))
2658 /* If saved buffer is alive, install it. */
2660 w->buffer = p->buffer;
2661 w->start_at_line_beg = p->start_at_line_beg;
2662 set_marker_restricted (w->start,
2663 Fmarker_position (p->start),
2664 w->buffer);
2665 set_marker_restricted (w->pointm,
2666 Fmarker_position (p->pointm),
2667 w->buffer);
2668 Fset_marker (XBUFFER (w->buffer)->mark,
2669 Fmarker_position (p->mark), w->buffer);
2671 /* As documented in Fcurrent_window_configuration, don't
2672 save the location of point in the buffer which was current
2673 when the window configuration was recorded. */
2674 if (!EQ (p->buffer, new_current_buffer) &&
2675 XBUFFER (p->buffer) == current_buffer)
2676 Fgoto_char (w->pointm);
2678 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
2679 /* Else unless window has a live buffer, get one. */
2681 w->buffer = Fcdr (Fcar (Vbuffer_alist));
2682 /* This will set the markers to beginning of visible
2683 range. */
2684 set_marker_restricted (w->start, make_number (0), w->buffer);
2685 set_marker_restricted (w->pointm, make_number (0),w->buffer);
2686 w->start_at_line_beg = Qt;
2688 else
2689 /* Keeping window's old buffer; make sure the markers
2690 are real. */
2692 /* Set window markers at start of visible range. */
2693 if (XMARKER (w->start)->buffer == 0)
2694 set_marker_restricted (w->start, make_number (0),
2695 w->buffer);
2696 if (XMARKER (w->pointm)->buffer == 0)
2697 set_marker_restricted (w->pointm,
2698 (make_number
2699 (BUF_PT (XBUFFER (w->buffer)))),
2700 w->buffer);
2701 w->start_at_line_beg = Qt;
2706 FRAME_ROOT_WINDOW (f) = data->root_window;
2707 Fselect_window (data->current_window);
2709 #ifdef MULTI_FRAME
2710 if (NILP (data->focus_frame)
2711 || (XTYPE (data->focus_frame) == Lisp_Frame
2712 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
2713 Fredirect_frame_focus (frame, data->focus_frame);
2714 #endif
2716 #if 0 /* I don't understand why this is needed, and it causes problems
2717 when the frame's old selected window has been deleted. */
2718 #ifdef MULTI_FRAME
2719 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
2720 Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
2721 #endif
2722 #endif
2724 /* Set the screen height to the value it had before this function. */
2725 if (previous_frame_height != FRAME_HEIGHT (f)
2726 || previous_frame_width != FRAME_WIDTH (f))
2727 change_frame_size (f, previous_frame_height, previous_frame_width,
2728 0, 0);
2729 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
2730 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
2733 #ifdef MULTI_FRAME
2734 /* Fselect_window will have made f the selected frame, so we
2735 reselect the proper frame here. Fhandle_switch_frame will change the
2736 selected window too, but that doesn't make the call to
2737 Fselect_window above totally superfluous; it still sets f's
2738 selected window. */
2739 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
2740 Fhandle_switch_frame (data->selected_frame, Qnil);
2741 #endif
2743 if (!NILP (new_current_buffer))
2744 Fset_buffer (new_current_buffer);
2746 Vminibuf_scroll_window = data->minibuf_scroll_window;
2747 return (Qnil);
2750 /* Mark all windows now on frame as deleted
2751 by setting their buffers to nil. */
2753 void
2754 delete_all_subwindows (w)
2755 register struct window *w;
2757 if (!NILP (w->next))
2758 delete_all_subwindows (XWINDOW (w->next));
2759 if (!NILP (w->vchild))
2760 delete_all_subwindows (XWINDOW (w->vchild));
2761 if (!NILP (w->hchild))
2762 delete_all_subwindows (XWINDOW (w->hchild));
2764 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
2766 /* We set all three of these fields to nil, to make sure that we can
2767 distinguish this dead window from any live window. Live leaf
2768 windows will have buffer set, and combination windows will have
2769 vchild or hchild set. */
2770 w->buffer = Qnil;
2771 w->vchild = Qnil;
2772 w->hchild = Qnil;
2775 static int
2776 count_windows (window)
2777 register struct window *window;
2779 register int count = 1;
2780 if (!NILP (window->next))
2781 count += count_windows (XWINDOW (window->next));
2782 if (!NILP (window->vchild))
2783 count += count_windows (XWINDOW (window->vchild));
2784 if (!NILP (window->hchild))
2785 count += count_windows (XWINDOW (window->hchild));
2786 return count;
2789 static int
2790 save_window_save (window, vector, i)
2791 Lisp_Object window;
2792 struct Lisp_Vector *vector;
2793 int i;
2795 register struct saved_window *p;
2796 register struct window *w;
2797 register Lisp_Object tem;
2799 for (;!NILP (window); window = w->next)
2801 p = SAVED_WINDOW_N (vector, i);
2802 w = XWINDOW (window);
2804 XFASTINT (w->temslot) = i++;
2805 p->window = window;
2806 p->buffer = w->buffer;
2807 p->left = w->left;
2808 p->top = w->top;
2809 p->width = w->width;
2810 p->height = w->height;
2811 p->hscroll = w->hscroll;
2812 p->display_table = w->display_table;
2813 if (!NILP (w->buffer))
2815 /* Save w's value of point in the window configuration.
2816 If w is the selected window, then get the value of point
2817 from the buffer; pointm is garbage in the selected window. */
2818 if (EQ (window, selected_window))
2820 p->pointm = Fmake_marker ();
2821 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
2822 w->buffer);
2824 else
2825 p->pointm = Fcopy_marker (w->pointm);
2827 p->start = Fcopy_marker (w->start);
2828 p->start_at_line_beg = w->start_at_line_beg;
2830 tem = XBUFFER (w->buffer)->mark;
2831 p->mark = Fcopy_marker (tem);
2833 else
2835 p->pointm = Qnil;
2836 p->start = Qnil;
2837 p->mark = Qnil;
2838 p->start_at_line_beg = Qnil;
2841 if (NILP (w->parent))
2842 p->parent = Qnil;
2843 else
2844 p->parent = XWINDOW (w->parent)->temslot;
2846 if (NILP (w->prev))
2847 p->prev = Qnil;
2848 else
2849 p->prev = XWINDOW (w->prev)->temslot;
2851 if (!NILP (w->vchild))
2852 i = save_window_save (w->vchild, vector, i);
2853 if (!NILP (w->hchild))
2854 i = save_window_save (w->hchild, vector, i);
2857 return i;
2860 DEFUN ("current-window-configuration",
2861 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
2862 "Return an object representing the current window configuration of FRAME.\n\
2863 If FRAME is nil or omitted, use the selected frame.\n\
2864 This describes the number of windows, their sizes and current buffers,\n\
2865 and for each displayed buffer, where display starts, and the positions of\n\
2866 point and mark. An exception is made for point in the current buffer:\n\
2867 its value is -not- saved.\n\
2868 This also records the currently selected frame, and FRAME's focus\n\
2869 redirection (see `redirect-frame-focus').")
2870 (frame)
2871 Lisp_Object frame;
2873 register Lisp_Object tem;
2874 register int n_windows;
2875 register struct save_window_data *data;
2876 register int i;
2877 FRAME_PTR f;
2879 if (NILP (frame))
2880 f = selected_frame;
2881 else
2883 CHECK_LIVE_FRAME (frame, 0);
2884 f = XFRAME (frame);
2887 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2888 data = (struct save_window_data *)
2889 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2890 Qnil));
2891 XFASTINT (data->frame_width) = FRAME_WIDTH (f);
2892 XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
2893 XFASTINT (data->frame_menu_bar_lines) = FRAME_MENU_BAR_LINES (f);
2894 #ifdef MULTI_FRAME
2895 XSET (data->selected_frame, Lisp_Frame, selected_frame);
2896 #endif
2897 data->current_window = FRAME_SELECTED_WINDOW (f);
2898 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2899 data->minibuf_scroll_window = Vminibuf_scroll_window;
2900 data->root_window = FRAME_ROOT_WINDOW (f);
2901 data->focus_frame = FRAME_FOCUS_FRAME (f);
2902 tem = Fmake_vector (make_number (n_windows), Qnil);
2903 data->saved_windows = tem;
2904 for (i = 0; i < n_windows; i++)
2905 XVECTOR (tem)->contents[i]
2906 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
2907 save_window_save (FRAME_ROOT_WINDOW (f),
2908 XVECTOR (tem), 0);
2909 XSET (tem, Lisp_Window_Configuration, data);
2910 return (tem);
2913 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
2914 0, UNEVALLED, 0,
2915 "Execute body, preserving window sizes and contents.\n\
2916 Restores which buffer appears in which window, where display starts,\n\
2917 as well as the current buffer.\n\
2918 Does not restore the value of point in current buffer.")
2919 (args)
2920 Lisp_Object args;
2922 register Lisp_Object val;
2923 register int count = specpdl_ptr - specpdl;
2925 record_unwind_protect (Fset_window_configuration,
2926 Fcurrent_window_configuration (Qnil));
2927 val = Fprogn (args);
2928 return unbind_to (count, val);
2931 init_window_once ()
2933 #ifdef MULTI_FRAME
2934 selected_frame = make_terminal_frame ();
2935 minibuf_window = selected_frame->minibuffer_window;
2936 selected_window = selected_frame->selected_window;
2937 last_nonminibuf_frame = selected_frame;
2938 #else /* not MULTI_FRAME */
2939 extern Lisp_Object get_minibuffer ();
2941 minibuf_window = make_window ();
2942 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
2944 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
2945 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
2946 XWINDOW (minibuf_window)->mini_p = Qt;
2948 /* These values 9 and 10 are arbitrary,
2949 just so that there is "something there."
2950 Correct values are put in in init_xdisp */
2952 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
2953 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
2955 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
2956 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
2957 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
2959 /* Prevent error in Fset_window_buffer. */
2960 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
2961 XWINDOW (minibuf_window)->buffer = Qt;
2963 /* Now set them up for real. */
2964 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
2965 Fcurrent_buffer ());
2966 Fset_window_buffer (minibuf_window, get_minibuffer (0));
2968 selected_window = FRAME_ROOT_WINDOW (selected_frame);
2969 /* Make sure this window seems more recently used than
2970 a newly-created, never-selected window. Increment
2971 window_select_count so the first selection ever will get
2972 something newer than this. */
2973 XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
2974 #endif /* not MULTI_FRAME */
2977 syms_of_window ()
2979 Qwindowp = intern ("windowp");
2980 staticpro (&Qwindowp);
2982 Qwindow_live_p = intern ("window-live-p");
2983 staticpro (&Qwindow_live_p);
2985 #ifndef MULTI_FRAME
2986 /* Make sure all windows get marked */
2987 staticpro (&minibuf_window);
2988 #endif
2990 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
2991 "Non-nil means call as function to display a help buffer.\n\
2992 Used by `with-output-to-temp-buffer'.");
2993 Vtemp_buffer_show_function = Qnil;
2995 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
2996 "If non-nil, function to call to handle `display-buffer'.\n\
2997 It will receive two args, the buffer and a flag which if non-nil means\n\
2998 that the currently selected window is not acceptable.\n\
2999 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3000 work using this function.");
3001 Vdisplay_buffer_function = Qnil;
3003 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3004 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3005 Vminibuf_scroll_window = Qnil;
3007 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3008 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3009 Vother_window_scroll_buffer = Qnil;
3011 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
3012 "*Non-nil means `display-buffer' should make a separate frame.");
3013 pop_up_frames = 0;
3015 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
3016 "*If non-nil, function to call to handle automatic new frame creation.\n\
3017 It is called with no arguments and should return a newly created frame.\n\
3019 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3020 where `pop-up-frame-alist' would hold the default frame parameters.");
3021 Vpop_up_frame_function = Qnil;
3023 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3024 "*Non-nil means display-buffer should make new windows.");
3025 pop_up_windows = 1;
3027 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3028 "*Number of lines of continuity when scrolling by screenfuls.");
3029 next_screen_context_lines = 2;
3031 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3032 "*display-buffer would prefer to split the largest window if this large.\n\
3033 If there is only one window, it is split regardless of this value.");
3034 split_height_threshold = 500;
3036 DEFVAR_INT ("window-min-height", &window_min_height,
3037 "*Delete any window less than this tall (including its mode line).");
3038 window_min_height = 4;
3040 DEFVAR_INT ("window-min-width", &window_min_width,
3041 "*Delete any window less than this wide.");
3042 window_min_width = 10;
3044 defsubr (&Sselected_window);
3045 defsubr (&Sminibuffer_window);
3046 defsubr (&Swindow_minibuffer_p);
3047 defsubr (&Swindowp);
3048 defsubr (&Swindow_live_p);
3049 defsubr (&Spos_visible_in_window_p);
3050 defsubr (&Swindow_buffer);
3051 defsubr (&Swindow_height);
3052 defsubr (&Swindow_width);
3053 defsubr (&Swindow_hscroll);
3054 defsubr (&Sset_window_hscroll);
3055 defsubr (&Swindow_edges);
3056 defsubr (&Scoordinates_in_window_p);
3057 defsubr (&Swindow_at);
3058 defsubr (&Swindow_point);
3059 defsubr (&Swindow_start);
3060 defsubr (&Swindow_end);
3061 defsubr (&Sset_window_point);
3062 defsubr (&Sset_window_start);
3063 defsubr (&Swindow_dedicated_p);
3064 defsubr (&Sset_window_dedicated_p);
3065 defsubr (&Swindow_display_table);
3066 defsubr (&Sset_window_display_table);
3067 defsubr (&Snext_window);
3068 defsubr (&Sprevious_window);
3069 defsubr (&Sother_window);
3070 defsubr (&Sget_lru_window);
3071 defsubr (&Sget_largest_window);
3072 defsubr (&Sget_buffer_window);
3073 defsubr (&Sdelete_other_windows);
3074 defsubr (&Sdelete_windows_on);
3075 defsubr (&Sreplace_buffer_in_windows);
3076 defsubr (&Sdelete_window);
3077 defsubr (&Sset_window_buffer);
3078 defsubr (&Sselect_window);
3079 defsubr (&Sdisplay_buffer);
3080 defsubr (&Ssplit_window);
3081 defsubr (&Senlarge_window);
3082 defsubr (&Sshrink_window);
3083 defsubr (&Sscroll_up);
3084 defsubr (&Sscroll_down);
3085 defsubr (&Sscroll_left);
3086 defsubr (&Sscroll_right);
3087 defsubr (&Sscroll_other_window);
3088 defsubr (&Srecenter);
3089 defsubr (&Smove_to_window_line);
3090 defsubr (&Swindow_configuration_p);
3091 defsubr (&Sset_window_configuration);
3092 defsubr (&Scurrent_window_configuration);
3093 defsubr (&Ssave_window_excursion);
3096 keys_of_window ()
3098 initial_define_key (control_x_map, '1', "delete-other-windows");
3099 initial_define_key (control_x_map, '2', "split-window");
3100 initial_define_key (control_x_map, '0', "delete-window");
3101 initial_define_key (control_x_map, 'o', "other-window");
3102 initial_define_key (control_x_map, '^', "enlarge-window");
3103 initial_define_key (control_x_map, '<', "scroll-left");
3104 initial_define_key (control_x_map, '>', "scroll-right");
3106 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3107 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3108 initial_define_key (meta_map, 'v', "scroll-down");
3110 initial_define_key (global_map, Ctl('L'), "recenter");
3111 initial_define_key (meta_map, 'r', "move-to-window-line");