(debug, debugger-eval-expression): Preserve match-data.
[emacs.git] / src / window.c
blob9515c1ca082c9f1364150e985fc586ab993bb867
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, w);
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 return make_number (window_internal_width (decode_window (window)));
270 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
271 "Return the number of columns by which WINDOW is scrolled from left margin.")
272 (window)
273 Lisp_Object window;
275 return decode_window (window)->hscroll;
278 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
279 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
280 NCOL should be zero or positive.")
281 (window, ncol)
282 register Lisp_Object window, ncol;
284 register struct window *w;
286 CHECK_NUMBER (ncol, 1);
287 if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
288 if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
289 args_out_of_range (ncol, Qnil);
290 w = decode_window (window);
291 if (XINT (w->hscroll) != XINT (ncol))
292 clip_changed = 1; /* Prevent redisplay shortcuts */
293 w->hscroll = ncol;
294 return ncol;
297 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
298 "Return a list of the edge coordinates of WINDOW.\n\
299 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
300 RIGHT is one more than the rightmost column used by WINDOW,\n\
301 and BOTTOM is one more than the bottommost row used by WINDOW\n\
302 and its mode-line.")
303 (window)
304 Lisp_Object window;
306 register struct window *w = decode_window (window);
308 return Fcons (w->left, Fcons (w->top,
309 Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
310 Fcons (make_number (XFASTINT (w->top)
311 + XFASTINT (w->height)),
312 Qnil))));
315 /* Test if the character at column *x, row *y is within window *w.
316 If it is not, return 0;
317 if it is in the window's text area,
318 set *x and *y to its location relative to the upper left corner
319 of the window, and
320 return 1;
321 if it is on the window's modeline, return 2;
322 if it is on the border between the window and its right sibling,
323 return 3. */
324 static int
325 coordinates_in_window (w, x, y)
326 register struct window *w;
327 register int *x, *y;
329 register int left = XINT (w->left);
330 register int width = XINT (w->width);
331 register int window_height = XINT (w->height);
332 register int top = XFASTINT (w->top);
334 if ( *x < left || *x >= left + width
335 || *y < top || *y >= top + window_height)
336 return 0;
338 /* Is the character is the mode line? */
339 if (*y == top + window_height - 1
340 && ! MINI_WINDOW_P (w))
341 return 2;
343 /* Is the character in the right border? */
344 if (*x == left + width - 1
345 && left + width != FRAME_WIDTH (XFRAME (w->frame)))
346 return 3;
348 *x -= left;
349 *y -= top;
350 return 1;
353 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
354 Scoordinates_in_window_p, 2, 2, 0,
355 "Return non-nil if COORDINATES are in WINDOW.\n\
356 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
357 measured in characters from the upper-left corner of the frame.\n\
358 (0 . 0) denotes the character in the upper left corner of the\n\
359 frame.\n\
360 If COORDINATES are in the text portion of WINDOW,\n\
361 the coordinates relative to the window are returned.\n\
362 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
363 If they are on the border between WINDOW and its right sibling,\n\
364 `vertical-line' is returned.")
365 (coordinates, window)
366 register Lisp_Object coordinates, window;
368 int x, y;
370 CHECK_LIVE_WINDOW (window, 0);
371 CHECK_CONS (coordinates, 1);
372 x = XINT (Fcar (coordinates));
373 y = XINT (Fcdr (coordinates));
375 switch (coordinates_in_window (XWINDOW (window), &x, &y))
377 case 0: /* NOT in window at all. */
378 return Qnil;
380 case 1: /* In text part of window. */
381 return Fcons (x, y);
383 case 2: /* In mode line of window. */
384 return Qmode_line;
386 case 3: /* On right border of window. */
387 return Qvertical_line;
389 default:
390 abort ();
394 /* Find the window containing column x, row y, and return it as a
395 Lisp_Object. If x, y is on the window's modeline, set *part
396 to 1; if it is on the separating line between the window and its
397 right sibling, set it to 2; otherwise set it to 0. If there is no
398 window under x, y return nil and leave *part unmodified. */
399 Lisp_Object
400 window_from_coordinates (frame, x, y, part)
401 FRAME_PTR frame;
402 int x, y;
403 int *part;
405 register Lisp_Object tem, first;
407 tem = first = FRAME_SELECTED_WINDOW (frame);
411 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
413 if (found)
415 *part = found - 1;
416 return tem;
419 tem = Fnext_window (tem, Qt, Qlambda);
421 while (! EQ (tem, first));
423 return Qnil;
426 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
427 "Return window containing coordinates X and Y on FRAME.\n\
428 If omitted, FRAME defaults to the currently selected frame.\n\
429 The top left corner of the frame is considered to be row 0,\n\
430 column 0.")
431 (x, y, frame)
432 Lisp_Object x, y, frame;
434 int part;
436 #ifdef MULTI_FRAME
437 if (NILP (frame))
438 XSET (frame, Lisp_Frame, selected_frame);
439 else
440 CHECK_LIVE_FRAME (frame, 2);
441 #endif
442 CHECK_NUMBER (x, 0);
443 CHECK_NUMBER (y, 1);
445 return window_from_coordinates (XFRAME (frame),
446 XINT (x), XINT (y),
447 &part);
450 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
451 "Return current value of point in WINDOW.\n\
452 For a nonselected window, this is the value point would have\n\
453 if that window were selected.\n\
455 Note that, when WINDOW is the selected window and its buffer\n\
456 is also currently selected, the value returned is the same as (point).\n\
457 It would be more strictly correct to return the `top-level' value\n\
458 of point, outside of any save-excursion forms.\n\
459 But that is hard to define.")
460 (window)
461 Lisp_Object window;
463 register struct window *w = decode_window (window);
465 if (w == XWINDOW (selected_window)
466 && current_buffer == XBUFFER (w->buffer))
467 return Fpoint ();
468 return Fmarker_position (w->pointm);
471 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
472 "Return position at which display currently starts in WINDOW.")
473 (window)
474 Lisp_Object window;
476 return Fmarker_position (decode_window (window)->start);
479 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
480 "Return position at which display currently ends in WINDOW.")
481 (window)
482 Lisp_Object window;
484 Lisp_Object value;
485 struct window *w = decode_window (window);
486 Lisp_Object buf;
488 buf = w->buffer;
489 CHECK_BUFFER (buf, 0);
491 XSET (value, Lisp_Int,
492 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
494 return value;
497 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
498 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
499 (window, pos)
500 Lisp_Object window, pos;
502 register struct window *w = decode_window (window);
504 CHECK_NUMBER_COERCE_MARKER (pos, 1);
505 if (w == XWINDOW (selected_window))
506 Fgoto_char (pos);
507 else
508 set_marker_restricted (w->pointm, pos, w->buffer);
510 return pos;
513 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
514 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
515 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
516 from overriding motion of point in order to display at this exact start.")
517 (window, pos, noforce)
518 Lisp_Object window, pos, noforce;
520 register struct window *w = decode_window (window);
522 CHECK_NUMBER_COERCE_MARKER (pos, 1);
523 set_marker_restricted (w->start, pos, w->buffer);
524 /* this is not right, but much easier than doing what is right. */
525 w->start_at_line_beg = Qnil;
526 if (NILP (noforce))
527 w->force_start = Qt;
528 w->update_mode_line = Qt;
529 XFASTINT (w->last_modified) = 0;
530 if (!EQ (window, selected_window))
531 windows_or_buffers_changed++;
532 return pos;
535 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
536 1, 1, 0,
537 "Return WINDOW's dedicated object, usually t or nil.\n\
538 See also `set-window-dedicated-p'.")
539 (window)
540 Lisp_Object window;
542 return decode_window (window)->dedicated;
545 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
546 Sset_window_dedicated_p, 2, 2, 0,
547 "Control whether WINDOW is dedicated to the buffer it displays.\n\
548 If it is dedicated, Emacs will not automatically change\n\
549 which buffer appears in it.\n\
550 The second argument is the new value for the dedication flag;\n\
551 non-nil means yes.")
552 (window, arg)
553 Lisp_Object window, arg;
555 register struct window *w = decode_window (window);
557 if (NILP (arg))
558 w->dedicated = Qnil;
559 else
560 w->dedicated = Qt;
562 return w->dedicated;
565 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
566 0, 1, 0,
567 "Return the display-table that WINDOW is using.")
568 (window)
569 Lisp_Object window;
571 return decode_window (window)->display_table;
574 /* Get the display table for use currently on window W.
575 This is either W's display table or W's buffer's display table.
576 Ignore the specified tables if they are not valid;
577 if no valid table is specified, return 0. */
579 struct Lisp_Vector *
580 window_display_table (w)
581 struct window *w;
583 Lisp_Object tem;
584 tem = w->display_table;
585 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
586 return XVECTOR (tem);
587 tem = XBUFFER (w->buffer)->display_table;
588 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
589 return XVECTOR (tem);
590 tem = Vstandard_display_table;
591 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
592 return XVECTOR (tem);
593 return 0;
596 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
597 "Set WINDOW's display-table to TABLE.")
598 (window, table)
599 register Lisp_Object window, table;
601 register struct window *w;
602 register Lisp_Object z; /* Return value. */
604 w = decode_window (window);
605 w->display_table = table;
606 return table;
609 /* Record info on buffer window w is displaying
610 when it is about to cease to display that buffer. */
611 static
612 unshow_buffer (w)
613 register struct window *w;
615 Lisp_Object buf;
617 buf = w->buffer;
618 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
619 abort ();
621 #if 0
622 if (w == XWINDOW (selected_window)
623 || ! EQ (buf, XWINDOW (selected_window)->buffer))
624 /* Do this except when the selected window's buffer
625 is being removed from some other window. */
626 #endif
627 /* last_window_start records the start position that this buffer
628 had in the last window to be disconnected from it.
629 Now that this statement is unconditional,
630 it is possible for the buffer to be displayed in the
631 selected window, while last_window_start reflects another
632 window which was recently showing the same buffer.
633 Some people might say that might be a good thing. Let's see. */
634 XBUFFER (buf)->last_window_start = marker_position (w->start);
636 /* Point in the selected window's buffer
637 is actually stored in that buffer, and the window's pointm isn't used.
638 So don't clobber point in that buffer. */
639 if (! EQ (buf, XWINDOW (selected_window)->buffer))
640 BUF_PT (XBUFFER (buf))
641 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
642 marker_position (w->pointm),
643 BUF_ZV (XBUFFER (buf)));
646 /* Put replacement into the window structure in place of old. */
647 static
648 replace_window (old, replacement)
649 Lisp_Object old, replacement;
651 register Lisp_Object tem;
652 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
654 /* If OLD is its frame's root_window, then replacement is the new
655 root_window for that frame. */
657 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
658 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
660 p->left = o->left;
661 p->top = o->top;
662 p->width = o->width;
663 p->height = o->height;
665 p->next = tem = o->next;
666 if (!NILP (tem))
667 XWINDOW (tem)->prev = replacement;
669 p->prev = tem = o->prev;
670 if (!NILP (tem))
671 XWINDOW (tem)->next = replacement;
673 p->parent = tem = o->parent;
674 if (!NILP (tem))
676 if (EQ (XWINDOW (tem)->vchild, old))
677 XWINDOW (tem)->vchild = replacement;
678 if (EQ (XWINDOW (tem)->hchild, old))
679 XWINDOW (tem)->hchild = replacement;
682 /*** Here, if replacement is a vertical combination
683 and so is its new parent, we should make replacement's
684 children be children of that parent instead. ***/
687 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
688 "Remove WINDOW from the display. Default is selected window.")
689 (window)
690 register Lisp_Object window;
692 register Lisp_Object tem, parent, sib;
693 register struct window *p;
694 register struct window *par;
696 /* Because this function is called by other C code on non-leaf
697 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
698 so we can't decode_window here. */
699 if (NILP (window))
700 window = selected_window;
701 else
702 CHECK_WINDOW (window, 0);
703 p = XWINDOW (window);
705 /* It's okay to delete an already-deleted window. */
706 if (NILP (p->buffer)
707 && NILP (p->hchild)
708 && NILP (p->vchild))
709 return Qnil;
711 parent = p->parent;
712 if (NILP (parent))
713 error ("Attempt to delete minibuffer or sole ordinary window");
714 par = XWINDOW (parent);
716 windows_or_buffers_changed++;
718 /* Are we trying to delete any frame's selected window? */
720 Lisp_Object frame, pwindow;
722 /* See if the frame's selected window is either WINDOW
723 or any subwindow of it, by finding all that window's parents
724 and comparing each one with WINDOW. */
725 frame = WINDOW_FRAME (XWINDOW (window));
726 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
728 while (!NILP (pwindow))
730 if (EQ (window, pwindow))
731 break;
732 pwindow = XWINDOW (pwindow)->parent;
735 if (EQ (window, pwindow))
737 Lisp_Object alternative;
738 alternative = Fnext_window (window, Qlambda, Qnil);
740 /* If we're about to delete the selected window on the
741 selected frame, then we should use Fselect_window to select
742 the new window. On the other hand, if we're about to
743 delete the selected window on any other frame, we shouldn't do
744 anything but set the frame's selected_window slot. */
745 if (EQ (window, selected_window))
746 Fselect_window (alternative);
747 else
748 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
752 tem = p->buffer;
753 /* tem is null for dummy parent windows
754 (which have inferiors but not any contents themselves) */
755 if (!NILP (tem))
757 unshow_buffer (p);
758 unchain_marker (p->pointm);
759 unchain_marker (p->start);
762 tem = p->next;
763 if (!NILP (tem))
764 XWINDOW (tem)->prev = p->prev;
766 tem = p->prev;
767 if (!NILP (tem))
768 XWINDOW (tem)->next = p->next;
770 if (EQ (window, par->hchild))
771 par->hchild = p->next;
772 if (EQ (window, par->vchild))
773 par->vchild = p->next;
775 /* Find one of our siblings to give our space to. */
776 sib = p->prev;
777 if (NILP (sib))
779 /* If p gives its space to its next sibling, that sibling needs
780 to have its top/left side pulled back to where p's is.
781 set_window_{height,width} will re-position the sibling's
782 children. */
783 sib = p->next;
784 XWINDOW (sib)->top = p->top;
785 XWINDOW (sib)->left = p->left;
788 /* Stretch that sibling. */
789 if (!NILP (par->vchild))
790 set_window_height (sib,
791 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
793 if (!NILP (par->hchild))
794 set_window_width (sib,
795 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
798 /* If parent now has only one child,
799 put the child into the parent's place. */
800 tem = par->hchild;
801 if (NILP (tem))
802 tem = par->vchild;
803 if (NILP (XWINDOW (tem)->next))
804 replace_window (parent, tem);
806 /* Since we may be deleting combination windows, we must make sure that
807 not only p but all its children have been marked as deleted. */
808 if (! NILP (p->hchild))
809 delete_all_subwindows (XWINDOW (p->hchild));
810 else if (! NILP (p->vchild))
811 delete_all_subwindows (XWINDOW (p->vchild));
813 /* Mark this window as deleted. */
814 p->buffer = p->hchild = p->vchild = Qnil;
816 return Qnil;
820 extern Lisp_Object next_frame (), prev_frame ();
822 /* This comment supplies the doc string for `next-window',
823 for make-docfile to see. We cannot put this in the real DEFUN
824 due to limits in the Unix cpp.
826 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
827 "Return next window after WINDOW in canonical ordering of windows.\n\
828 If omitted, WINDOW defaults to the selected window.\n\
830 Optional second arg MINIBUF t means count the minibuffer window even\n\
831 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
832 it is active. MINIBUF neither t nor nil means not to count the\n\
833 minibuffer even if it is active.\n\
835 Several frames may share a single minibuffer; if the minibuffer\n\
836 counts, all windows on all frames that share that minibuffer count\n\
837 too. This means that next-window may be used to iterate through the\n\
838 set of windows even when the minibuffer is on another frame. If the\n\
839 minibuffer does not count, only windows from WINDOW's frame count.\n\
841 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
842 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
843 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
844 Anything else means restrict to WINDOW's frame.\n\
846 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
847 `next-window' to iterate through the entire cycle of acceptable\n\
848 windows, eventually ending up back at the window you started with.\n\
849 `previous-window' traverses the same cycle, in the reverse order.")
850 (window, minibuf, all_frames) */
852 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
854 (window, minibuf, all_frames)
855 register Lisp_Object window, minibuf, all_frames;
857 register Lisp_Object tem;
858 Lisp_Object start_window;
860 if (NILP (window))
861 window = selected_window;
862 else
863 CHECK_LIVE_WINDOW (window, 0);
865 start_window = window;
867 /* minibuf == nil may or may not include minibuffers.
868 Decide if it does. */
869 if (NILP (minibuf))
870 minibuf = (minibuf_level ? Qt : Qlambda);
872 #ifdef MULTI_FRAME
873 /* all_frames == nil doesn't specify which frames to include.
874 Decide which frames it includes. */
875 if (NILP (all_frames))
876 all_frames = (EQ (minibuf, Qt)
877 ? (FRAME_MINIBUF_WINDOW
878 (XFRAME
879 (WINDOW_FRAME
880 (XWINDOW (window)))))
881 : Qnil);
882 else if (EQ (all_frames, Qvisible))
884 else if (! EQ (all_frames, Qt))
885 all_frames = Qnil;
886 /* Now all_frames is t meaning search all frames,
887 nil meaning search just current frame,
888 or a window, meaning search the frame that window belongs to. */
889 #endif
891 /* Do this loop at least once, to get the next window, and perhaps
892 again, if we hit the minibuffer and that is not acceptable. */
895 /* Find a window that actually has a next one. This loop
896 climbs up the tree. */
897 while (tem = XWINDOW (window)->next, NILP (tem))
898 if (tem = XWINDOW (window)->parent, !NILP (tem))
899 window = tem;
900 else
902 /* We've reached the end of this frame.
903 Which other frames are acceptable? */
904 tem = WINDOW_FRAME (XWINDOW (window));
905 #ifdef MULTI_FRAME
906 if (! NILP (all_frames))
907 tem = next_frame (tem, all_frames);
908 #endif
909 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
911 break;
914 window = tem;
916 /* If we're in a combination window, find its first child and
917 recurse on that. Otherwise, we've found the window we want. */
918 while (1)
920 if (!NILP (XWINDOW (window)->hchild))
921 window = XWINDOW (window)->hchild;
922 else if (!NILP (XWINDOW (window)->vchild))
923 window = XWINDOW (window)->vchild;
924 else break;
927 /* Which windows are acceptible?
928 Exit the loop and accept this window if
929 this isn't a minibuffer window, or
930 we're accepting minibuffer windows, or
931 we've come all the way around and we're back at the original window. */
932 while (MINI_WINDOW_P (XWINDOW (window))
933 && ! EQ (minibuf, Qt)
934 && ! EQ (window, start_window));
936 return window;
939 /* This comment supplies the doc string for `previous-window',
940 for make-docfile to see. We cannot put this in the real DEFUN
941 due to limits in the Unix cpp.
943 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
944 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
945 If omitted, WINDOW defaults to the selected window.\n\
947 Optional second arg MINIBUF t means count the minibuffer window even\n\
948 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
949 it is active. MINIBUF neither t nor nil means not to count the\n\
950 minibuffer even if it is active.\n\
952 Several frames may share a single minibuffer; if the minibuffer\n\
953 counts, all windows on all frames that share that minibuffer count\n\
954 too. This means that previous-window may be used to iterate through\n\
955 the set of windows even when the minibuffer is on another frame. If\n\
956 the minibuffer does not count, only windows from WINDOW's frame\n\
957 count.\n\
959 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
960 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
961 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
962 Anything else means restrict to WINDOW's frame.\n\
964 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
965 `previous-window' to iterate through the entire cycle of acceptable\n\
966 windows, eventually ending up back at the window you started with.\n\
967 `next-window' traverses the same cycle, in the reverse order.")
968 (window, minibuf, all_frames) */
971 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
973 (window, minibuf, all_frames)
974 register Lisp_Object window, minibuf, all_frames;
976 register Lisp_Object tem;
977 Lisp_Object start_window;
979 if (NILP (window))
980 window = selected_window;
981 else
982 CHECK_LIVE_WINDOW (window, 0);
984 start_window = window;
986 /* minibuf == nil may or may not include minibuffers.
987 Decide if it does. */
988 if (NILP (minibuf))
989 minibuf = (minibuf_level ? Qt : Qlambda);
991 #ifdef MULTI_FRAME
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. */
1008 #endif
1010 /* Do this loop at least once, to get the previous window, and perhaps
1011 again, if we hit the minibuffer and that is not acceptable. */
1014 /* Find a window that actually has a previous one. This loop
1015 climbs up the tree. */
1016 while (tem = XWINDOW (window)->prev, NILP (tem))
1017 if (tem = XWINDOW (window)->parent, !NILP (tem))
1018 window = tem;
1019 else
1021 /* We have found the top window on the frame.
1022 Which frames are acceptable? */
1023 tem = WINDOW_FRAME (XWINDOW (window));
1024 #ifdef MULTI_FRAME
1025 if (! NILP (all_frames))
1026 /* It's actually important that we use prev_frame here,
1027 rather than next_frame. All the windows acceptable
1028 according to the given parameters should form a ring;
1029 Fnext_window and Fprevious_window should go back and
1030 forth around the ring. If we use next_frame here,
1031 then Fnext_window and Fprevious_window take different
1032 paths through the set of acceptable windows.
1033 window_loop assumes that these `ring' requirement are
1034 met. */
1035 tem = prev_frame (tem, all_frames);
1036 #endif
1037 /* If this frame has a minibuffer, find that window first,
1038 because it is conceptually the last window in that frame. */
1039 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1040 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1041 else
1042 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1044 break;
1047 window = tem;
1048 /* If we're in a combination window, find its last child and
1049 recurse on that. Otherwise, we've found the window we want. */
1050 while (1)
1052 if (!NILP (XWINDOW (window)->hchild))
1053 window = XWINDOW (window)->hchild;
1054 else if (!NILP (XWINDOW (window)->vchild))
1055 window = XWINDOW (window)->vchild;
1056 else break;
1057 while (tem = XWINDOW (window)->next, !NILP (tem))
1058 window = tem;
1061 /* Which windows are acceptable?
1062 Exit the loop and accept this window if
1063 this isn't a minibuffer window, or
1064 we're accepting minibuffer windows, or
1065 we've come all the way around and we're back at the original window. */
1066 while (MINI_WINDOW_P (XWINDOW (window))
1067 && !EQ (minibuf, Qt)
1068 && !EQ (window, start_window));
1070 return window;
1073 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1074 "Select the ARG'th different window on this frame.\n\
1075 All windows on current frame are arranged in a cyclic order.\n\
1076 This command selects the window ARG steps away in that order.\n\
1077 A negative ARG moves in the opposite order. If the optional second\n\
1078 argument ALL_FRAMES is non-nil, cycle through all frames.")
1079 (n, all_frames)
1080 register Lisp_Object n, all_frames;
1082 register int i;
1083 register Lisp_Object w;
1085 CHECK_NUMBER (n, 0);
1086 w = selected_window;
1087 i = XINT (n);
1089 while (i > 0)
1091 w = Fnext_window (w, Qnil, all_frames);
1092 i--;
1094 while (i < 0)
1096 w = Fprevious_window (w, Qnil, all_frames);
1097 i++;
1099 Fselect_window (w);
1100 return Qnil;
1103 /* Look at all windows, performing an operation specified by TYPE
1104 with argument OBJ.
1105 If FRAMES is Qt, look at all frames;
1106 Qnil, look at just the selected frame;
1107 Qvisible, look at visible frames;
1108 a frame, just look at windows on that frame.
1109 If MINI is non-zero, perform the operation on minibuffer windows too.
1112 enum window_loop
1114 WINDOW_LOOP_UNUSED,
1115 GET_BUFFER_WINDOW, /* Arg is buffer */
1116 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1117 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1118 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1119 GET_LARGEST_WINDOW,
1120 UNSHOW_BUFFER /* Arg is buffer */
1123 static Lisp_Object
1124 window_loop (type, obj, mini, frames)
1125 enum window_loop type;
1126 register Lisp_Object obj, frames;
1127 int mini;
1129 register Lisp_Object w;
1130 register Lisp_Object best_window;
1131 register Lisp_Object next_window;
1132 register Lisp_Object last_window;
1133 FRAME_PTR frame;
1134 Lisp_Object frame_arg;
1135 frame_arg = Qt;
1137 #ifdef MULTI_FRAME
1138 /* If we're only looping through windows on a particular frame,
1139 frame points to that frame. If we're looping through windows
1140 on all frames, frame is 0. */
1141 if (FRAMEP (frames))
1142 frame = XFRAME (frames);
1143 else if (NILP (frames))
1144 frame = selected_frame;
1145 else
1146 frame = 0;
1147 if (frame)
1148 frame_arg = Qlambda;
1149 else if (EQ (frames, Qvisible))
1150 frame_arg = frames;
1151 #else
1152 frame = 0;
1153 #endif
1155 /* frame_arg is Qlambda to stick to one frame,
1156 Qvisible to consider all visible frames,
1157 or Qt otherwise. */
1159 /* Pick a window to start with. */
1160 if (XTYPE (obj) == Lisp_Window)
1161 w = obj;
1162 else if (frame)
1163 w = FRAME_SELECTED_WINDOW (frame);
1164 else
1165 w = FRAME_SELECTED_WINDOW (selected_frame);
1167 /* Figure out the last window we're going to mess with. Since
1168 Fnext_window, given the same options, is guaranteed to go in a
1169 ring, we can just use Fprevious_window to find the last one.
1171 We can't just wait until we hit the first window again, because
1172 it might be deleted. */
1174 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
1176 best_window = Qnil;
1177 for (;;)
1179 FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1181 /* Pick the next window now, since some operations will delete
1182 the current window. */
1183 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
1185 /* Note that we do not pay attention here to whether
1186 the frame is visible, since Fnext_window skips non-visible frames
1187 if that is desired, under the control of frame_arg. */
1188 if (! MINI_WINDOW_P (XWINDOW (w))
1189 || (mini && minibuf_level > 0))
1190 switch (type)
1192 case GET_BUFFER_WINDOW:
1193 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1194 return w;
1195 break;
1197 case GET_LRU_WINDOW:
1198 /* t as arg means consider only full-width windows */
1199 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
1200 != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1201 break;
1202 /* Ignore dedicated windows and minibuffers. */
1203 if (MINI_WINDOW_P (XWINDOW (w))
1204 || !NILP (XWINDOW (w)->dedicated))
1205 break;
1206 if (NILP (best_window)
1207 || (XFASTINT (XWINDOW (best_window)->use_time)
1208 > XFASTINT (XWINDOW (w)->use_time)))
1209 best_window = w;
1210 break;
1212 case DELETE_OTHER_WINDOWS:
1213 if (XWINDOW (w) != XWINDOW (obj))
1214 Fdelete_window (w);
1215 break;
1217 case DELETE_BUFFER_WINDOWS:
1218 if (EQ (XWINDOW (w)->buffer, obj))
1220 /* If we're deleting the buffer displayed in the only window
1221 on the frame, find a new buffer to display there. */
1222 if (NILP (XWINDOW (w)->parent))
1224 Lisp_Object new_buffer;
1225 new_buffer = Fother_buffer (obj, Qnil);
1226 if (NILP (new_buffer))
1227 new_buffer
1228 = Fget_buffer_create (build_string ("*scratch*"));
1229 Fset_window_buffer (w, new_buffer);
1230 if (EQ (w, selected_window))
1231 Fset_buffer (XWINDOW (w)->buffer);
1233 else
1234 Fdelete_window (w);
1236 break;
1238 case GET_LARGEST_WINDOW:
1239 /* Ignore dedicated windows and minibuffers. */
1240 if (MINI_WINDOW_P (XWINDOW (w))
1241 || !NILP (XWINDOW (w)->dedicated))
1242 break;
1244 struct window *best_window_ptr = XWINDOW (best_window);
1245 struct window *w_ptr = XWINDOW (w);
1246 if (NILP (best_window) ||
1247 (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width))
1248 > (XFASTINT (best_window_ptr->height)
1249 * XFASTINT (best_window_ptr->width)))
1250 best_window = w;
1252 break;
1254 case UNSHOW_BUFFER:
1255 if (EQ (XWINDOW (w)->buffer, obj))
1257 /* Find another buffer to show in this window. */
1258 Lisp_Object another_buffer;
1259 another_buffer = Fother_buffer (obj, Qnil);
1260 if (NILP (another_buffer))
1261 another_buffer
1262 = Fget_buffer_create (build_string ("*scratch*"));
1263 Fset_window_buffer (w, another_buffer);
1264 if (EQ (w, selected_window))
1265 Fset_buffer (XWINDOW (w)->buffer);
1267 break;
1270 if (EQ (w, last_window))
1271 break;
1273 w = next_window;
1276 return best_window;
1279 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1280 "Return the window least recently selected or used for display.\n\
1281 If optional argument FRAME is `visible', search all visible frames.\n\
1282 If FRAME is t, search all frames.\n\
1283 If FRAME is nil, search only the selected frame.\n\
1284 If FRAME is a frame, search only that frame.")
1285 (frame)
1286 Lisp_Object frame;
1288 register Lisp_Object w;
1289 /* First try for a window that is full-width */
1290 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1291 if (!NILP (w) && !EQ (w, selected_window))
1292 return w;
1293 /* If none of them, try the rest */
1294 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1297 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1298 "Return the largest window in area.\n\
1299 If optional argument FRAME is `visible', search all visible frames.\n\
1300 If FRAME is t, search all frames.\n\
1301 If FRAME is nil, search only the selected frame.\n\
1302 If FRAME is a frame, search only that frame.")
1303 (frame)
1304 Lisp_Object frame;
1306 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1307 frame);
1310 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1311 "Return a window currently displaying BUFFER, or nil if none.\n\
1312 If optional argument FRAME is `visible', search all visible frames.\n\
1313 If FRAME is t, search all frames.\n\
1314 If FRAME is nil, search only the selected frame.\n\
1315 If FRAME is a frame, search only that frame.")
1316 (buffer, frame)
1317 Lisp_Object buffer, frame;
1319 buffer = Fget_buffer (buffer);
1320 if (XTYPE (buffer) == Lisp_Buffer)
1321 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1322 else
1323 return Qnil;
1326 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1327 0, 1, "",
1328 "Make WINDOW (or the selected window) fill its frame.\n\
1329 Only the frame WINDOW is on is affected.\n\
1330 This function tries to reduce display jumps\n\
1331 by keeping the text previously visible in WINDOW\n\
1332 in the same place on the frame. Doing this depends on\n\
1333 the value of (window-start WINDOW), so if calling this function\n\
1334 in a program gives strange scrolling, make sure the window-start\n\
1335 value is reasonable when this function is called.")
1336 (window)
1337 Lisp_Object window;
1339 struct window *w;
1340 struct buffer *obuf = current_buffer;
1341 int opoint;
1342 int top;
1344 if (NILP (window))
1345 window = selected_window;
1346 else
1347 CHECK_LIVE_WINDOW (window, 0);
1349 w = XWINDOW (window);
1350 top = XFASTINT (w->top);
1352 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1354 Fset_buffer (w->buffer);
1355 opoint = point;
1356 SET_PT (marker_position (w->start));
1357 /* Like Frecenter but avoid setting w->force_start. */
1358 Fvertical_motion (make_number (- (top - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w))))),
1359 window);
1360 Fset_marker (w->start, make_number (PT), w->buffer);
1361 w->start_at_line_beg = Fbolp ();
1363 SET_PT (opoint);
1364 set_buffer_internal (obuf);
1365 return Qnil;
1368 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1369 1, 2, "bDelete windows on (buffer): ",
1370 "Delete all windows showing BUFFER.\n\
1371 Optional second argument FRAME controls which frames are affected.\n\
1372 If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1373 If t, delete only windows showing BUFFER in the selected frame.\n\
1374 If `visible', delete all windows showing BUFFER in any visible frame.\n\
1375 If a frame, delete only windows showing BUFFER in that frame.")
1376 (buffer, frame)
1377 Lisp_Object buffer, frame;
1379 #ifdef MULTI_FRAME
1380 /* FRAME uses t and nil to mean the opposite of what window_loop
1381 expects. */
1382 if (! FRAMEP (frame))
1383 frame = NILP (frame) ? Qt : Qnil;
1384 #else
1385 frame = Qt;
1386 #endif
1388 if (!NILP (buffer))
1390 buffer = Fget_buffer (buffer);
1391 CHECK_BUFFER (buffer, 0);
1392 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1394 return Qnil;
1397 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1398 Sreplace_buffer_in_windows,
1399 1, 1, "bReplace buffer in windows: ",
1400 "Replace BUFFER with some other buffer in all windows showing it.")
1401 (buffer)
1402 Lisp_Object buffer;
1404 if (!NILP (buffer))
1406 buffer = Fget_buffer (buffer);
1407 CHECK_BUFFER (buffer, 0);
1408 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1410 return Qnil;
1413 /* Set the height of WINDOW and all its inferiors. */
1415 /* The smallest acceptable dimensions for a window. Anything smaller
1416 might crash Emacs. */
1417 #define MIN_SAFE_WINDOW_WIDTH (2)
1418 #define MIN_SAFE_WINDOW_HEIGHT (2)
1420 /* Make sure that window_min_height and window_min_width are
1421 not too small; if they are, set them to safe minima. */
1423 static void
1424 check_min_window_sizes ()
1426 /* Smaller values might permit a crash. */
1427 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1428 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1429 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1430 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1433 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1434 minimum allowable size. */
1435 void
1436 check_frame_size (frame, rows, cols)
1437 FRAME_PTR frame;
1438 int *rows, *cols;
1440 /* For height, we have to see:
1441 whether the frame has a minibuffer,
1442 whether it wants a mode line, and
1443 whether it has a menu bar. */
1444 int min_height =
1445 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1446 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
1447 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1448 if (FRAME_MENU_BAR_LINES (frame) > 0)
1449 min_height += FRAME_MENU_BAR_LINES (frame);
1451 if (*rows < min_height)
1452 *rows = min_height;
1453 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1454 *cols = MIN_SAFE_WINDOW_WIDTH;
1457 /* Normally the window is deleted if it gets too small.
1458 nodelete nonzero means do not do this.
1459 (The caller should check later and do so if appropriate) */
1461 set_window_height (window, height, nodelete)
1462 Lisp_Object window;
1463 int height;
1464 int nodelete;
1466 register struct window *w = XWINDOW (window);
1467 register struct window *c;
1468 int oheight = XFASTINT (w->height);
1469 int top, pos, lastbot, opos, lastobot;
1470 Lisp_Object child;
1472 check_min_window_sizes ();
1474 if (!nodelete
1475 && ! NILP (w->parent)
1476 && height < window_min_height)
1478 Fdelete_window (window);
1479 return;
1482 XFASTINT (w->last_modified) = 0;
1483 windows_or_buffers_changed++;
1484 XFASTINT (w->height) = height;
1485 if (!NILP (w->hchild))
1487 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1489 XWINDOW (child)->top = w->top;
1490 set_window_height (child, height, nodelete);
1493 else if (!NILP (w->vchild))
1495 lastbot = top = XFASTINT (w->top);
1496 lastobot = 0;
1497 for (child = w->vchild; !NILP (child); child = c->next)
1499 c = XWINDOW (child);
1501 opos = lastobot + XFASTINT (c->height);
1503 XFASTINT (c->top) = lastbot;
1505 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1507 /* Avoid confusion: inhibit deletion of child if becomes too small */
1508 set_window_height (child, pos + top - lastbot, 1);
1510 /* Now advance child to next window,
1511 and set lastbot if child was not just deleted. */
1512 lastbot = pos + top;
1513 lastobot = opos;
1515 /* Now delete any children that became too small. */
1516 if (!nodelete)
1517 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1519 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1524 /* Recursively set width of WINDOW and its inferiors. */
1526 set_window_width (window, width, nodelete)
1527 Lisp_Object window;
1528 int width;
1529 int nodelete;
1531 register struct window *w = XWINDOW (window);
1532 register struct window *c;
1533 int owidth = XFASTINT (w->width);
1534 int left, pos, lastright, opos, lastoright;
1535 Lisp_Object child;
1537 if (!nodelete && width < window_min_width)
1539 Fdelete_window (window);
1540 return;
1543 XFASTINT (w->last_modified) = 0;
1544 windows_or_buffers_changed++;
1545 XFASTINT (w->width) = width;
1546 if (!NILP (w->vchild))
1548 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1550 XWINDOW (child)->left = w->left;
1551 set_window_width (child, width, nodelete);
1554 else if (!NILP (w->hchild))
1556 lastright = left = XFASTINT (w->left);
1557 lastoright = 0;
1558 for (child = w->hchild; !NILP (child); child = c->next)
1560 c = XWINDOW (child);
1562 opos = lastoright + XFASTINT (c->width);
1564 XFASTINT (c->left) = lastright;
1566 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1568 /* Inhibit deletion for becoming too small */
1569 set_window_width (child, pos + left - lastright, 1);
1571 /* Now advance child to next window,
1572 and set lastright if child was not just deleted. */
1573 lastright = pos + left, lastoright = opos;
1575 /* Delete children that became too small */
1576 if (!nodelete)
1577 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1579 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1584 int window_select_count;
1586 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1587 "Make WINDOW display BUFFER as its contents.\n\
1588 BUFFER can be a buffer or buffer name.")
1589 (window, buffer)
1590 register Lisp_Object window, buffer;
1592 register Lisp_Object tem;
1593 register struct window *w = decode_window (window);
1595 buffer = Fget_buffer (buffer);
1596 CHECK_BUFFER (buffer, 1);
1598 if (NILP (XBUFFER (buffer)->name))
1599 error ("Attempt to display deleted buffer");
1601 tem = w->buffer;
1602 if (NILP (tem))
1603 error ("Window is deleted");
1604 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1605 is first being set up. */
1607 if (!NILP (w->dedicated) && !EQ (tem, buffer))
1608 error ("Window is dedicated to %s\n", tem);
1610 unshow_buffer (w);
1613 w->buffer = buffer;
1614 w->window_end_pos = 0;
1615 w->window_end_valid = Qnil;
1616 w->hscroll = 0;
1617 Fset_marker (w->pointm,
1618 make_number (BUF_PT (XBUFFER (buffer))),
1619 buffer);
1620 set_marker_restricted (w->start,
1621 make_number (XBUFFER (buffer)->last_window_start),
1622 buffer);
1623 w->start_at_line_beg = Qnil;
1624 w->force_start = Qnil;
1625 XFASTINT (w->last_modified) = 0;
1626 windows_or_buffers_changed++;
1627 if (EQ (window, selected_window))
1628 Fset_buffer (buffer);
1630 return Qnil;
1633 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1634 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1635 The main editor command loop selects the buffer of the selected window\n\
1636 before each command.")
1637 (window)
1638 register Lisp_Object window;
1640 register struct window *w;
1641 register struct window *ow = XWINDOW (selected_window);
1643 CHECK_LIVE_WINDOW (window, 0);
1645 w = XWINDOW (window);
1647 if (NILP (w->buffer))
1648 error ("Trying to select deleted window or non-leaf window");
1650 XFASTINT (w->use_time) = ++window_select_count;
1651 if (EQ (window, selected_window))
1652 return window;
1654 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1655 ow->buffer);
1657 selected_window = window;
1658 #ifdef MULTI_FRAME
1659 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
1661 XFRAME (WINDOW_FRAME (w))->selected_window = window;
1662 Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
1664 else
1665 selected_frame->selected_window = window;
1666 #endif
1668 record_buffer (w->buffer);
1669 Fset_buffer (w->buffer);
1671 /* Go to the point recorded in the window.
1672 This is important when the buffer is in more
1673 than one window. It also matters when
1674 redisplay_window has altered point after scrolling,
1675 because it makes the change only in the window. */
1677 register int new_point = marker_position (w->pointm);
1678 if (new_point < BEGV)
1679 SET_PT (BEGV);
1680 if (new_point > ZV)
1681 SET_PT (ZV);
1682 else
1683 SET_PT (new_point);
1686 windows_or_buffers_changed++;
1687 return window;
1690 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
1691 "BDisplay buffer: \nP",
1692 "Make BUFFER appear in some window but don't select it.\n\
1693 BUFFER can be a buffer or a buffer name.\n\
1694 If BUFFER is shown already in some window, just use that one,\n\
1695 unless the window is the selected window and the optional second\n\
1696 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
1697 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
1698 Returns the window displaying BUFFER.")
1699 (buffer, not_this_window)
1700 register Lisp_Object buffer, not_this_window;
1702 register Lisp_Object window;
1704 buffer = Fget_buffer (buffer);
1705 CHECK_BUFFER (buffer, 0);
1707 if (!NILP (Vdisplay_buffer_function))
1708 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1710 if (NILP (not_this_window)
1711 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1712 return selected_window;
1714 #ifdef MULTI_FRAME
1715 /* If pop_up_frames,
1716 look for a window showing BUFFER on any visible frame. */
1717 window = Fget_buffer_window (buffer, pop_up_frames ? Qvisible : Qnil);
1718 #else
1719 window = Fget_buffer_window (buffer, Qnil);
1720 #endif
1721 if (!NILP (window)
1722 && (NILP (not_this_window) || !EQ (window, selected_window)))
1723 return window;
1725 #ifdef MULTI_FRAME
1726 /* If there are no frames open that have more than a minibuffer,
1727 we need to create a new frame. */
1728 if (pop_up_frames || last_nonminibuf_frame == 0)
1730 window
1731 = Fframe_selected_window (call0 (Vpop_up_frame_function));
1732 Fset_window_buffer (window, buffer);
1733 #if 0
1734 Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
1735 #endif
1736 return window;
1738 #endif /* MULTI_FRAME */
1740 if (pop_up_windows
1741 #ifdef MULTI_FRAME
1742 || FRAME_MINIBUF_ONLY_P (selected_frame)
1743 #endif
1746 Lisp_Object frames;
1748 frames = Qnil;
1749 #ifdef MULTI_FRAME
1750 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1751 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
1752 #endif
1753 /* Don't try to create a window if would get an error */
1754 if (split_height_threshold < window_min_height << 1)
1755 split_height_threshold = window_min_height << 1;
1757 window = Fget_largest_window (frames);
1759 if (!NILP (window)
1760 && window_height (window) >= split_height_threshold
1761 && (XFASTINT (XWINDOW (window)->width)
1762 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
1763 window = Fsplit_window (window, Qnil, Qnil);
1764 else
1766 window = Fget_lru_window (frames);
1767 if ((EQ (window, selected_window)
1768 || EQ (XWINDOW (window)->parent, Qnil))
1769 && window_height (window) >= window_min_height << 1)
1770 window = Fsplit_window (window, Qnil, Qnil);
1773 else
1774 window = Fget_lru_window (Qnil);
1776 Fset_window_buffer (window, buffer);
1777 return window;
1780 void
1781 temp_output_buffer_show (buf)
1782 register Lisp_Object buf;
1784 register struct buffer *old = current_buffer;
1785 register Lisp_Object window;
1786 register struct window *w;
1788 Fset_buffer (buf);
1789 XBUFFER (buf)->save_modified = MODIFF;
1790 BEGV = BEG;
1791 ZV = Z;
1792 SET_PT (BEG);
1793 clip_changed = 1;
1794 set_buffer_internal (old);
1796 if (!EQ (Vtemp_buffer_show_function, Qnil))
1797 call1 (Vtemp_buffer_show_function, buf);
1798 else
1800 window = Fdisplay_buffer (buf, Qnil);
1802 #ifdef MULTI_FRAME
1803 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1804 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1805 #endif /* MULTI_FRAME */
1806 Vminibuf_scroll_window = window;
1807 w = XWINDOW (window);
1808 XFASTINT (w->hscroll) = 0;
1809 set_marker_restricted (w->start, make_number (1), buf);
1810 set_marker_restricted (w->pointm, make_number (1), buf);
1814 static
1815 make_dummy_parent (window)
1816 Lisp_Object window;
1818 register Lisp_Object old, new;
1819 register struct window *o, *p;
1821 old = window;
1822 XSETTYPE (old, Lisp_Vector);
1823 new = Fcopy_sequence (old);
1824 XSETTYPE (new, Lisp_Window);
1826 o = XWINDOW (old);
1827 p = XWINDOW (new);
1828 XFASTINT (p->sequence_number) = ++sequence_number;
1830 /* Put new into window structure in place of window */
1831 replace_window (window, new);
1833 o->next = Qnil;
1834 o->prev = Qnil;
1835 o->vchild = Qnil;
1836 o->hchild = Qnil;
1837 o->parent = new;
1839 p->start = Qnil;
1840 p->pointm = Qnil;
1841 p->buffer = Qnil;
1844 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1845 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1846 WINDOW defaults to selected one and SIZE to half its size.\n\
1847 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1848 and put SIZE columns in the first of the pair.")
1849 (window, chsize, horflag)
1850 Lisp_Object window, chsize, horflag;
1852 register Lisp_Object new;
1853 register struct window *o, *p;
1854 register int size;
1856 if (NILP (window))
1857 window = selected_window;
1858 else
1859 CHECK_LIVE_WINDOW (window, 0);
1861 o = XWINDOW (window);
1863 if (NILP (chsize))
1865 if (!NILP (horflag))
1866 /* Round odd size up, since this is for the left-hand window,
1867 and it will lose a column for the separators. */
1868 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1869 else
1870 size = XFASTINT (o->height) >> 1;
1872 else
1874 CHECK_NUMBER (chsize, 1);
1875 size = XINT (chsize);
1878 if (MINI_WINDOW_P (o))
1879 error ("Attempt to split minibuffer window");
1880 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1881 error ("Attempt to split unsplittable frame");
1883 check_min_window_sizes ();
1885 if (NILP (horflag))
1887 if (size < window_min_height
1888 || size + window_min_height > XFASTINT (o->height))
1889 args_out_of_range_3 (window, chsize, horflag);
1890 if (NILP (o->parent)
1891 || NILP (XWINDOW (o->parent)->vchild))
1893 make_dummy_parent (window);
1894 new = o->parent;
1895 XWINDOW (new)->vchild = window;
1898 else
1900 if (size < window_min_width
1901 || size + window_min_width > XFASTINT (o->width))
1902 args_out_of_range_3 (window, chsize, horflag);
1903 if (NILP (o->parent)
1904 || NILP (XWINDOW (o->parent)->hchild))
1906 make_dummy_parent (window);
1907 new = o->parent;
1908 XWINDOW (new)->hchild = window;
1912 /* Now we know that window's parent is a vertical combination
1913 if we are dividing vertically, or a horizontal combination
1914 if we are making side-by-side windows */
1916 windows_or_buffers_changed++;
1917 new = make_window ();
1918 p = XWINDOW (new);
1920 p->frame = o->frame;
1921 p->next = o->next;
1922 if (!NILP (p->next))
1923 XWINDOW (p->next)->prev = new;
1924 p->prev = window;
1925 o->next = new;
1926 p->parent = o->parent;
1927 p->buffer = Qt;
1929 Fset_window_buffer (new, o->buffer);
1931 /* Apportion the available frame space among the two new windows */
1933 if (!NILP (horflag))
1935 p->height = o->height;
1936 p->top = o->top;
1937 XFASTINT (p->width) = XFASTINT (o->width) - size;
1938 XFASTINT (o->width) = size;
1939 XFASTINT (p->left) = XFASTINT (o->left) + size;
1941 else
1943 p->left = o->left;
1944 p->width = o->width;
1945 XFASTINT (p->height) = XFASTINT (o->height) - size;
1946 XFASTINT (o->height) = size;
1947 XFASTINT (p->top) = XFASTINT (o->top) + size;
1950 return new;
1953 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1954 "Make current window ARG lines bigger.\n\
1955 From program, optional second arg non-nil means grow sideways ARG columns.")
1956 (n, side)
1957 register Lisp_Object n, side;
1959 CHECK_NUMBER (n, 0);
1960 change_window_height (XINT (n), !NILP (side));
1961 return Qnil;
1964 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1965 "Make current window ARG lines smaller.\n\
1966 From program, optional second arg non-nil means shrink sideways ARG columns.")
1967 (n, side)
1968 register Lisp_Object n, side;
1970 CHECK_NUMBER (n, 0);
1971 change_window_height (-XINT (n), !NILP (side));
1972 return Qnil;
1976 window_height (window)
1977 Lisp_Object window;
1979 register struct window *p = XWINDOW (window);
1980 return XFASTINT (p->height);
1984 window_width (window)
1985 Lisp_Object window;
1987 register struct window *p = XWINDOW (window);
1988 return XFASTINT (p->width);
1991 #define MINSIZE(w) \
1992 (widthflag \
1993 ? window_min_width \
1994 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
1996 #define CURBEG(w) \
1997 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
1999 #define CURSIZE(w) \
2000 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
2002 /* Unlike set_window_height, this function
2003 also changes the heights of the siblings so as to
2004 keep everything consistent. */
2006 change_window_height (delta, widthflag)
2007 register int delta;
2008 int widthflag;
2010 register Lisp_Object parent;
2011 Lisp_Object window;
2012 register struct window *p;
2013 int *sizep;
2014 int (*sizefun) () = widthflag ? window_width : window_height;
2015 register int (*setsizefun) () = (widthflag
2016 ? set_window_width
2017 : set_window_height);
2019 check_min_window_sizes ();
2021 window = selected_window;
2022 while (1)
2024 p = XWINDOW (window);
2025 parent = p->parent;
2026 if (NILP (parent))
2028 if (widthflag)
2029 error ("No other window to side of this one");
2030 break;
2032 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2033 : !NILP (XWINDOW (parent)->vchild))
2034 break;
2035 window = parent;
2038 sizep = &CURSIZE (window);
2040 if (*sizep + delta < MINSIZE (window))
2042 Fdelete_window (window);
2043 return;
2047 register int maxdelta;
2049 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2050 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2051 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
2052 /* This is a frame with only one window, a minibuffer-only
2053 or a minibufferless frame. */
2054 : (delta = 0));
2056 if (delta > maxdelta)
2057 /* This case traps trying to make the minibuffer
2058 the full frame, or make the only window aside from the
2059 minibuffer the full frame. */
2060 delta = maxdelta;
2062 if (delta == 0)
2063 return;
2066 if (!NILP (p->next) &&
2067 (*sizefun) (p->next) - delta >= MINSIZE (p->next))
2069 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
2070 (*setsizefun) (window, *sizep + delta, 0);
2071 CURBEG (p->next) += delta;
2072 /* This does not change size of p->next,
2073 but it propagates the new top edge to its children */
2074 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
2076 else if (!NILP (p->prev) &&
2077 (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
2079 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
2080 CURBEG (window) -= delta;
2081 (*setsizefun) (window, *sizep + delta, 0);
2083 else
2085 register int delta1;
2086 register int opht = (*sizefun) (parent);
2088 /* If trying to grow this window to or beyond size of the parent,
2089 make delta1 so big that, on shrinking back down,
2090 all the siblings end up with less than one line and are deleted. */
2091 if (opht <= *sizep + delta)
2092 delta1 = opht * opht * 2;
2093 /* Otherwise, make delta1 just right so that if we add delta1
2094 lines to this window and to the parent, and then shrink
2095 the parent back to its original size, the new proportional
2096 size of this window will increase by delta. */
2097 else
2098 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2100 /* Add delta1 lines or columns to this window, and to the parent,
2101 keeping things consistent while not affecting siblings. */
2102 CURSIZE (parent) = opht + delta1;
2103 (*setsizefun) (window, *sizep + delta1, 0);
2105 /* Squeeze out delta1 lines or columns from our parent,
2106 shriking this window and siblings proportionately.
2107 This brings parent back to correct size.
2108 Delta1 was calculated so this makes this window the desired size,
2109 taking it all out of the siblings. */
2110 (*setsizefun) (parent, opht, 0);
2113 XFASTINT (p->last_modified) = 0;
2115 #undef MINSIZE
2116 #undef CURBEG
2117 #undef CURSIZE
2120 /* Return number of lines of text (not counting mode line) in W. */
2123 window_internal_height (w)
2124 struct window *w;
2126 int ht = XFASTINT (w->height);
2128 if (MINI_WINDOW_P (w))
2129 return ht;
2131 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2132 || !NILP (w->next) || !NILP (w->prev)
2133 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
2134 return ht - 1;
2136 return ht;
2140 /* Return the number of columns in W.
2141 Don't count columns occupied by scroll bars or the vertical bar
2142 separating W from the sibling to its right. */
2144 window_internal_width (w)
2145 struct window *w;
2147 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2148 int left = XINT (w->left);
2149 int width = XINT (w->width);
2151 /* If this window is flush against the right edge of the frame, its
2152 internal width is its full width. */
2153 if (left + width >= FRAME_WIDTH (f))
2154 return width;
2156 /* If we are not flush right, then our rightmost columns are
2157 occupied by some sort of separator. */
2159 /* Scroll bars occupy a few columns. */
2160 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2161 return width - VERTICAL_SCROLL_BAR_WIDTH;
2163 /* The column of `|' characters separating side-by-side windows
2164 occupies one column only. */
2165 return width - 1;
2169 /* Scroll contents of window WINDOW up N lines. */
2171 void
2172 window_scroll (window, n, noerror)
2173 Lisp_Object window;
2174 int n;
2175 int noerror;
2177 register struct window *w = XWINDOW (window);
2178 register int opoint = point;
2179 register int pos;
2180 register int ht = window_internal_height (w);
2181 register Lisp_Object tem;
2182 int lose;
2183 Lisp_Object bolp, nmoved;
2185 XFASTINT (tem) = point;
2186 tem = Fpos_visible_in_window_p (tem, window);
2188 if (NILP (tem))
2190 Fvertical_motion (make_number (- (ht / 2)), window);
2191 XFASTINT (tem) = point;
2192 Fset_marker (w->start, tem, w->buffer);
2193 w->force_start = Qt;
2196 SET_PT (marker_position (w->start));
2197 lose = n < 0 && point == BEGV;
2198 Fvertical_motion (make_number (n), window);
2199 pos = point;
2200 bolp = Fbolp ();
2201 SET_PT (opoint);
2203 if (lose)
2205 if (noerror)
2206 return;
2207 else
2208 Fsignal (Qbeginning_of_buffer, Qnil);
2211 if (pos < ZV)
2213 set_marker_restricted (w->start, make_number (pos), w->buffer);
2214 w->start_at_line_beg = bolp;
2215 w->update_mode_line = Qt;
2216 XFASTINT (w->last_modified) = 0;
2217 if (pos > opoint)
2218 SET_PT (pos);
2219 if (n < 0)
2221 SET_PT (pos);
2222 tem = Fvertical_motion (make_number (ht), window);
2223 if (point > opoint || XFASTINT (tem) < ht)
2224 SET_PT (opoint);
2225 else
2226 Fvertical_motion (make_number (-1), window);
2229 else
2231 if (noerror)
2232 return;
2233 else
2234 Fsignal (Qend_of_buffer, Qnil);
2238 /* This is the guts of Fscroll_up and Fscroll_down. */
2240 static void
2241 scroll_command (n, direction)
2242 register Lisp_Object n;
2243 int direction;
2245 register int defalt;
2246 int count = specpdl_ptr - specpdl;
2248 /* If selected window's buffer isn't current, make it current for the moment.
2249 But don't screw up if window_scroll gets an error. */
2250 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2252 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2253 Fset_buffer (XWINDOW (selected_window)->buffer);
2256 defalt = (window_internal_height (XWINDOW (selected_window))
2257 - next_screen_context_lines);
2258 defalt = direction * (defalt < 1 ? 1 : defalt);
2260 if (NILP (n))
2261 window_scroll (selected_window, defalt, 0);
2262 else if (EQ (n, Qminus))
2263 window_scroll (selected_window, - defalt, 0);
2264 else
2266 n = Fprefix_numeric_value (n);
2267 window_scroll (selected_window, XINT (n) * direction, 0);
2270 unbind_to (count, Qnil);
2273 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2274 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2275 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2276 Negative ARG means scroll downward.\n\
2277 When calling from a program, supply a number as argument or nil.")
2279 Lisp_Object n;
2281 scroll_command (n, 1);
2282 return Qnil;
2285 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2286 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2287 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2288 Negative ARG means scroll upward.\n\
2289 When calling from a program, supply a number as argument or nil.")
2291 Lisp_Object n;
2293 scroll_command (n, -1);
2294 return Qnil;
2297 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2298 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2299 The next window is the one below the current one; or the one at the top\n\
2300 if the current one is at the bottom. Negative ARG means scroll downward.\n\
2301 When calling from a program, supply a number as argument or nil.\n\
2303 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2304 specifies the window to scroll.\n\
2305 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2306 showing that buffer, popping the buffer up if necessary.")
2308 register Lisp_Object n;
2310 register Lisp_Object window;
2311 register int ht;
2312 register struct window *w;
2313 register int count = specpdl_ptr - specpdl;
2315 if (MINI_WINDOW_P (XWINDOW (selected_window))
2316 && !NILP (Vminibuf_scroll_window))
2317 window = Vminibuf_scroll_window;
2318 /* If buffer is specified, scroll that buffer. */
2319 else if (!NILP (Vother_window_scroll_buffer))
2321 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
2322 if (NILP (window))
2323 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2325 else
2327 /* Nothing specified; look for a neighboring window on the same
2328 frame. */
2329 window = Fnext_window (selected_window, Qnil, Qnil);
2331 if (EQ (window, selected_window))
2332 /* That didn't get us anywhere; look for a window on another
2333 visible frame. */
2335 window = Fnext_window (window, Qnil, Qt);
2336 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2337 && ! EQ (window, selected_window));
2340 CHECK_LIVE_WINDOW (window, 0);
2342 if (EQ (window, selected_window))
2343 error ("There is no other window");
2345 w = XWINDOW (window);
2346 ht = window_internal_height (w);
2348 /* Don't screw up if window_scroll gets an error. */
2349 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2351 Fset_buffer (w->buffer);
2352 SET_PT (marker_position (w->pointm));
2354 if (NILP (n))
2355 window_scroll (window, ht - next_screen_context_lines, 1);
2356 else if (EQ (n, Qminus))
2357 window_scroll (window, next_screen_context_lines - ht, 1);
2358 else
2360 if (XTYPE (n) == Lisp_Cons)
2361 n = Fcar (n);
2362 CHECK_NUMBER (n, 0);
2363 window_scroll (window, XINT (n), 1);
2366 Fset_marker (w->pointm, make_number (point), Qnil);
2367 unbind_to (count, Qnil);
2369 return Qnil;
2372 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
2373 "Scroll selected window display ARG columns left.\n\
2374 Default for ARG is window width minus 2.")
2375 (arg)
2376 register Lisp_Object arg;
2379 if (NILP (arg))
2380 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
2381 else
2382 arg = Fprefix_numeric_value (arg);
2384 return
2385 Fset_window_hscroll (selected_window,
2386 make_number (XINT (XWINDOW (selected_window)->hscroll)
2387 + XINT (arg)));
2390 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
2391 "Scroll selected window display ARG columns right.\n\
2392 Default for ARG is window width minus 2.")
2393 (arg)
2394 register Lisp_Object arg;
2396 if (NILP (arg))
2397 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
2398 else
2399 arg = Fprefix_numeric_value (arg);
2401 return
2402 Fset_window_hscroll (selected_window,
2403 make_number (XINT (XWINDOW (selected_window)->hscroll)
2404 - XINT (arg)));
2407 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
2408 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2409 The desired position of point is always relative to the current window.\n\
2410 Just C-u as prefix means put point in the center of the window.\n\
2411 No arg (i.e., it is nil) erases the entire frame and then\n\
2412 redraws with point in the center of the current window.")
2414 register Lisp_Object n;
2416 register struct window *w = XWINDOW (selected_window);
2417 register int ht = window_internal_height (w);
2418 register int opoint = point;
2419 Lisp_Object window;
2421 if (NILP (n))
2423 extern int frame_garbaged;
2425 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
2426 XFASTINT (n) = ht / 2;
2428 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2430 XFASTINT (n) = ht / 2;
2432 else
2434 n = Fprefix_numeric_value (n);
2435 CHECK_NUMBER (n, 0);
2438 if (XINT (n) < 0)
2439 XSETINT (n, XINT (n) + ht);
2441 XSETINT (n, - XINT (n));
2443 XSET (window, Lisp_Window, w);
2444 Fvertical_motion (n, window);
2445 Fset_marker (w->start, make_number (point), w->buffer);
2446 w->start_at_line_beg = Fbolp ();
2448 SET_PT (opoint);
2449 w->force_start = Qt;
2451 return Qnil;
2454 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2455 1, 1, "P",
2456 "Position point relative to window.\n\
2457 With no argument, position text at center of window.\n\
2458 An argument specifies frame line; zero means top of window,\n\
2459 negative means relative to bottom of window.")
2460 (arg)
2461 register Lisp_Object arg;
2463 register struct window *w = XWINDOW (selected_window);
2464 register int height = window_internal_height (w);
2465 register int start;
2466 Lisp_Object window;
2468 if (NILP (arg))
2469 XFASTINT (arg) = height / 2;
2470 else
2472 arg = Fprefix_numeric_value (arg);
2473 if (XINT (arg) < 0)
2474 XSETINT (arg, XINT (arg) + height);
2477 start = marker_position (w->start);
2478 XSET (window, Lisp_Window, w);
2479 if (start < BEGV || start > ZV)
2481 Fvertical_motion (make_number (- (height / 2)), window);
2482 Fset_marker (w->start, make_number (point), w->buffer);
2483 w->start_at_line_beg = Fbolp ();
2484 w->force_start = Qt;
2486 else
2487 SET_PT (start);
2489 return Fvertical_motion (arg, window);
2492 struct save_window_data
2494 int size_from_Lisp_Vector_struct;
2495 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2496 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
2497 Lisp_Object selected_frame;
2498 Lisp_Object current_window;
2499 Lisp_Object current_buffer;
2500 Lisp_Object minibuf_scroll_window;
2501 Lisp_Object root_window;
2502 Lisp_Object focus_frame;
2503 /* A vector, interpreted as a struct saved_window */
2504 Lisp_Object saved_windows;
2507 /* Arg to Fmake_vector */
2508 #define SAVE_WINDOW_DATA_SIZE \
2509 ((sizeof (struct save_window_data) \
2510 - (sizeof (struct Lisp_Vector) \
2511 /* Don't count the contents member of the struct Lisp_Vector */ \
2512 - sizeof (Lisp_Object))) \
2513 / sizeof (Lisp_Object))
2515 /* This is saved as a Lisp_Vector */
2516 struct saved_window
2518 /* these first two must agree with struct Lisp_Vector in lisp.h */
2519 int size_from_Lisp_Vector_struct;
2520 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2522 Lisp_Object window;
2523 Lisp_Object buffer, start, pointm, mark;
2524 Lisp_Object left, top, width, height, hscroll;
2525 Lisp_Object parent, prev;
2526 Lisp_Object start_at_line_beg;
2527 Lisp_Object display_table;
2529 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2531 #define SAVED_WINDOW_N(swv,n) \
2532 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2534 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2535 "T if OBJECT is a window-configration object.")
2536 (obj)
2537 Lisp_Object obj;
2539 if (XTYPE (obj) == Lisp_Window_Configuration)
2540 return Qt;
2541 return Qnil;
2545 DEFUN ("set-window-configuration", Fset_window_configuration,
2546 Sset_window_configuration, 1, 1, 0,
2547 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2548 CONFIGURATION must be a value previously returned\n\
2549 by `current-window-configuration' (which see).")
2550 (configuration)
2551 Lisp_Object configuration;
2553 register struct save_window_data *data;
2554 struct Lisp_Vector *saved_windows;
2555 Lisp_Object new_current_buffer;
2556 Lisp_Object frame;
2557 FRAME_PTR f;
2559 while (XTYPE (configuration) != Lisp_Window_Configuration)
2561 configuration = wrong_type_argument (intern ("window-configuration-p"),
2562 configuration);
2565 data = (struct save_window_data *) XVECTOR (configuration);
2566 saved_windows = XVECTOR (data->saved_windows);
2568 new_current_buffer = data->current_buffer;
2569 if (NILP (XBUFFER (new_current_buffer)->name))
2570 new_current_buffer = Qnil;
2572 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2573 f = XFRAME (frame);
2575 /* If f is a dead frame, don't bother rebuilding its window tree.
2576 However, there is other stuff we should still try to do below. */
2577 if (FRAME_LIVE_P (f))
2579 register struct window *w;
2580 register struct saved_window *p;
2581 int k;
2583 /* If the frame has been resized since this window configuration was
2584 made, we change the frame to the size specified in the
2585 configuration, restore the configuration, and then resize it
2586 back. We keep track of the prevailing height in these variables. */
2587 int previous_frame_height = FRAME_HEIGHT (f);
2588 int previous_frame_width = FRAME_WIDTH (f);
2589 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
2591 if (XFASTINT (data->frame_height) != previous_frame_height
2592 || XFASTINT (data->frame_width) != previous_frame_width)
2593 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
2594 #ifdef HAVE_X_WINDOWS
2595 if (XFASTINT (data->frame_menu_bar_lines)
2596 != previous_frame_menu_bar_lines)
2597 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
2598 #endif
2600 windows_or_buffers_changed++;
2602 /* Kludge Alert!
2603 Mark all windows now on frame as "deleted".
2604 Restoring the new configuration "undeletes" any that are in it.
2606 Save their current buffers in their height fields, since we may
2607 need it later, if a buffer saved in the configuration is now
2608 dead. */
2609 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2611 for (k = 0; k < saved_windows->size; k++)
2613 p = SAVED_WINDOW_N (saved_windows, k);
2614 w = XWINDOW (p->window);
2615 w->next = Qnil;
2617 if (!NILP (p->parent))
2618 w->parent = SAVED_WINDOW_N (saved_windows,
2619 XFASTINT (p->parent))->window;
2620 else
2621 w->parent = Qnil;
2623 if (!NILP (p->prev))
2625 w->prev = SAVED_WINDOW_N (saved_windows,
2626 XFASTINT (p->prev))->window;
2627 XWINDOW (w->prev)->next = p->window;
2629 else
2631 w->prev = Qnil;
2632 if (!NILP (w->parent))
2634 if (EQ (p->width, XWINDOW (w->parent)->width))
2636 XWINDOW (w->parent)->vchild = p->window;
2637 XWINDOW (w->parent)->hchild = Qnil;
2639 else
2641 XWINDOW (w->parent)->hchild = p->window;
2642 XWINDOW (w->parent)->vchild = Qnil;
2647 /* If we squirreled away the buffer in the window's height,
2648 restore it now. */
2649 if (XTYPE (w->height) == Lisp_Buffer)
2650 w->buffer = w->height;
2651 w->left = p->left;
2652 w->top = p->top;
2653 w->width = p->width;
2654 w->height = p->height;
2655 w->hscroll = p->hscroll;
2656 w->display_table = p->display_table;
2657 XFASTINT (w->last_modified) = 0;
2659 /* Reinstall the saved buffer and pointers into it. */
2660 if (NILP (p->buffer))
2661 w->buffer = p->buffer;
2662 else
2664 if (!NILP (XBUFFER (p->buffer)->name))
2665 /* If saved buffer is alive, install it. */
2667 w->buffer = p->buffer;
2668 w->start_at_line_beg = p->start_at_line_beg;
2669 set_marker_restricted (w->start,
2670 Fmarker_position (p->start),
2671 w->buffer);
2672 set_marker_restricted (w->pointm,
2673 Fmarker_position (p->pointm),
2674 w->buffer);
2675 Fset_marker (XBUFFER (w->buffer)->mark,
2676 Fmarker_position (p->mark), w->buffer);
2678 /* As documented in Fcurrent_window_configuration, don't
2679 save the location of point in the buffer which was current
2680 when the window configuration was recorded. */
2681 if (!EQ (p->buffer, new_current_buffer) &&
2682 XBUFFER (p->buffer) == current_buffer)
2683 Fgoto_char (w->pointm);
2685 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
2686 /* Else unless window has a live buffer, get one. */
2688 w->buffer = Fcdr (Fcar (Vbuffer_alist));
2689 /* This will set the markers to beginning of visible
2690 range. */
2691 set_marker_restricted (w->start, make_number (0), w->buffer);
2692 set_marker_restricted (w->pointm, make_number (0),w->buffer);
2693 w->start_at_line_beg = Qt;
2695 else
2696 /* Keeping window's old buffer; make sure the markers
2697 are real. */
2699 /* Set window markers at start of visible range. */
2700 if (XMARKER (w->start)->buffer == 0)
2701 set_marker_restricted (w->start, make_number (0),
2702 w->buffer);
2703 if (XMARKER (w->pointm)->buffer == 0)
2704 set_marker_restricted (w->pointm,
2705 (make_number
2706 (BUF_PT (XBUFFER (w->buffer)))),
2707 w->buffer);
2708 w->start_at_line_beg = Qt;
2713 FRAME_ROOT_WINDOW (f) = data->root_window;
2714 Fselect_window (data->current_window);
2716 #ifdef MULTI_FRAME
2717 if (NILP (data->focus_frame)
2718 || (XTYPE (data->focus_frame) == Lisp_Frame
2719 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
2720 Fredirect_frame_focus (frame, data->focus_frame);
2721 #endif
2723 #if 0 /* I don't understand why this is needed, and it causes problems
2724 when the frame's old selected window has been deleted. */
2725 #ifdef MULTI_FRAME
2726 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
2727 Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
2728 #endif
2729 #endif
2731 /* Set the screen height to the value it had before this function. */
2732 if (previous_frame_height != FRAME_HEIGHT (f)
2733 || previous_frame_width != FRAME_WIDTH (f))
2734 change_frame_size (f, previous_frame_height, previous_frame_width,
2735 0, 0);
2736 #ifdef HAVE_X_WINDOWS
2737 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
2738 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
2739 #endif
2742 #ifdef MULTI_FRAME
2743 /* Fselect_window will have made f the selected frame, so we
2744 reselect the proper frame here. Fhandle_switch_frame will change the
2745 selected window too, but that doesn't make the call to
2746 Fselect_window above totally superfluous; it still sets f's
2747 selected window. */
2748 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
2749 Fhandle_switch_frame (data->selected_frame, Qnil);
2750 #endif
2752 if (!NILP (new_current_buffer))
2753 Fset_buffer (new_current_buffer);
2755 Vminibuf_scroll_window = data->minibuf_scroll_window;
2756 return (Qnil);
2759 /* Mark all windows now on frame as deleted
2760 by setting their buffers to nil. */
2762 void
2763 delete_all_subwindows (w)
2764 register struct window *w;
2766 if (!NILP (w->next))
2767 delete_all_subwindows (XWINDOW (w->next));
2768 if (!NILP (w->vchild))
2769 delete_all_subwindows (XWINDOW (w->vchild));
2770 if (!NILP (w->hchild))
2771 delete_all_subwindows (XWINDOW (w->hchild));
2773 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
2775 /* We set all three of these fields to nil, to make sure that we can
2776 distinguish this dead window from any live window. Live leaf
2777 windows will have buffer set, and combination windows will have
2778 vchild or hchild set. */
2779 w->buffer = Qnil;
2780 w->vchild = Qnil;
2781 w->hchild = Qnil;
2784 static int
2785 count_windows (window)
2786 register struct window *window;
2788 register int count = 1;
2789 if (!NILP (window->next))
2790 count += count_windows (XWINDOW (window->next));
2791 if (!NILP (window->vchild))
2792 count += count_windows (XWINDOW (window->vchild));
2793 if (!NILP (window->hchild))
2794 count += count_windows (XWINDOW (window->hchild));
2795 return count;
2798 static int
2799 save_window_save (window, vector, i)
2800 Lisp_Object window;
2801 struct Lisp_Vector *vector;
2802 int i;
2804 register struct saved_window *p;
2805 register struct window *w;
2806 register Lisp_Object tem;
2808 for (;!NILP (window); window = w->next)
2810 p = SAVED_WINDOW_N (vector, i);
2811 w = XWINDOW (window);
2813 XFASTINT (w->temslot) = i++;
2814 p->window = window;
2815 p->buffer = w->buffer;
2816 p->left = w->left;
2817 p->top = w->top;
2818 p->width = w->width;
2819 p->height = w->height;
2820 p->hscroll = w->hscroll;
2821 p->display_table = w->display_table;
2822 if (!NILP (w->buffer))
2824 /* Save w's value of point in the window configuration.
2825 If w is the selected window, then get the value of point
2826 from the buffer; pointm is garbage in the selected window. */
2827 if (EQ (window, selected_window))
2829 p->pointm = Fmake_marker ();
2830 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
2831 w->buffer);
2833 else
2834 p->pointm = Fcopy_marker (w->pointm);
2836 p->start = Fcopy_marker (w->start);
2837 p->start_at_line_beg = w->start_at_line_beg;
2839 tem = XBUFFER (w->buffer)->mark;
2840 p->mark = Fcopy_marker (tem);
2842 else
2844 p->pointm = Qnil;
2845 p->start = Qnil;
2846 p->mark = Qnil;
2847 p->start_at_line_beg = Qnil;
2850 if (NILP (w->parent))
2851 p->parent = Qnil;
2852 else
2853 p->parent = XWINDOW (w->parent)->temslot;
2855 if (NILP (w->prev))
2856 p->prev = Qnil;
2857 else
2858 p->prev = XWINDOW (w->prev)->temslot;
2860 if (!NILP (w->vchild))
2861 i = save_window_save (w->vchild, vector, i);
2862 if (!NILP (w->hchild))
2863 i = save_window_save (w->hchild, vector, i);
2866 return i;
2869 DEFUN ("current-window-configuration",
2870 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
2871 "Return an object representing the current window configuration of FRAME.\n\
2872 If FRAME is nil or omitted, use the selected frame.\n\
2873 This describes the number of windows, their sizes and current buffers,\n\
2874 and for each displayed buffer, where display starts, and the positions of\n\
2875 point and mark. An exception is made for point in the current buffer:\n\
2876 its value is -not- saved.\n\
2877 This also records the currently selected frame, and FRAME's focus\n\
2878 redirection (see `redirect-frame-focus').")
2879 (frame)
2880 Lisp_Object frame;
2882 register Lisp_Object tem;
2883 register int n_windows;
2884 register struct save_window_data *data;
2885 register int i;
2886 FRAME_PTR f;
2888 if (NILP (frame))
2889 f = selected_frame;
2890 else
2892 CHECK_LIVE_FRAME (frame, 0);
2893 f = XFRAME (frame);
2896 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2897 data = (struct save_window_data *)
2898 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2899 Qnil));
2900 XFASTINT (data->frame_width) = FRAME_WIDTH (f);
2901 XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
2902 XFASTINT (data->frame_menu_bar_lines) = FRAME_MENU_BAR_LINES (f);
2903 #ifdef MULTI_FRAME
2904 XSET (data->selected_frame, Lisp_Frame, selected_frame);
2905 #endif
2906 data->current_window = FRAME_SELECTED_WINDOW (f);
2907 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2908 data->minibuf_scroll_window = Vminibuf_scroll_window;
2909 data->root_window = FRAME_ROOT_WINDOW (f);
2910 data->focus_frame = FRAME_FOCUS_FRAME (f);
2911 tem = Fmake_vector (make_number (n_windows), Qnil);
2912 data->saved_windows = tem;
2913 for (i = 0; i < n_windows; i++)
2914 XVECTOR (tem)->contents[i]
2915 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
2916 save_window_save (FRAME_ROOT_WINDOW (f),
2917 XVECTOR (tem), 0);
2918 XSET (tem, Lisp_Window_Configuration, data);
2919 return (tem);
2922 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
2923 0, UNEVALLED, 0,
2924 "Execute body, preserving window sizes and contents.\n\
2925 Restores which buffer appears in which window, where display starts,\n\
2926 as well as the current buffer.\n\
2927 Does not restore the value of point in current buffer.")
2928 (args)
2929 Lisp_Object args;
2931 register Lisp_Object val;
2932 register int count = specpdl_ptr - specpdl;
2934 record_unwind_protect (Fset_window_configuration,
2935 Fcurrent_window_configuration (Qnil));
2936 val = Fprogn (args);
2937 return unbind_to (count, val);
2940 init_window_once ()
2942 #ifdef MULTI_FRAME
2943 selected_frame = make_terminal_frame ();
2944 minibuf_window = selected_frame->minibuffer_window;
2945 selected_window = selected_frame->selected_window;
2946 last_nonminibuf_frame = selected_frame;
2947 #else /* not MULTI_FRAME */
2948 extern Lisp_Object get_minibuffer ();
2950 minibuf_window = make_window ();
2951 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
2953 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
2954 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
2955 XWINDOW (minibuf_window)->mini_p = Qt;
2957 /* These values 9 and 10 are arbitrary,
2958 just so that there is "something there."
2959 Correct values are put in in init_xdisp */
2961 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
2962 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
2964 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
2965 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
2966 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
2968 /* Prevent error in Fset_window_buffer. */
2969 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
2970 XWINDOW (minibuf_window)->buffer = Qt;
2972 /* Now set them up for real. */
2973 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
2974 Fcurrent_buffer ());
2975 Fset_window_buffer (minibuf_window, get_minibuffer (0));
2977 selected_window = FRAME_ROOT_WINDOW (selected_frame);
2978 /* Make sure this window seems more recently used than
2979 a newly-created, never-selected window. Increment
2980 window_select_count so the first selection ever will get
2981 something newer than this. */
2982 XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
2983 #endif /* not MULTI_FRAME */
2986 syms_of_window ()
2988 Qwindowp = intern ("windowp");
2989 staticpro (&Qwindowp);
2991 Qwindow_live_p = intern ("window-live-p");
2992 staticpro (&Qwindow_live_p);
2994 #ifndef MULTI_FRAME
2995 /* Make sure all windows get marked */
2996 staticpro (&minibuf_window);
2997 #endif
2999 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
3000 "Non-nil means call as function to display a help buffer.\n\
3001 Used by `with-output-to-temp-buffer'.");
3002 Vtemp_buffer_show_function = Qnil;
3004 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
3005 "If non-nil, function to call to handle `display-buffer'.\n\
3006 It will receive two args, the buffer and a flag which if non-nil means\n\
3007 that the currently selected window is not acceptable.\n\
3008 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3009 work using this function.");
3010 Vdisplay_buffer_function = Qnil;
3012 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3013 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3014 Vminibuf_scroll_window = Qnil;
3016 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3017 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3018 Vother_window_scroll_buffer = Qnil;
3020 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
3021 "*Non-nil means `display-buffer' should make a separate frame.");
3022 pop_up_frames = 0;
3024 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
3025 "*If non-nil, function to call to handle automatic new frame creation.\n\
3026 It is called with no arguments and should return a newly created frame.\n\
3028 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3029 where `pop-up-frame-alist' would hold the default frame parameters.");
3030 Vpop_up_frame_function = Qnil;
3032 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3033 "*Non-nil means display-buffer should make new windows.");
3034 pop_up_windows = 1;
3036 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3037 "*Number of lines of continuity when scrolling by screenfuls.");
3038 next_screen_context_lines = 2;
3040 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3041 "*display-buffer would prefer to split the largest window if this large.\n\
3042 If there is only one window, it is split regardless of this value.");
3043 split_height_threshold = 500;
3045 DEFVAR_INT ("window-min-height", &window_min_height,
3046 "*Delete any window less than this tall (including its mode line).");
3047 window_min_height = 4;
3049 DEFVAR_INT ("window-min-width", &window_min_width,
3050 "*Delete any window less than this wide.");
3051 window_min_width = 10;
3053 defsubr (&Sselected_window);
3054 defsubr (&Sminibuffer_window);
3055 defsubr (&Swindow_minibuffer_p);
3056 defsubr (&Swindowp);
3057 defsubr (&Swindow_live_p);
3058 defsubr (&Spos_visible_in_window_p);
3059 defsubr (&Swindow_buffer);
3060 defsubr (&Swindow_height);
3061 defsubr (&Swindow_width);
3062 defsubr (&Swindow_hscroll);
3063 defsubr (&Sset_window_hscroll);
3064 defsubr (&Swindow_edges);
3065 defsubr (&Scoordinates_in_window_p);
3066 defsubr (&Swindow_at);
3067 defsubr (&Swindow_point);
3068 defsubr (&Swindow_start);
3069 defsubr (&Swindow_end);
3070 defsubr (&Sset_window_point);
3071 defsubr (&Sset_window_start);
3072 defsubr (&Swindow_dedicated_p);
3073 defsubr (&Sset_window_dedicated_p);
3074 defsubr (&Swindow_display_table);
3075 defsubr (&Sset_window_display_table);
3076 defsubr (&Snext_window);
3077 defsubr (&Sprevious_window);
3078 defsubr (&Sother_window);
3079 defsubr (&Sget_lru_window);
3080 defsubr (&Sget_largest_window);
3081 defsubr (&Sget_buffer_window);
3082 defsubr (&Sdelete_other_windows);
3083 defsubr (&Sdelete_windows_on);
3084 defsubr (&Sreplace_buffer_in_windows);
3085 defsubr (&Sdelete_window);
3086 defsubr (&Sset_window_buffer);
3087 defsubr (&Sselect_window);
3088 defsubr (&Sdisplay_buffer);
3089 defsubr (&Ssplit_window);
3090 defsubr (&Senlarge_window);
3091 defsubr (&Sshrink_window);
3092 defsubr (&Sscroll_up);
3093 defsubr (&Sscroll_down);
3094 defsubr (&Sscroll_left);
3095 defsubr (&Sscroll_right);
3096 defsubr (&Sscroll_other_window);
3097 defsubr (&Srecenter);
3098 defsubr (&Smove_to_window_line);
3099 defsubr (&Swindow_configuration_p);
3100 defsubr (&Sset_window_configuration);
3101 defsubr (&Scurrent_window_configuration);
3102 defsubr (&Ssave_window_excursion);
3105 keys_of_window ()
3107 initial_define_key (control_x_map, '1', "delete-other-windows");
3108 initial_define_key (control_x_map, '2', "split-window");
3109 initial_define_key (control_x_map, '0', "delete-window");
3110 initial_define_key (control_x_map, 'o', "other-window");
3111 initial_define_key (control_x_map, '^', "enlarge-window");
3112 initial_define_key (control_x_map, '<', "scroll-left");
3113 initial_define_key (control_x_map, '>', "scroll-right");
3115 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3116 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3117 initial_define_key (meta_map, 'v', "scroll-down");
3119 initial_define_key (global_map, Ctl('L'), "recenter");
3120 initial_define_key (meta_map, 'r', "move-to-window-line");