entered into RCS
[emacs.git] / src / window.c
blob7db2bfec0757bda124a63218b7c1b9ce783eea20
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1992 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;
34 Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
35 Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
37 static 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 /* Window that the mouse is over (nil if no mouse support). */
64 Lisp_Object Vmouse_window;
66 /* Last mouse click data structure (nil if no mouse support). */
67 Lisp_Object Vmouse_event;
69 /* Non-nil means it's function to call to display temp buffers. */
70 Lisp_Object Vtemp_buffer_show_function;
72 /* If a window gets smaller than either of these, it is removed. */
73 int window_min_height;
74 int window_min_width;
76 /* Nonzero implies Fdisplay_buffer should create windows. */
77 int pop_up_windows;
79 /* Nonzero implies make new frames for Fdisplay_buffer. */
80 int pop_up_frames;
82 /* Non-nil means use this function instead of default */
83 Lisp_Object Vpop_up_frame_function;
85 /* Function to call to handle Fdisplay_buffer. */
86 Lisp_Object Vdisplay_buffer_function;
88 /* Fdisplay_buffer always splits the largest window
89 if that window is more than this high. */
90 int split_height_threshold;
92 /* Number of lines of continuity in scrolling by screenfuls. */
93 int next_screen_context_lines;
95 /* Incremented for each window created. */
96 static int sequence_number;
98 #define min(a, b) ((a) < (b) ? (a) : (b))
100 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
101 "Returns t if OBJ is a window.")
102 (obj)
103 Lisp_Object obj;
105 return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
108 Lisp_Object
109 make_window ()
111 register Lisp_Object val;
112 register struct window *p;
114 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
115 includes the first element. */
116 val = Fmake_vector (
117 make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)
118 + sizeof (Lisp_Object))
119 / sizeof (Lisp_Object)),
120 Qnil);
121 XSETTYPE (val, Lisp_Window);
122 p = XWINDOW (val);
123 XFASTINT (p->sequence_number) = ++sequence_number;
124 XFASTINT (p->left) = XFASTINT (p->top)
125 = XFASTINT (p->height) = XFASTINT (p->width)
126 = XFASTINT (p->hscroll) = 0;
127 XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
128 p->start = Fmake_marker ();
129 p->pointm = Fmake_marker ();
130 XFASTINT (p->use_time) = 0;
131 p->frame = Qnil;
132 p->display_table = Qnil;
133 p->dedicated = Qnil;
134 return val;
137 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
138 "Return the window that the cursor now appears in and commands apply to.")
141 return selected_window;
144 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 0, 0,
145 "Return the window used now for minibuffers.")
148 #ifdef MULTI_FRAME
149 choose_minibuf_frame ();
150 #endif /* MULTI_FRAME */
151 return minibuf_window;
154 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 1, 1, 0,
155 "Returns non-nil if WINDOW is a minibuffer window.")
156 (window)
157 Lisp_Object window;
159 struct window *w = decode_window (window);
160 return (MINI_WINDOW_P (w) ? Qt : Qnil);
163 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
164 Spos_visible_in_window_p, 0, 2, 0,
165 "Return t if position POS is currently on the frame in WINDOW.\n\
166 Returns nil if that position is scrolled vertically out of view.\n\
167 POS defaults to point; WINDOW, to the selected window.")
168 (pos, window)
169 Lisp_Object pos, window;
171 register struct window *w;
172 register int top;
173 register int height;
174 register int posint;
175 register struct buffer *buf;
176 struct position posval;
178 if (NILP (pos))
179 posint = point;
180 else
182 CHECK_NUMBER_COERCE_MARKER (pos, 0);
183 posint = XINT (pos);
186 if (NILP (window))
187 window = selected_window;
188 else
189 CHECK_WINDOW (window, 1);
190 w = XWINDOW (window);
191 top = marker_position (w->start);
193 if (posint < top)
194 return Qnil;
196 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
198 buf = XBUFFER (w->buffer);
199 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
201 /* If frame is up to date,
202 use the info recorded about how much text fit on it. */
203 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
204 || (XFASTINT (w->window_end_vpos) < height))
205 return Qt;
206 return Qnil;
208 else
210 if (posint > BUF_Z (buf))
211 return Qnil;
213 /* If that info is not correct, calculate afresh */
214 posval = *compute_motion (top, 0, 0, posint, height, 0,
215 XFASTINT (w->width) - 1
216 - (XFASTINT (w->width) + XFASTINT (w->left)
217 != FRAME_WIDTH (XFRAME (w->frame))),
218 XINT (w->hscroll), 0);
220 return posval.vpos < height ? Qt : Qnil;
224 static struct window *
225 decode_window (window)
226 register Lisp_Object window;
228 if (NILP (window))
229 return XWINDOW (selected_window);
231 CHECK_WINDOW (window, 0);
232 return XWINDOW (window);
235 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
236 "Return the buffer that WINDOW is displaying.")
237 (window)
238 Lisp_Object window;
240 return decode_window (window)->buffer;
243 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
244 "Return the number of lines in WINDOW (including its mode line).")
245 (window)
246 Lisp_Object window;
248 return decode_window (window)->height;
251 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
252 "Return the number of columns in WINDOW.")
253 (window)
254 Lisp_Object window;
256 register struct window *w = decode_window (window);
257 register int width = w->width;
259 /* If this window does not end at the right margin,
260 must deduct one column for the border */
261 if ((width + w->left) == FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
262 return width;
263 return width - 1;
266 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
267 "Return the number of columns by which WINDOW is scrolled from left margin.")
268 (window)
269 Lisp_Object window;
271 return decode_window (window)->hscroll;
274 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
275 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
276 NCOL should be zero or positive.")
277 (window, ncol)
278 register Lisp_Object window, ncol;
280 register struct window *w;
282 CHECK_NUMBER (ncol, 1);
283 if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
284 if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
285 args_out_of_range (ncol, Qnil);
286 w = decode_window (window);
287 if (w->hscroll != ncol)
288 clip_changed = 1; /* Prevent redisplay shortcuts */
289 w->hscroll = ncol;
290 return ncol;
293 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
294 "Return a list of the edge coordinates of WINDOW.\n\
295 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
296 RIGHT is one more than the rightmost column used by WINDOW,\n\
297 and BOTTOM is one more than the bottommost row used by WINDOW\n\
298 and its mode-line.")
299 (window)
300 Lisp_Object window;
302 register struct window *w = decode_window (window);
304 return Fcons (w->left, Fcons (w->top,
305 Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
306 Fcons (make_number (XFASTINT (w->top)
307 + XFASTINT (w->height)),
308 Qnil))));
311 /* Test if the character at column *x, row *y is within window *w.
312 If it is not, return 0;
313 if it is in the window's text area,
314 set *x and *y to its location relative to the upper left corner
315 of the window, and
316 return 1;
317 if it is on the window's modeline, return 2;
318 if it is on the border between the window and its right sibling,
319 return 3. */
320 static int
321 coordinates_in_window (w, x, y)
322 register struct window *w;
323 register int *x, *y;
325 register int left = XINT (w->left);
326 register int width = XINT (w->width);
327 register int window_height = XINT (w->height);
328 register int top = XFASTINT (w->top);
330 if ( *x < left || *x >= left + width
331 || *y < top || *y >= top + window_height)
332 return 0;
334 /* Is the character is the mode line? */
335 if (*y == top + window_height - 1
336 && window_height > 1) /* 1 line => minibuffer */
337 return 2;
339 /* Is the character in the right border? */
340 if (*x == left + width - 1
341 && left + width != FRAME_WIDTH (XFRAME (w->frame)))
342 return 3;
344 *x -= left;
345 *y -= top;
346 return 1;
349 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
350 Scoordinates_in_window_p, 2, 2, 0,
351 "Return non-nil if COORDINATES are in WINDOW.\n\
352 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
353 measured in characters from the upper-left corner of the frame.\n\
354 (0 . 0) denotes the character in the upper left corner of the\n\
355 frame.\n\
356 If COORDINATES are in the text portion of WINDOW,\n\
357 the coordinates relative to the window are returned.\n\
358 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
359 If they are on the border between WINDOW and its right sibling,\n\
360 `vertical-line' is returned.")
361 (coordinates, window)
362 register Lisp_Object coordinates, window;
364 int x, y;
366 CHECK_WINDOW (window, 0);
367 CHECK_CONS (coordinates, 1);
368 x = XINT (Fcar (coordinates));
369 y = XINT (Fcdr (coordinates));
371 switch (coordinates_in_window (XWINDOW (window), &x, &y))
373 case 0: /* NOT in window at all. */
374 return Qnil;
376 case 1: /* In text part of window. */
377 return Fcons (x, y);
379 case 2: /* In mode line of window. */
380 return Qmode_line;
382 case 3: /* On right border of window. */
383 return Qvertical_line;
385 default:
386 abort ();
390 /* Find the window containing column x, row y, and return it as a
391 Lisp_Object. If x, y is on the window's modeline, set *part
392 to 1; if it is on the separating line between the window and its
393 right sibling, set it to 2; otherwise set it to 0. If there is no
394 window under x, y return nil and leave *part unmodified. */
395 Lisp_Object
396 window_from_coordinates (frame, x, y, part)
397 FRAME_PTR frame;
398 int x, y;
399 int *part;
401 register Lisp_Object tem, first;
403 tem = first = FRAME_SELECTED_WINDOW (frame);
407 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
409 if (found)
411 *part = found - 1;
412 return tem;
415 tem = Fnext_window (tem, Qt, Qlambda);
417 while (! EQ (tem, first));
419 return Qnil;
422 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
423 "Return window containing row ROW, column COLUMN on FRAME.\n\
424 If omitted, FRAME defaults to the currently selected frame.\n\
425 The top left corner of the frame is considered to be row 0,\n\
426 column 0.")
427 (row, column, frame)
428 Lisp_Object row, column, frame;
430 int part;
432 if (NILP (frame))
433 XSET (frame, Lisp_Frame, selected_frame);
434 else
435 CHECK_LIVE_FRAME (frame, 2);
436 CHECK_NUMBER (row, 0);
437 CHECK_NUMBER (column, 1);
439 return window_from_coordinates (XFRAME (frame),
440 XINT (row), XINT (column),
441 &part);
444 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
445 "Return current value of point in WINDOW.\n\
446 For a nonselected window, this is the value point would have\n\
447 if that window were selected.\n\
449 Note that, when WINDOW is the selected window and its buffer\n\
450 is also currently selected, the value returned is the same as (point).\n\
451 It would be more strictly correct to return the `top-level' value\n\
452 of point, outside of any save-excursion forms.\n\
453 But that is hard to define.")
454 (window)
455 Lisp_Object window;
457 register struct window *w = decode_window (window);
459 if (w == XWINDOW (selected_window)
460 && current_buffer == XBUFFER (w->buffer))
461 return Fpoint ();
462 return Fmarker_position (w->pointm);
465 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
466 "Return position at which display currently starts in WINDOW.")
467 (window)
468 Lisp_Object window;
470 return Fmarker_position (decode_window (window)->start);
473 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
474 "Return position at which display currently ends in WINDOW.")
475 (window)
476 Lisp_Object window;
478 Lisp_Object value;
479 struct window *w = decode_window (window);
481 XSET (value, Lisp_Int,
482 BUF_Z (current_buffer) - XFASTINT (w->window_end_pos));
484 return value;
487 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
488 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
489 (window, pos)
490 Lisp_Object window, pos;
492 register struct window *w = decode_window (window);
494 CHECK_NUMBER_COERCE_MARKER (pos, 1);
495 if (w == XWINDOW (selected_window))
496 Fgoto_char (pos);
497 else
498 set_marker_restricted (w->pointm, pos, w->buffer);
500 return pos;
503 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
504 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
505 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
506 from overriding motion of point in order to display at this exact start.")
507 (window, pos, noforce)
508 Lisp_Object window, pos, noforce;
510 register struct window *w = decode_window (window);
512 CHECK_NUMBER_COERCE_MARKER (pos, 1);
513 set_marker_restricted (w->start, pos, w->buffer);
514 /* this is not right, but much easier than doing what is right. */
515 w->start_at_line_beg = Qnil;
516 if (NILP (noforce))
517 w->force_start = Qt;
518 w->update_mode_line = Qt;
519 XFASTINT (w->last_modified) = 0;
520 if (!EQ (window, selected_window))
521 windows_or_buffers_changed++;
522 return pos;
525 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
526 1, 1, 0,
527 "Return WINDOW's dedicated object, usually t or nil.\n\
528 See also `set-window-buffer-dedicated'.")
529 (window)
530 Lisp_Object window;
532 return decode_window (window)->dedicated;
535 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
536 Sset_window_dedicated_p, 2, 2, 0,
537 "Control whether WINDOW is dedicated to the buffer it displays.\n\
538 If it is dedicated, Emacs will not automatically change\n\
539 which buffer appears in it.\n\
540 The second argument is the new value for the dedication flag;\n\
541 non-nil means yes.")
542 (window, arg)
543 Lisp_Object window, arg;
545 register struct window *w = decode_window (window);
547 if (NILP (arg))
548 w->dedicated = Qnil;
549 else
550 w->dedicated = Qt;
552 return w->dedicated;
555 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
556 0, 1, 0,
557 "Return the display-table that WINDOW is using.")
558 (window)
559 Lisp_Object window;
561 return decode_window (window)->display_table;
564 /* Get the display table for use currently on window W.
565 This is either W's display table or W's buffer's display table.
566 Ignore the specified tables if they are not valid;
567 if no valid table is specified, return 0. */
569 struct Lisp_Vector *
570 window_display_table (w)
571 struct window *w;
573 Lisp_Object tem;
574 tem = w->display_table;
575 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
576 return XVECTOR (tem);
577 tem = XBUFFER (w->buffer)->display_table;
578 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
579 return XVECTOR (tem);
580 tem = Vstandard_display_table;
581 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
582 return XVECTOR (tem);
583 return 0;
586 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
587 "Set WINDOW's display-table to TABLE.")
588 (window, table)
589 register Lisp_Object window, table;
591 register struct window *w;
592 register Lisp_Object z; /* Return value. */
594 w = decode_window (window);
595 w->display_table = table;
596 return table;
599 /* Record info on buffer window w is displaying
600 when it is about to cease to display that buffer. */
601 static
602 unshow_buffer (w)
603 register struct window *w;
605 Lisp_Object buf = w->buffer;
607 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
608 abort ();
610 if (w == XWINDOW (selected_window)
611 || ! EQ (buf, XWINDOW (selected_window)->buffer))
612 /* Do this except when the selected window's buffer
613 is being removed from some other window. */
614 XBUFFER (buf)->last_window_start = marker_position (w->start);
616 /* Point in the selected window's buffer
617 is actually stored in that buffer, and the window's pointm isn't used.
618 So don't clobber point in that buffer. */
619 if (! EQ (buf, XWINDOW (selected_window)->buffer))
620 BUF_PT (XBUFFER (buf))
621 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
622 marker_position (w->pointm),
623 BUF_ZV (XBUFFER (buf)));
626 /* Put replacement into the window structure in place of old. */
627 static
628 replace_window (old, replacement)
629 Lisp_Object old, replacement;
631 register Lisp_Object tem;
632 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
634 /* If OLD is its frame's root_window, then replacement is the new
635 root_window for that frame. */
637 if (old == FRAME_ROOT_WINDOW (XFRAME (o->frame)))
638 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
640 p->left = o->left;
641 p->top = o->top;
642 p->width = o->width;
643 p->height = o->height;
645 p->next = tem = o->next;
646 if (!NILP (tem))
647 XWINDOW (tem)->prev = replacement;
649 p->prev = tem = o->prev;
650 if (!NILP (tem))
651 XWINDOW (tem)->next = replacement;
653 p->parent = tem = o->parent;
654 if (!NILP (tem))
656 if (EQ (XWINDOW (tem)->vchild, old))
657 XWINDOW (tem)->vchild = replacement;
658 if (EQ (XWINDOW (tem)->hchild, old))
659 XWINDOW (tem)->hchild = replacement;
662 /*** Here, if replacement is a vertical combination
663 and so is its new parent, we should make replacement's
664 children be children of that parent instead. ***/
667 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
668 "Remove WINDOW from the display. Default is selected window.")
669 (window)
670 register Lisp_Object window;
672 register Lisp_Object tem, parent, sib;
673 register struct window *p;
674 register struct window *par;
676 if (NILP (window))
677 window = selected_window;
678 else
679 CHECK_WINDOW (window, 0);
681 p = XWINDOW (window);
682 parent = p->parent;
683 if (NILP (parent))
684 error ("Attempt to delete minibuffer or sole ordinary window");
685 par = XWINDOW (parent);
687 windows_or_buffers_changed++;
689 if (EQ (window, selected_window))
690 Fselect_window (Fnext_window (window, Qnil, Qnil));
692 tem = p->buffer;
693 /* tem is null for dummy parent windows
694 (which have inferiors but not any contents themselves) */
695 if (!NILP (tem))
697 unshow_buffer (p);
698 unchain_marker (p->pointm);
699 unchain_marker (p->start);
700 p->buffer = Qnil;
703 tem = p->next;
704 if (!NILP (tem))
705 XWINDOW (tem)->prev = p->prev;
707 tem = p->prev;
708 if (!NILP (tem))
709 XWINDOW (tem)->next = p->next;
711 if (EQ (window, par->hchild))
712 par->hchild = p->next;
713 if (EQ (window, par->vchild))
714 par->vchild = p->next;
716 /* Find one of our siblings to give our space to. */
717 sib = p->prev;
718 if (NILP (sib))
720 /* If p gives its space to its next sibling, that sibling needs
721 to have its top/left side pulled back to where p's is.
722 set_window_{height,width} will re-position the sibling's
723 children. */
724 sib = p->next;
725 XFASTINT (XWINDOW (sib)->top) = p->top;
726 XFASTINT (XWINDOW (sib)->left) = p->left;
729 /* Stretch that sibling. */
730 if (!NILP (par->vchild))
731 set_window_height (sib,
732 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
734 if (!NILP (par->hchild))
735 set_window_width (sib,
736 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
739 /* If parent now has only one child,
740 put the child into the parent's place. */
742 tem = par->hchild;
743 if (NILP (tem))
744 tem = par->vchild;
745 if (NILP (XWINDOW (tem)->next))
746 replace_window (parent, tem);
747 return Qnil;
751 extern Lisp_Object next_frame (), prev_frame ();
753 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
754 "Return next window after WINDOW in canonical ordering of windows.\n\
755 If omitted, WINDOW defaults to the selected window.\n\
757 Optional second arg MINIBUF t means count the minibuffer window even\n\
758 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
759 it is active. MINIBUF neither t nor nil means not to count the\n\
760 minibuffer even if it is active.\n\
762 Several frames may share a single minibuffer; if the minibuffer\n\
763 counts, all windows on all frames that share that minibuffer count\n\
764 too. This means that next-window may be used to iterate through the\n\
765 set of windows even when the minibuffer is on another frame. If the\n\
766 minibuffer does not count, only windows from WINDOW's frame count.\n\
768 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
769 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
770 above. If neither nil nor t, restrict to WINDOW's frame.")
771 (window, minibuf, all_frames)
772 register Lisp_Object window, minibuf, all_frames;
774 register Lisp_Object tem;
775 Lisp_Object start_window;
777 if (NILP (window))
778 window = selected_window;
779 else
780 CHECK_WINDOW (window, 0);
782 start_window = window;
784 /* minibuf == nil may or may not include minibuffers.
785 Decide if it does. */
786 if (NILP (minibuf))
787 minibuf = (minibuf_level ? Qt : Qlambda);
789 /* all_frames == nil doesn't specify which frames to include.
790 Decide which frames it includes. */
791 if (NILP (all_frames))
792 all_frames = (EQ (minibuf, Qt)
793 ? (FRAME_MINIBUF_WINDOW
794 (XFRAME
795 (WINDOW_FRAME
796 (XWINDOW (window)))))
797 : Qnil);
798 else if (! EQ (all_frames, Qt))
799 all_frames = Qnil;
801 /* Do this loop at least once, to get the next window, and perhaps
802 again, if we hit the minibuffer and that is not acceptable. */
805 /* Find a window that actually has a next one. This loop
806 climbs up the tree. */
807 while (tem = XWINDOW (window)->next, NILP (tem))
808 if (tem = XWINDOW (window)->parent, !NILP (tem))
809 window = tem;
810 else
812 /* We've reached the end of this frame.
813 Which other frames are acceptable? */
814 tem = WINDOW_FRAME (XWINDOW (window));
815 #ifdef MULTI_FRAME
816 if (! NILP (all_frames))
817 tem = next_frame (tem, all_frames);
818 #endif
819 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
821 break;
824 window = tem;
826 /* If we're in a combination window, find its first child and
827 recurse on that. Otherwise, we've found the window we want. */
828 while (1)
830 if (!NILP (XWINDOW (window)->hchild))
831 window = XWINDOW (window)->hchild;
832 else if (!NILP (XWINDOW (window)->vchild))
833 window = XWINDOW (window)->vchild;
834 else break;
837 /* Which windows are acceptible?
838 Exit the loop and accept this window if
839 this isn't a minibuffer window, or
840 we're accepting minibuffer windows, or
841 we've come all the way around and we're back at the original window. */
842 while (MINI_WINDOW_P (XWINDOW (window))
843 && ! EQ (minibuf, Qt)
844 && window != start_window);
846 return window;
849 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
850 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
851 If omitted, WINDOW defaults to the selected window.\n\
853 Optional second arg MINIBUF t means count the minibuffer window even\n\
854 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
855 it is active. MINIBUF neither t nor nil means not to count the\n\
856 minibuffer even if it is active.\n\
858 Several frames may share a single minibuffer; if the minibuffer\n\
859 counts, all windows on all frames that share that minibuffer count\n\
860 too. This means that previous-window may be used to iterate through\n\
861 the set of windows even when the minibuffer is on another frame. If\n\
862 the minibuffer does not count, only windows from WINDOW's frame\n\
863 count.\n\
865 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
866 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
867 above. If neither nil nor t, restrict to WINDOW's frame.")
868 (window, minibuf, all_frames)
869 register Lisp_Object window, minibuf, all_frames;
871 register Lisp_Object tem;
872 Lisp_Object start_window;
874 if (NILP (window))
875 window = selected_window;
876 else
877 CHECK_WINDOW (window, 0);
879 start_window = window;
881 /* minibuf == nil may or may not include minibuffers.
882 Decide if it does. */
883 if (NILP (minibuf))
884 minibuf = (minibuf_level ? Qt : Qlambda);
886 /* all_frames == nil doesn't specify which frames to include.
887 Decide which frames it includes. */
888 if (NILP (all_frames))
889 all_frames = (EQ (minibuf, Qt)
890 ? (FRAME_MINIBUF_WINDOW
891 (XFRAME
892 (WINDOW_FRAME
893 (XWINDOW (window)))))
894 : Qnil);
895 else if (! EQ (all_frames, Qt))
896 all_frames = Qnil;
898 /* Do this loop at least once, to get the previous window, and perhaps
899 again, if we hit the minibuffer and that is not acceptable. */
902 /* Find a window that actually has a previous one. This loop
903 climbs up the tree. */
904 while (tem = XWINDOW (window)->prev, NILP (tem))
905 if (tem = XWINDOW (window)->parent, !NILP (tem))
906 window = tem;
907 else
909 /* We have found the top window on the frame.
910 Which frames are acceptable? */
911 tem = WINDOW_FRAME (XWINDOW (window));
912 #ifdef MULTI_FRAME
913 if (! NILP (all_frames))
914 tem = next_frame (tem, all_frames);
915 #endif
916 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
918 break;
921 window = tem;
922 /* If we're in a combination window, find its last child and
923 recurse on that. Otherwise, we've found the window we want. */
924 while (1)
926 if (!NILP (XWINDOW (window)->hchild))
927 window = XWINDOW (window)->hchild;
928 else if (!NILP (XWINDOW (window)->vchild))
929 window = XWINDOW (window)->vchild;
930 else break;
931 while (tem = XWINDOW (window)->next, !NILP (tem))
932 window = tem;
935 /* Which windows are acceptable?
936 Exit the loop and accept this window if
937 this isn't a minibuffer window, or
938 we're accepting minibuffer windows, or
939 we've come all the way around and we're back at the original window. */
940 while (MINI_WINDOW_P (XWINDOW (window))
941 && !EQ (minibuf, Qt)
942 && window != start_window);
944 return window;
947 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
948 "Select the ARG'th different window on this frame.\n\
949 All windows on current frame are arranged in a cyclic order.\n\
950 This command selects the window ARG steps away in that order.\n\
951 A negative ARG moves in the opposite order. If the optional second\n\
952 argument ALL_FRAMES is non-nil, cycle through all frames.")
953 (n, all_frames)
954 register Lisp_Object n, all_frames;
956 register int i;
957 register Lisp_Object w;
959 CHECK_NUMBER (n, 0);
960 w = selected_window;
961 i = XINT (n);
963 while (i > 0)
965 w = Fnext_window (w, Qnil, all_frames);
966 i--;
968 while (i < 0)
970 w = Fprevious_window (w, Qnil, all_frames);
971 i++;
973 Fselect_window (w);
974 return Qnil;
977 /* Look at all windows, performing an operation specified by TYPE
978 with argument OBJ.
979 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
980 frame. If FRAMES is a frame, just look at windows on that frame.
981 If MINI is non-zero, perform the operation on minibuffer windows too.
984 enum window_loop
986 WINDOW_LOOP_UNUSED,
987 GET_BUFFER_WINDOW, /* Arg is buffer */
988 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
989 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
990 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
991 GET_LARGEST_WINDOW,
992 UNSHOW_BUFFER, /* Arg is buffer */
995 static Lisp_Object
996 window_loop (type, obj, mini, frames)
997 enum window_loop type;
998 register Lisp_Object obj, frames;
999 int mini;
1001 register Lisp_Object w;
1002 register Lisp_Object best_window;
1003 register Lisp_Object next_window;
1004 register Lisp_Object first_window;
1005 FRAME_PTR frame;
1007 /* If we're only looping through windows on a particular frame,
1008 frame points to that frame. If we're looping through windows
1009 on all frames, frame is 0. */
1010 if (FRAMEP (frames))
1011 frame = XFRAME (frames);
1012 else if (NILP (frames))
1013 frame = selected_frame;
1014 else
1015 frame = 0;
1017 /* Pick a window to start with. */
1018 if (XTYPE (obj) == Lisp_Window)
1019 first_window = obj;
1020 else if (frame)
1021 first_window = FRAME_SELECTED_WINDOW (frame);
1022 else
1023 first_window = FRAME_SELECTED_WINDOW (selected_frame);
1025 w = first_window;
1026 best_window = Qnil;
1029 /* Pick the next window now, since some operations will delete
1030 the current window. */
1031 #ifdef MULTI_FRAME
1032 if (frame)
1033 next_window = Fnext_window (w, (mini ? Qt : Qnil), Qlambda);
1034 else
1035 #endif /* MULTI_FRAME */
1036 /* We know frame is 0, so we're looping through all frames.
1037 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1038 next_window = Fnext_window (w, mini ? Qt : Qnil, Qt);
1040 if (!MINI_WINDOW_P (XWINDOW (w))
1041 || (mini && minibuf_level > 0))
1042 switch (type)
1044 case GET_BUFFER_WINDOW:
1045 #if 0
1046 /* Ignore invisible and iconified frames. */
1047 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1048 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1049 break;
1050 #endif
1051 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1052 return w;
1053 break;
1055 case GET_LRU_WINDOW:
1056 /* t as arg means consider only full-width windows */
1057 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
1058 != FRAME_WIDTH (frame))
1059 break;
1060 #if 0
1061 /* Ignore invisible and iconified frames. */
1062 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1063 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1064 break;
1065 #endif
1066 /* Ignore dedicated windows and minibuffers. */
1067 if (MINI_WINDOW_P (XWINDOW (w))
1068 || !NILP (XWINDOW (w)->dedicated))
1069 break;
1070 if (NILP (best_window)
1071 || (XFASTINT (XWINDOW (best_window)->use_time)
1072 > XFASTINT (XWINDOW (w)->use_time)))
1073 best_window = w;
1074 break;
1076 case DELETE_OTHER_WINDOWS:
1077 if (XWINDOW (w) != XWINDOW (obj))
1078 Fdelete_window (w);
1079 break;
1081 case DELETE_BUFFER_WINDOWS:
1082 if (EQ (XWINDOW (w)->buffer, obj))
1084 /* If we're deleting the buffer displayed in the only window
1085 on the frame, find a new buffer to display there. */
1086 if (NILP (XWINDOW (w)->parent))
1088 Lisp_Object new_buffer = Fother_buffer (obj);
1089 if (NILP (new_buffer))
1090 new_buffer
1091 = Fget_buffer_create (build_string ("*scratch*"));
1092 Fset_window_buffer (w, new_buffer);
1093 Fset_buffer (XWINDOW (w)->buffer);
1095 else
1096 Fdelete_window (w);
1098 break;
1100 case GET_LARGEST_WINDOW:
1101 #if 0
1102 /* Ignore invisible and iconified frames. */
1103 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1104 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1105 break;
1106 #endif
1107 /* Ignore dedicated windows and minibuffers. */
1108 if (MINI_WINDOW_P (XWINDOW (w))
1109 || !NILP (XWINDOW (w)->dedicated))
1110 break;
1112 struct window *best_window_ptr = XWINDOW (best_window);
1113 struct window *w_ptr = XWINDOW (w);
1114 if (NILP (best_window) ||
1115 (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width))
1116 > (XFASTINT (best_window_ptr->height)
1117 * XFASTINT (best_window_ptr->width)))
1118 best_window = w;
1120 break;
1122 case UNSHOW_BUFFER:
1123 if (EQ (XWINDOW (w)->buffer, obj))
1125 /* Find another buffer to show in this window. */
1126 Lisp_Object another_buffer = Fother_buffer (obj);
1127 if (NILP (another_buffer))
1128 another_buffer
1129 = Fget_buffer_create (build_string ("*scratch*"));
1130 Fset_window_buffer (w, another_buffer);
1131 if (EQ (w, selected_window))
1132 Fset_buffer (XWINDOW (w)->buffer);
1134 break;
1136 w = next_window;
1138 while (! EQ (w, first_window));
1140 return best_window;
1143 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1144 "Return the window least recently selected or used for display.\n\
1145 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1146 frame, search only that frame.\n")
1147 (frames)
1148 Lisp_Object frames;
1150 register Lisp_Object w;
1151 /* First try for a window that is full-width */
1152 w = window_loop (GET_LRU_WINDOW, Qt, 0, frames);
1153 if (!NILP (w) && !EQ (w, selected_window))
1154 return w;
1155 /* If none of them, try the rest */
1156 return window_loop (GET_LRU_WINDOW, Qnil, 0, frames);
1159 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1160 "Return the largest window in area.\n\
1161 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1162 frame, search only that frame.\n")
1163 (frame)
1164 Lisp_Object frame;
1166 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1167 frame);
1170 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1171 "Return a window currently displaying BUFFER, or nil if none.\n\
1172 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1173 frame, search only that frame.\n")
1174 (buffer, frame)
1175 Lisp_Object buffer, frame;
1177 buffer = Fget_buffer (buffer);
1178 if (XTYPE (buffer) == Lisp_Buffer)
1179 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1180 else
1181 return Qnil;
1184 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1185 0, 1, "",
1186 "Make WINDOW (or the selected window) fill its frame.\n\
1187 Only the frame WINDOW is on is affected.")
1188 (window)
1189 Lisp_Object window;
1191 struct window *w;
1192 int opoint = point;
1193 struct buffer *obuf = current_buffer;
1194 int top;
1196 if (NILP (window))
1197 window = selected_window;
1198 else
1199 CHECK_WINDOW (window, 0);
1201 w = XWINDOW (window);
1202 top = XFASTINT (w->top);
1204 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME(w));
1206 Fset_buffer (w->buffer);
1207 SET_PT (marker_position (w->start));
1208 Frecenter (make_number (top));
1210 set_buffer_internal (obuf);
1211 SET_PT (opoint);
1212 return Qnil;
1215 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1216 1, 1, "bDelete windows on (buffer): ",
1217 "Delete all windows showing BUFFER.")
1218 (buffer)
1219 Lisp_Object buffer;
1221 if (!NILP (buffer))
1223 buffer = Fget_buffer (buffer);
1224 CHECK_BUFFER (buffer, 0);
1225 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, Qt);
1227 return Qnil;
1230 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1231 Sreplace_buffer_in_windows,
1232 1, 1, "bReplace buffer in windows: ",
1233 "Replace BUFFER with some other buffer in all windows showing it.")
1234 (buffer)
1235 Lisp_Object buffer;
1237 if (!NILP (buffer))
1239 buffer = Fget_buffer (buffer);
1240 CHECK_BUFFER (buffer, 0);
1241 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1243 return Qnil;
1246 /* Set the height of WINDOW and all its inferiors. */
1247 /* Normally the window is deleted if it gets too small.
1248 nodelete nonzero means do not do this.
1249 (The caller should check later and do so if appropriate) */
1251 set_window_height (window, height, nodelete)
1252 Lisp_Object window;
1253 int height;
1254 int nodelete;
1256 register struct window *w = XWINDOW (window);
1257 register struct window *c;
1258 int oheight = XFASTINT (w->height);
1259 int top, pos, lastbot, opos, lastobot;
1260 Lisp_Object child;
1262 if (!nodelete
1263 && ! NILP (w->parent)
1264 && height < window_min_height)
1266 Fdelete_window (window);
1267 return;
1270 XFASTINT (w->last_modified) = 0;
1271 windows_or_buffers_changed++;
1272 XFASTINT (w->height) = height;
1273 if (!NILP (w->hchild))
1275 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1277 XWINDOW (child)->top = w->top;
1278 set_window_height (child, height, nodelete);
1281 else if (!NILP (w->vchild))
1283 lastbot = top = XFASTINT (w->top);
1284 lastobot = 0;
1285 for (child = w->vchild; !NILP (child); child = c->next)
1287 c = XWINDOW (child);
1289 opos = lastobot + XFASTINT (c->height);
1291 XFASTINT (c->top) = lastbot;
1293 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1295 /* Avoid confusion: inhibit deletion of child if becomes too small */
1296 set_window_height (child, pos + top - lastbot, 1);
1298 /* Now advance child to next window,
1299 and set lastbot if child was not just deleted. */
1300 lastbot = pos + top;
1301 lastobot = opos;
1303 /* Now delete any children that became too small. */
1304 if (!nodelete)
1305 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1307 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1312 /* Recursively set width of WINDOW and its inferiors. */
1314 set_window_width (window, width, nodelete)
1315 Lisp_Object window;
1316 int width;
1317 int nodelete;
1319 register struct window *w = XWINDOW (window);
1320 register struct window *c;
1321 int owidth = XFASTINT (w->width);
1322 int left, pos, lastright, opos, lastoright;
1323 Lisp_Object child;
1325 if (!nodelete && width < window_min_width)
1327 Fdelete_window (window);
1328 return;
1331 XFASTINT (w->last_modified) = 0;
1332 windows_or_buffers_changed++;
1333 XFASTINT (w->width) = width;
1334 if (!NILP (w->vchild))
1336 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1338 XWINDOW (child)->left = w->left;
1339 set_window_width (child, width, nodelete);
1342 else if (!NILP (w->hchild))
1344 lastright = left = XFASTINT (w->left);
1345 lastoright = 0;
1346 for (child = w->hchild; !NILP (child); child = c->next)
1348 c = XWINDOW (child);
1350 opos = lastoright + XFASTINT (c->width);
1352 XFASTINT (c->left) = lastright;
1354 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1356 /* Inhibit deletion for becoming too small */
1357 set_window_width (child, pos + left - lastright, 1);
1359 /* Now advance child to next window,
1360 and set lastright if child was not just deleted. */
1361 lastright = pos + left, lastoright = opos;
1363 /* Delete children that became too small */
1364 if (!nodelete)
1365 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1367 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1372 int window_select_count;
1374 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1375 "Make WINDOW display BUFFER as its contents.\n\
1376 BUFFER can be a buffer or buffer name.")
1377 (window, buffer)
1378 register Lisp_Object window, buffer;
1380 register Lisp_Object tem;
1381 register struct window *w = decode_window (window);
1383 buffer = Fget_buffer (buffer);
1384 CHECK_BUFFER (buffer, 1);
1386 if (NILP (XBUFFER (buffer)->name))
1387 error ("Attempt to display deleted buffer");
1389 tem = w->buffer;
1390 if (NILP (tem))
1391 error ("Window is deleted");
1392 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1393 is first being set up. */
1395 if (!NILP (w->dedicated) && !EQ (tem, buffer))
1396 error ("Window is dedicated to %s\n", tem);
1398 unshow_buffer (w);
1401 w->buffer = buffer;
1402 Fset_marker (w->pointm,
1403 make_number (BUF_PT (XBUFFER (buffer))),
1404 buffer);
1405 set_marker_restricted (w->start,
1406 make_number (XBUFFER (buffer)->last_window_start),
1407 buffer);
1408 w->start_at_line_beg = Qnil;
1409 XFASTINT (w->last_modified) = 0;
1410 windows_or_buffers_changed++;
1411 if (EQ (window, selected_window))
1412 Fset_buffer (buffer);
1414 return Qnil;
1417 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1418 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1419 The main editor command loop selects the buffer of the selected window\n\
1420 before each command.")
1421 (window)
1422 register Lisp_Object window;
1424 register struct window *w;
1425 register struct window *ow = XWINDOW (selected_window);
1427 CHECK_WINDOW (window, 0);
1429 w = XWINDOW (window);
1431 if (NILP (w->buffer))
1432 error ("Trying to select deleted window or non-leaf window");
1434 XFASTINT (w->use_time) = ++window_select_count;
1435 if (EQ (window, selected_window))
1436 return window;
1438 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1439 ow->buffer);
1441 selected_window = window;
1442 #ifdef MULTI_FRAME
1443 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
1445 XFRAME (WINDOW_FRAME (w))->selected_window = window;
1446 Fselect_frame (WINDOW_FRAME (w), Qnil);
1448 else
1449 selected_frame->selected_window = window;
1450 #endif
1452 record_buffer (w->buffer);
1453 Fset_buffer (w->buffer);
1455 /* Go to the point recorded in the window.
1456 This is important when the buffer is in more
1457 than one window. It also matters when
1458 redisplay_window has altered point after scrolling,
1459 because it makes the change only in the window. */
1461 register int new_point = marker_position (w->pointm);
1462 if (new_point < BEGV)
1463 SET_PT (BEGV);
1464 if (new_point > ZV)
1465 SET_PT (ZV);
1466 else
1467 SET_PT (new_point);
1470 windows_or_buffers_changed++;
1471 return window;
1474 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
1475 "BDisplay buffer:\nP",
1476 "Make BUFFER appear in some window but don't select it.\n\
1477 BUFFER can be a buffer or a buffer name.\n\
1478 If BUFFER is shown already in some window, just use that one,\n\
1479 unless the window is the selected window and the optional second\n\
1480 argument NOT_THIS_WINDOW is non-nil.\n\
1481 Returns the window displaying BUFFER.")
1482 (buffer, not_this_window)
1483 register Lisp_Object buffer, not_this_window;
1485 register Lisp_Object window;
1487 buffer = Fget_buffer (buffer);
1488 CHECK_BUFFER (buffer, 0);
1490 if (!NILP (Vdisplay_buffer_function))
1491 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1493 if (NILP (not_this_window)
1494 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1495 return selected_window;
1497 window = Fget_buffer_window (buffer, Qnil);
1498 if (!NILP (window)
1499 && (NILP (not_this_window) || !EQ (window, selected_window)))
1500 return window;
1502 #ifdef MULTI_FRAME
1503 /* If there are no frames open that have more than a minibuffer,
1504 we need to create a new frame. */
1505 if (pop_up_frames || last_nonminibuf_frame == 0)
1507 window
1508 = Fframe_selected_window (call0 (Vpop_up_frame_function));
1509 Fset_window_buffer (window, buffer);
1510 #if 0
1511 Fselect_frame (XWINDOW (window)->frame, Qnil);
1512 #endif
1513 return window;
1515 #endif /* MULTI_FRAME */
1517 if (pop_up_windows
1518 #ifdef MULTI_FRAME
1519 || FRAME_MINIBUF_ONLY_P (selected_frame)
1520 #endif
1523 Lisp_Object frames = Qnil;
1525 #ifdef MULTI_FRAME
1526 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1527 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
1528 #endif
1529 /* Don't try to create a window if would get an error */
1530 if (split_height_threshold < window_min_height << 1)
1531 split_height_threshold = window_min_height << 1;
1533 window = Fget_largest_window (frames);
1535 if (!NILP (window)
1536 && window_height (window) >= split_height_threshold
1538 (XFASTINT (XWINDOW (window)->width)
1539 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
1540 window = Fsplit_window (window, Qnil, Qnil);
1541 else
1543 window = Fget_lru_window (frames);
1544 if ((EQ (window, selected_window)
1545 || EQ (XWINDOW (window)->parent, Qnil))
1546 && window_height (window) >= window_min_height << 1)
1547 window = Fsplit_window (window, Qnil, Qnil);
1550 else
1551 window = Fget_lru_window (Qnil);
1553 Fset_window_buffer (window, buffer);
1554 return window;
1557 void
1558 temp_output_buffer_show (buf)
1559 register Lisp_Object buf;
1561 register struct buffer *old = current_buffer;
1562 register Lisp_Object window;
1563 register struct window *w;
1565 Fset_buffer (buf);
1566 XBUFFER (buf)->save_modified = MODIFF;
1567 BEGV = BEG;
1568 ZV = Z;
1569 SET_PT (BEG);
1570 clip_changed = 1;
1571 set_buffer_internal (old);
1573 if (!EQ (Vtemp_buffer_show_function, Qnil))
1574 call1 (Vtemp_buffer_show_function, buf);
1575 else
1577 window = Fdisplay_buffer (buf, Qnil);
1579 #ifdef MULTI_FRAME
1580 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1581 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1582 #endif /* MULTI_FRAME */
1583 Vminibuf_scroll_window = window;
1584 w = XWINDOW (window);
1585 XFASTINT (w->hscroll) = 0;
1586 set_marker_restricted (w->start, make_number (1), buf);
1587 set_marker_restricted (w->pointm, make_number (1), buf);
1591 static
1592 make_dummy_parent (window)
1593 Lisp_Object window;
1595 register Lisp_Object old, new;
1596 register struct window *o, *p;
1598 old = window;
1599 XSETTYPE (old, Lisp_Vector);
1600 new = Fcopy_sequence (old);
1601 XSETTYPE (new, Lisp_Window);
1603 o = XWINDOW (old);
1604 p = XWINDOW (new);
1605 XFASTINT (p->sequence_number) = ++sequence_number;
1607 /* Put new into window structure in place of window */
1608 replace_window (window, new);
1610 o->next = Qnil;
1611 o->prev = Qnil;
1612 o->vchild = Qnil;
1613 o->hchild = Qnil;
1614 o->parent = new;
1616 p->start = Qnil;
1617 p->pointm = Qnil;
1618 p->buffer = Qnil;
1621 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1622 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1623 WINDOW defaults to selected one and SIZE to half its size.\n\
1624 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1625 and put SIZE columns in the first of the pair.")
1626 (window, chsize, horflag)
1627 Lisp_Object window, chsize, horflag;
1629 register Lisp_Object new;
1630 register struct window *o, *p;
1631 register int size;
1633 if (NILP (window))
1634 window = selected_window;
1635 else
1636 CHECK_WINDOW (window, 0);
1638 o = XWINDOW (window);
1640 if (NILP (chsize))
1642 if (!NILP (horflag))
1643 /* Round odd size up, since this is for the left-hand window,
1644 and it will lose a column for the separators. */
1645 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1646 else
1647 size = XFASTINT (o->height) >> 1;
1649 else
1651 CHECK_NUMBER (chsize, 1);
1652 size = XINT (chsize);
1655 if (MINI_WINDOW_P (o))
1656 error ("Attempt to split minibuffer window");
1657 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1658 error ("Attempt to split unsplittable frame");
1660 /* Smaller values might permit a crash. */
1661 if (window_min_width < 2)
1662 window_min_width = 2;
1663 if (window_min_height < 2)
1664 window_min_height = 2;
1666 if (NILP (horflag))
1668 if (size < window_min_height
1669 || size + window_min_height > XFASTINT (o->height))
1670 args_out_of_range_3 (window, chsize, horflag);
1671 if (NILP (o->parent)
1672 || NILP (XWINDOW (o->parent)->vchild))
1674 make_dummy_parent (window);
1675 new = o->parent;
1676 XWINDOW (new)->vchild = window;
1679 else
1681 if (size < window_min_width
1682 || size + window_min_width > XFASTINT (o->width))
1683 args_out_of_range_3 (window, chsize, horflag);
1684 if (NILP (o->parent)
1685 || NILP (XWINDOW (o->parent)->hchild))
1687 make_dummy_parent (window);
1688 new = o->parent;
1689 XWINDOW (new)->hchild = window;
1693 /* Now we know that window's parent is a vertical combination
1694 if we are dividing vertically, or a horizontal combination
1695 if we are making side-by-side windows */
1697 windows_or_buffers_changed++;
1698 new = make_window ();
1699 p = XWINDOW (new);
1701 p->frame = o->frame;
1702 p->next = o->next;
1703 if (!NILP (p->next))
1704 XWINDOW (p->next)->prev = new;
1705 p->prev = window;
1706 o->next = new;
1707 p->parent = o->parent;
1708 p->buffer = Qt;
1710 Fset_window_buffer (new, o->buffer);
1712 /* Apportion the available frame space among the two new windows */
1714 if (!NILP (horflag))
1716 p->height = o->height;
1717 p->top = o->top;
1718 XFASTINT (p->width) = XFASTINT (o->width) - size;
1719 XFASTINT (o->width) = size;
1720 XFASTINT (p->left) = XFASTINT (o->left) + size;
1722 else
1724 p->left = o->left;
1725 p->width = o->width;
1726 XFASTINT (p->height) = XFASTINT (o->height) - size;
1727 XFASTINT (o->height) = size;
1728 XFASTINT (p->top) = XFASTINT (o->top) + size;
1731 return new;
1734 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1735 "Make current window ARG lines bigger.\n\
1736 From program, optional second arg non-nil means grow sideways ARG columns.")
1737 (n, side)
1738 register Lisp_Object n, side;
1740 CHECK_NUMBER (n, 0);
1741 change_window_height (XINT (n), !NILP (side));
1742 return Qnil;
1745 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1746 "Make current window ARG lines smaller.\n\
1747 From program, optional second arg non-nil means shrink sideways ARG columns.")
1748 (n, side)
1749 register Lisp_Object n, side;
1751 CHECK_NUMBER (n, 0);
1752 change_window_height (-XINT (n), !NILP (side));
1753 return Qnil;
1757 window_height (window)
1758 Lisp_Object window;
1760 register struct window *p = XWINDOW (window);
1761 return XFASTINT (p->height);
1765 window_width (window)
1766 Lisp_Object window;
1768 register struct window *p = XWINDOW (window);
1769 return XFASTINT (p->width);
1772 #define MINSIZE(w) \
1773 (widthflag ? window_min_width : window_min_height)
1775 #define CURBEG(w) \
1776 *(widthflag ? (int *) &(w)->left : (int *) &(w)->top)
1778 #define CURSIZE(w) \
1779 *(widthflag ? (int *) &(w)->width : (int *) &(w)->height)
1781 /* Unlike set_window_height, this function
1782 also changes the heights of the siblings so as to
1783 keep everything consistent. */
1785 change_window_height (delta, widthflag)
1786 register int delta;
1787 int widthflag;
1789 register Lisp_Object parent;
1790 Lisp_Object window;
1791 register struct window *p;
1792 int *sizep;
1793 int (*sizefun) () = widthflag ? window_width : window_height;
1794 register int (*setsizefun) () = (widthflag
1795 ? set_window_width
1796 : set_window_height);
1798 /* Smaller values might permit a crash. */
1799 if (window_min_width < 2)
1800 window_min_width = 2;
1801 if (window_min_height < 2)
1802 window_min_height = 2;
1804 window = selected_window;
1805 while (1)
1807 p = XWINDOW (window);
1808 parent = p->parent;
1809 if (NILP (parent))
1811 if (widthflag)
1812 error ("No other window to side of this one");
1813 break;
1815 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
1816 : !NILP (XWINDOW (parent)->vchild))
1817 break;
1818 window = parent;
1821 sizep = &CURSIZE (p);
1823 if (*sizep + delta < MINSIZE (p)
1824 && !NILP (XWINDOW (window)->parent))
1826 Fdelete_window (window);
1827 return;
1831 register int maxdelta;
1833 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
1834 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
1835 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
1836 /* This is a frame with only one window, a minibuffer-only
1837 or a minibufferless frame. */
1838 : (delta = 0));
1840 if (delta > maxdelta)
1841 /* This case traps trying to make the minibuffer
1842 the full frame, or make the only window aside from the
1843 minibuffer the full frame. */
1844 delta = maxdelta;
1846 if (delta == 0)
1847 return;
1850 if (!NILP (p->next) &&
1851 (*sizefun) (p->next) - delta >= MINSIZE (p->next))
1853 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
1854 (*setsizefun) (window, *sizep + delta, 0);
1855 CURBEG (XWINDOW (p->next)) += delta;
1856 /* This does not change size of p->next,
1857 but it propagates the new top edge to its children */
1858 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
1860 else if (!NILP (p->prev) &&
1861 (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
1863 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
1864 CURBEG (p) -= delta;
1865 (*setsizefun) (window, *sizep + delta, 0);
1867 else
1869 register int delta1;
1870 register int opht = (*sizefun) (parent);
1872 /* If trying to grow this window to or beyond size of the parent,
1873 make delta1 so big that, on shrinking back down,
1874 all the siblings end up with less than one line and are deleted. */
1875 if (opht <= *sizep + delta)
1876 delta1 = opht * opht * 2;
1877 /* Otherwise, make delta1 just right so that if we add delta1
1878 lines to this window and to the parent, and then shrink
1879 the parent back to its original size, the new proportional
1880 size of this window will increase by delta. */
1881 else
1882 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
1884 /* Add delta1 lines or columns to this window, and to the parent,
1885 keeping things consistent while not affecting siblings. */
1886 CURSIZE (XWINDOW (parent)) = opht + delta1;
1887 (*setsizefun) (window, *sizep + delta1, 0);
1889 /* Squeeze out delta1 lines or columns from our parent,
1890 shriking this window and siblings proportionately.
1891 This brings parent back to correct size.
1892 Delta1 was calculated so this makes this window the desired size,
1893 taking it all out of the siblings. */
1894 (*setsizefun) (parent, opht, 0);
1897 XFASTINT (p->last_modified) = 0;
1899 #undef MINSIZE
1900 #undef CURBEG
1901 #undef CURSIZE
1904 /* Return number of lines of text (not counting mode line) in W. */
1907 window_internal_height (w)
1908 struct window *w;
1910 int ht = XFASTINT (w->height);
1912 if (MINI_WINDOW_P (w))
1913 return ht;
1915 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
1916 || !NILP (w->next) || !NILP (w->prev)
1917 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
1918 return ht - 1;
1920 return ht;
1923 /* Scroll contents of window WINDOW up N lines. */
1925 void
1926 window_scroll (window, n, noerror)
1927 Lisp_Object window;
1928 int n;
1929 int noerror;
1931 register struct window *w = XWINDOW (window);
1932 register int opoint = point;
1933 register int pos;
1934 register int ht = window_internal_height (w);
1935 register Lisp_Object tem;
1936 int lose;
1937 Lisp_Object bolp, nmoved;
1939 XFASTINT (tem) = point;
1940 tem = Fpos_visible_in_window_p (tem, window);
1942 if (NILP (tem))
1944 Fvertical_motion (make_number (- ht / 2));
1945 XFASTINT (tem) = point;
1946 Fset_marker (w->start, tem, w->buffer);
1947 w->force_start = Qt;
1950 SET_PT (marker_position (w->start));
1951 lose = n < 0 && point == BEGV;
1952 Fvertical_motion (make_number (n));
1953 pos = point;
1954 bolp = Fbolp ();
1955 SET_PT (opoint);
1957 if (lose)
1959 if (noerror)
1960 return;
1961 else
1962 Fsignal (Qbeginning_of_buffer, Qnil);
1965 if (pos < ZV)
1967 set_marker_restricted (w->start, make_number (pos), w->buffer);
1968 w->start_at_line_beg = bolp;
1969 w->update_mode_line = Qt;
1970 XFASTINT (w->last_modified) = 0;
1971 if (pos > opoint)
1972 SET_PT (pos);
1973 if (n < 0)
1975 SET_PT (pos);
1976 tem = Fvertical_motion (make_number (ht));
1977 if (point > opoint || XFASTINT (tem) < ht)
1978 SET_PT (opoint);
1979 else
1980 Fvertical_motion (make_number (-1));
1983 else
1985 if (noerror)
1986 return;
1987 else
1988 Fsignal (Qend_of_buffer, Qnil);
1992 /* This is the guts of Fscroll_up and Fscroll_down. */
1994 static void
1995 scroll_command (n, direction)
1996 register Lisp_Object n;
1997 int direction;
1999 register int defalt;
2000 int count = specpdl_ptr - specpdl;
2002 /* If selected window's buffer isn't current, make it current for the moment.
2003 But don't screw up if window_scroll gets an error. */
2004 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2006 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2007 Fset_buffer (XWINDOW (selected_window)->buffer);
2010 defalt = (window_internal_height (XWINDOW (selected_window))
2011 - next_screen_context_lines);
2012 defalt = direction * (defalt < 1 ? 1 : defalt);
2014 if (NILP (n))
2015 window_scroll (selected_window, defalt, 0);
2016 else if (EQ (n, Qminus))
2017 window_scroll (selected_window, - defalt, 0);
2018 else
2020 n = Fprefix_numeric_value (n);
2021 window_scroll (selected_window, XINT (n) * direction, 0);
2024 unbind_to (count, Qnil);
2027 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2028 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2029 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2030 When calling from a program, supply a number as argument or nil.")
2032 Lisp_Object n;
2034 scroll_command (n, 1);
2035 return Qnil;
2038 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2039 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2040 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2041 When calling from a program, supply a number as argument or nil.")
2043 Lisp_Object n;
2045 scroll_command (n, -1);
2046 return Qnil;
2049 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2050 "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
2051 The next window is the one below the current one; or the one at the top\n\
2052 if the current one is at the bottom.\n\
2053 When calling from a program, supply a number as argument or nil.\n\
2055 If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2056 specifies the window to scroll.\n\
2057 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2058 showing that buffer, popping the buffer up if necessary.")
2060 register Lisp_Object n;
2062 register Lisp_Object window;
2063 register int ht;
2064 register struct window *w;
2065 register int count = specpdl_ptr - specpdl;
2067 if (MINI_WINDOW_P (XWINDOW (selected_window))
2068 && !NILP (Vminibuf_scroll_window))
2069 window = Vminibuf_scroll_window;
2070 /* If buffer is specified, scroll that buffer. */
2071 else if (!NILP (Vother_window_scroll_buffer))
2073 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
2074 if (NILP (window))
2075 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2077 else
2078 /* Nothing specified; pick a neighboring window. */
2079 window = Fnext_window (selected_window, Qnil, Qt);
2080 CHECK_WINDOW (window, 0);
2082 if (EQ (window, selected_window))
2083 error ("There is no other window");
2085 w = XWINDOW (window);
2086 ht = window_internal_height (w);
2088 /* Don't screw up if window_scroll gets an error. */
2089 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2091 Fset_buffer (w->buffer);
2092 SET_PT (marker_position (w->pointm));
2094 if (NILP (n))
2095 window_scroll (window, ht - next_screen_context_lines, 1);
2096 else if (EQ (n, Qminus))
2097 window_scroll (window, next_screen_context_lines - ht, 1);
2098 else
2100 if (XTYPE (n) == Lisp_Cons)
2101 n = Fcar (n);
2102 CHECK_NUMBER (n, 0);
2103 window_scroll (window, XINT (n), 1);
2106 Fset_marker (w->pointm, make_number (point), Qnil);
2107 unbind_to (count);
2109 return Qnil;
2112 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
2113 "Scroll selected window display ARG columns left.\n\
2114 Default for ARG is window width minus 2.")
2115 (arg)
2116 register Lisp_Object arg;
2119 if (NILP (arg))
2120 XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
2121 else
2122 arg = Fprefix_numeric_value (arg);
2124 return
2125 Fset_window_hscroll (selected_window,
2126 make_number (XINT (XWINDOW (selected_window)->hscroll)
2127 + XINT (arg)));
2130 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
2131 "Scroll selected window display ARG columns right.\n\
2132 Default for ARG is window width minus 2.")
2133 (arg)
2134 register Lisp_Object arg;
2136 if (NILP (arg))
2137 XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
2138 else
2139 arg = Fprefix_numeric_value (arg);
2141 return
2142 Fset_window_hscroll (selected_window,
2143 make_number (XINT (XWINDOW (selected_window)->hscroll)
2144 - XINT (arg)));
2147 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
2148 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2149 The desired position of point is always relative to the current window.\n\
2150 Just C-u as prefix means put point in the center of the window.\n\
2151 No arg (i.e., it is nil) erases the entire frame and then\n\
2152 redraws with point in the center of the current window.")
2154 register Lisp_Object n;
2156 register struct window *w = XWINDOW (selected_window);
2157 register int ht = window_internal_height (w);
2158 register int opoint = point;
2160 if (NILP (n))
2162 extern int frame_garbaged;
2164 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
2165 XFASTINT (n) = ht / 2;
2167 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2169 XFASTINT (n) = ht / 2;
2171 else
2173 n = Fprefix_numeric_value (n);
2174 CHECK_NUMBER (n, 0);
2177 if (XINT (n) < 0)
2178 XSETINT (n, XINT (n) + ht);
2180 XSETINT (n, - XINT (n));
2182 Fvertical_motion (n);
2183 Fset_marker (w->start, make_number (point), w->buffer);
2184 w->start_at_line_beg = Fbolp ();
2186 SET_PT (opoint);
2187 w->force_start = Qt;
2189 return Qnil;
2192 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2193 1, 1, "P",
2194 "Position point relative to window.\n\
2195 With no argument, position text at center of window.\n\
2196 An argument specifies frame line; zero means top of window,\n\
2197 negative means relative to bottom of window.")
2198 (arg)
2199 register Lisp_Object arg;
2201 register struct window *w = XWINDOW (selected_window);
2202 register int height = window_internal_height (w);
2203 register int start;
2205 if (NILP (arg))
2206 XFASTINT (arg) = height / 2;
2207 else
2209 arg = Fprefix_numeric_value (arg);
2210 if (XINT (arg) < 0)
2211 XSETINT (arg, XINT (arg) + height);
2214 start = marker_position (w->start);
2215 if (start < BEGV || start > ZV)
2217 Fvertical_motion (make_number (- height / 2));
2218 Fset_marker (w->start, make_number (point), w->buffer);
2219 w->start_at_line_beg = Fbolp ();
2220 w->force_start = Qt;
2222 else
2223 SET_PT (start);
2225 return Fvertical_motion (arg);
2228 struct save_window_data
2230 int size_from_Lisp_Vector_struct;
2231 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2232 Lisp_Object frame_width, frame_height;
2233 Lisp_Object current_window;
2234 Lisp_Object current_buffer;
2235 Lisp_Object minibuf_scroll_window;
2236 Lisp_Object root_window;
2237 /* A vector, interpreted as a struct saved_window */
2238 Lisp_Object saved_windows;
2240 #define SAVE_WINDOW_DATA_SIZE 7 /* Arg to Fmake_vector */
2242 /* This is saved as a Lisp_Vector */
2243 struct saved_window
2245 /* these first two must agree with struct Lisp_Vector in lisp.h */
2246 int size_from_Lisp_Vector_struct;
2247 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2249 Lisp_Object window;
2250 Lisp_Object buffer, start, pointm, mark;
2251 Lisp_Object left, top, width, height, hscroll;
2252 Lisp_Object parent, prev;
2253 Lisp_Object start_at_line_beg;
2254 Lisp_Object display_table;
2256 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2258 #define SAVED_WINDOW_N(swv,n) \
2259 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2261 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2262 "T if OBJECT is a window-configration object.")
2263 (obj)
2264 Lisp_Object obj;
2266 if (XTYPE (obj) == Lisp_Window_Configuration)
2267 return Qt;
2268 return Qnil;
2272 DEFUN ("set-window-configuration",
2273 Fset_window_configuration, Sset_window_configuration,
2274 1, 1, 0,
2275 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2276 CONFIGURATION must be a value previously returned\n\
2277 by `current-window-configuration' (which see).")
2278 (arg)
2279 Lisp_Object arg;
2281 register struct window *w;
2282 register struct save_window_data *data;
2283 struct Lisp_Vector *saved_windows;
2284 register struct saved_window *p;
2285 register Lisp_Object tem;
2286 Lisp_Object new_current_buffer;
2287 int k;
2288 FRAME_PTR f;
2290 while (XTYPE (arg) != Lisp_Window_Configuration)
2292 arg = wrong_type_argument (intern ("window-configuration-p"), arg);
2295 data = (struct save_window_data *) XVECTOR (arg);
2296 saved_windows = XVECTOR (data->saved_windows);
2298 f = XFRAME (XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame);
2300 if (XFASTINT (data->frame_height) != FRAME_HEIGHT (f)
2301 || XFASTINT (data->frame_width) != FRAME_WIDTH (f))
2303 /* Presumably something clever could be done.
2304 However, it doesn't seem worth the effort */
2305 error ("Frame size %dx%d in saved window configuration mismatches frame.",
2306 XFASTINT (data->frame_height),
2307 XFASTINT (data->frame_width));
2310 windows_or_buffers_changed++;
2311 new_current_buffer = data->current_buffer;
2312 if (NILP (XBUFFER (new_current_buffer)->name))
2313 new_current_buffer = Qnil;
2315 /* Mark all windows now on frame as "deleted".
2316 Restoring the new configuration "undeletes" any that are in it. */
2318 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2319 #if 0
2320 /* This loses when the minibuf frame is not f. */
2321 delete_all_subwindows (XWINDOW (XWINDOW (minibuf_window)->prev));
2322 #endif
2324 for (k = 0; k < saved_windows->size; k++)
2326 p = SAVED_WINDOW_N (saved_windows, k);
2327 w = XWINDOW (p->window);
2328 w->next = Qnil;
2330 if (!NILP (p->parent))
2331 w->parent = SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window;
2332 else
2333 w->parent = Qnil;
2335 if (!NILP (p->prev))
2337 w->prev = SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window;
2338 #ifdef MULTI_FRAME
2339 /* This is true for a minibuffer-only frame. */
2340 if (w->mini_p && EQ (w->prev, p->window))
2341 w->next = Qnil;
2342 else
2343 #endif /* MULTI_FRAME */
2344 XWINDOW (w->prev)->next = p->window;
2346 else
2348 w->prev = Qnil;
2349 if (!NILP (w->parent))
2351 if (EQ (p->width, XWINDOW (w->parent)->width))
2353 XWINDOW (w->parent)->vchild = p->window;
2354 XWINDOW (w->parent)->hchild = Qnil;
2356 else
2358 XWINDOW (w->parent)->hchild = p->window;
2359 XWINDOW (w->parent)->vchild = Qnil;
2363 w->left = p->left;
2364 w->top = p->top;
2365 w->width = p->width;
2366 w->height = p->height;
2367 w->hscroll = p->hscroll;
2368 w->display_table = p->display_table;
2369 XFASTINT (w->last_modified) = 0;
2371 /* Reinstall the saved buffer and pointers into it. */
2372 if (NILP (p->buffer))
2373 w->buffer = p->buffer;
2374 else
2376 if (!NILP (XBUFFER (p->buffer)->name))
2377 /* If saved buffer is alive, install it. */
2379 w->buffer = p->buffer;
2380 w->start_at_line_beg = p->start_at_line_beg;
2381 set_marker_restricted (w->start, Fmarker_position (p->start), w->buffer);
2382 set_marker_restricted (w->pointm, Fmarker_position (p->pointm), w->buffer);
2383 Fset_marker (XBUFFER (w->buffer)->mark,
2384 Fmarker_position (p->mark), w->buffer);
2386 if (!EQ (p->buffer, new_current_buffer) &&
2387 XBUFFER (p->buffer) == current_buffer)
2388 Fgoto_char (w->pointm);
2390 else if (NILP (XBUFFER (w->buffer)->name))
2391 /* Else if window's old buffer is dead too, get a live one. */
2393 w->buffer = Fcdr (Fcar (Vbuffer_alist));
2394 /* This will set the markers to beginning of visible range. */
2395 set_marker_restricted (w->start, make_number (0), w->buffer);
2396 set_marker_restricted (w->pointm, make_number (0), w->buffer);
2397 w->start_at_line_beg = Qt;
2399 else
2400 /* Keeping window's old buffer; make sure the markers are real. */
2401 /* Else if window's old buffer is dead too, get a live one. */
2403 /* Set window markers at start of visible range. */
2404 if (XMARKER (w->start)->buffer == 0)
2405 set_marker_restricted (w->start, make_number (0), w->buffer);
2406 if (XMARKER (w->pointm)->buffer == 0)
2407 set_marker_restricted (w->pointm,
2408 make_number (BUF_PT (XBUFFER (w->buffer))),
2409 w->buffer);
2410 w->start_at_line_beg = Qt;
2415 FRAME_ROOT_WINDOW (f) = data->root_window;
2417 #ifdef MULTI_FRAME
2418 if (f != selected_frame && ! FRAME_IS_TERMCAP (f))
2419 Fselect_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
2420 #endif
2422 if (f == selected_frame)
2424 Fselect_window (data->current_window);
2425 if (!NILP (new_current_buffer))
2426 Fset_buffer (new_current_buffer);
2427 else
2428 Fset_buffer (XWINDOW (selected_window)->buffer);
2431 Vminibuf_scroll_window = data->minibuf_scroll_window;
2432 return (Qnil);
2435 /* Mark all windows now on frame as deleted
2436 by setting their buffers to nil. */
2438 static void
2439 delete_all_subwindows (w)
2440 register struct window *w;
2442 register int count = 1;
2443 w->buffer = Qnil;
2444 if (!NILP (w->next))
2445 delete_all_subwindows (XWINDOW (w->next));
2446 if (!NILP (w->vchild))
2447 delete_all_subwindows (XWINDOW (w->vchild));
2448 if (!NILP (w->hchild))
2449 delete_all_subwindows (XWINDOW (w->hchild));
2452 static int
2453 count_windows (window)
2454 register struct window *window;
2456 register int count = 1;
2457 if (!NILP (window->next))
2458 count += count_windows (XWINDOW (window->next));
2459 if (!NILP (window->vchild))
2460 count += count_windows (XWINDOW (window->vchild));
2461 if (!NILP (window->hchild))
2462 count += count_windows (XWINDOW (window->hchild));
2463 return count;
2466 static int
2467 save_window_save (window, vector, i)
2468 Lisp_Object window;
2469 struct Lisp_Vector *vector;
2470 int i;
2472 register struct saved_window *p;
2473 register struct window *w;
2474 register Lisp_Object tem;
2476 for (;!NILP (window); window = w->next)
2478 p = SAVED_WINDOW_N (vector, i);
2479 w = XWINDOW (window);
2481 XFASTINT (w->temslot) = i++;
2482 p->window = window;
2483 p->buffer = w->buffer;
2484 p->left = w->left;
2485 p->top = w->top;
2486 p->width = w->width;
2487 p->height = w->height;
2488 p->hscroll = w->hscroll;
2489 p->display_table = w->display_table;
2490 if (!NILP (w->buffer))
2492 /* Save w's value of point in the window configuration.
2493 If w is the selected window, then get the value of point
2494 from the buffer; pointm is garbage in the selected window. */
2495 if (EQ (window, selected_window))
2497 p->pointm = Fmake_marker ();
2498 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
2499 w->buffer);
2501 else
2502 p->pointm = Fcopy_marker (w->pointm);
2504 p->start = Fcopy_marker (w->start);
2505 p->start_at_line_beg = w->start_at_line_beg;
2507 tem = XBUFFER (w->buffer)->mark;
2508 p->mark = Fcopy_marker (tem);
2510 else
2512 p->pointm = Qnil;
2513 p->start = Qnil;
2514 p->mark = Qnil;
2515 p->start_at_line_beg = Qnil;
2518 if (NILP (w->parent))
2519 p->parent = Qnil;
2520 else
2521 p->parent = XWINDOW (w->parent)->temslot;
2523 if (NILP (w->prev))
2524 p->prev = Qnil;
2525 else
2526 p->prev = XWINDOW (w->prev)->temslot;
2528 if (!NILP (w->vchild))
2529 i = save_window_save (w->vchild, vector, i);
2530 if (!NILP (w->hchild))
2531 i = save_window_save (w->hchild, vector, i);
2534 return i;
2537 DEFUN ("current-window-configuration",
2538 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
2539 "Return an object representing the current window configuration of FRAME.\n\
2540 If FRAME is nil or omitted, use the selected frame.\n\
2541 This describes the number of windows, their sizes and current buffers,\n\
2542 and for each displayed buffer, where display starts, and the positions of\n\
2543 point and mark. An exception is made for point in the current buffer:\n\
2544 its value is -not- saved.")
2545 (frame)
2546 Lisp_Object frame;
2548 register Lisp_Object tem;
2549 register int n_windows;
2550 register struct save_window_data *data;
2551 register int i;
2552 FRAME_PTR f;
2554 if (NILP (frame))
2555 f = selected_frame;
2556 else
2558 CHECK_LIVE_FRAME (frame, 0);
2559 f = XFRAME (frame);
2562 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2563 data = (struct save_window_data *)
2564 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2565 Qnil));
2566 XFASTINT (data->frame_width) = FRAME_WIDTH (f);
2567 XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
2568 data->current_window = FRAME_SELECTED_WINDOW (f);
2569 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2570 data->minibuf_scroll_window = Vminibuf_scroll_window;
2571 data->root_window = FRAME_ROOT_WINDOW (f);
2572 tem = Fmake_vector (make_number (n_windows), Qnil);
2573 data->saved_windows = tem;
2574 for (i = 0; i < n_windows; i++)
2575 XVECTOR (tem)->contents[i]
2576 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
2577 save_window_save (FRAME_ROOT_WINDOW (f),
2578 XVECTOR (tem), 0);
2579 XSET (tem, Lisp_Window_Configuration, data);
2580 return (tem);
2583 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
2584 0, UNEVALLED, 0,
2585 "Execute body, preserving window sizes and contents.\n\
2586 Restores which buffer appears in which window, where display starts,\n\
2587 as well as the current buffer.\n\
2588 Does not restore the value of point in current buffer.")
2589 (args)
2590 Lisp_Object args;
2592 register Lisp_Object val;
2593 register int count = specpdl_ptr - specpdl;
2595 record_unwind_protect (Fset_window_configuration,
2596 Fcurrent_window_configuration (Qnil));
2597 val = Fprogn (args);
2598 return unbind_to (count, val);
2601 init_window_once ()
2603 #ifdef MULTI_FRAME
2604 selected_frame = make_terminal_frame ();
2605 minibuf_window = selected_frame->minibuffer_window;
2606 selected_window = selected_frame->selected_window;
2607 last_nonminibuf_frame = selected_frame;
2608 #else /* not MULTI_FRAME */
2609 extern Lisp_Object get_minibuffer ();
2611 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
2612 minibuf_window = make_window ();
2614 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
2615 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
2617 /* These values 9 and 10 are arbitrary,
2618 just so that there is "something there."
2619 Correct values are put in in init_xdisp */
2621 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
2622 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
2624 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
2625 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
2626 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
2628 /* Prevent error in Fset_window_buffer. */
2629 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
2630 XWINDOW (minibuf_window)->buffer = Qt;
2632 /* Now set them up for real. */
2633 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
2634 Fcurrent_buffer ());
2635 Fset_window_buffer (minibuf_window, get_minibuffer (0));
2637 selected_window = FRAME_ROOT_WINDOW (selected_frame);
2638 /* Make sure this window seems more recently used than
2639 a newly-created, never-selected window. Increment
2640 window_select_count so the first selection ever will get
2641 something newer than this. */
2642 XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
2643 #endif /* not MULTI_FRAME */
2646 syms_of_window ()
2648 Qwindowp = intern ("windowp");
2649 staticpro (&Qwindowp);
2651 /* Make sure all windows get marked */
2652 staticpro (&minibuf_window);
2654 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
2655 "Non-nil means call as function to display a help buffer.\n\
2656 Used by `with-output-to-temp-buffer'.");
2657 Vtemp_buffer_show_function = Qnil;
2659 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
2660 "If non-nil, function to call to handle `display-buffer'.\n\
2661 It will receive two args, the buffer and a flag which if non-nil means\n\
2662 that the currently selected window is not acceptable.\n\
2663 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2664 work using this function.");
2665 Vdisplay_buffer_function = Qnil;
2667 DEFVAR_LISP ("mouse-window", &Vmouse_window,
2668 "Window that the last mouse click occurred on.");
2669 Vmouse_window = Qnil;
2671 DEFVAR_LISP ("mouse-event", &Vmouse_event,
2672 "The last mouse-event object. A list of four elements:\n\
2673 ((X-POS Y-POS) WINDOW FRAME-PART KEYSEQ).\n\
2674 KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2675 WINDOW is the window that the click applies do.\n\
2676 If FRAME-PART is non-nil, the event was on a scrollbar;\n\
2677 then Y-POS is really the total length of the scrollbar, while X-POS is\n\
2678 the relative position of the scrollbar's value within that total length.\n\
2679 FRAME-PART is one of the following symbols:\n\
2680 `vertical-scrollbar', `vertical-slider',\n\
2681 `vertical-thumbup', `vertical-thumbdown',\n\
2682 `horizontal-scrollbar', `horizontal-slider',\n\
2683 `horizontal-thumbleft', `horizontal-thumbright'");
2684 Vmouse_event = Qnil;
2686 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
2687 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2688 Vminibuf_scroll_window = Qnil;
2690 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
2691 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2692 Vother_window_scroll_buffer = Qnil;
2694 #ifdef MULTI_FRAME
2695 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
2696 "*Non-nil means `display-buffer' should make a separate frame.");
2697 pop_up_frames = 0;
2699 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
2700 "*If non-nil, function to call to handle automatic new frame creation.\n\
2701 It is called with no arguments and should return a newly created frame.\n\
2703 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
2704 where `pop-up-frame-alist' would hold the default frame parameters.");
2705 Vpop_up_frame_function = Qnil;
2706 #endif
2708 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
2709 "*Non-nil means display-buffer should make new windows.");
2710 pop_up_windows = 1;
2712 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
2713 "*Number of lines of continuity when scrolling by screenfuls.");
2714 next_screen_context_lines = 2;
2716 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
2717 "*display-buffer would prefer to split the largest window if this large.\n\
2718 If there is only one window, it is split regardless of this value.");
2719 split_height_threshold = 500;
2721 DEFVAR_INT ("window-min-height", &window_min_height,
2722 "*Delete any window less than this tall (including its mode line).");
2723 window_min_height = 4;
2725 DEFVAR_INT ("window-min-width", &window_min_width,
2726 "*Delete any window less than this wide.");
2727 window_min_width = 10;
2729 defsubr (&Sselected_window);
2730 defsubr (&Sminibuffer_window);
2731 defsubr (&Swindow_minibuffer_p);
2732 defsubr (&Swindowp);
2733 defsubr (&Spos_visible_in_window_p);
2734 defsubr (&Swindow_buffer);
2735 defsubr (&Swindow_height);
2736 defsubr (&Swindow_width);
2737 defsubr (&Swindow_hscroll);
2738 defsubr (&Sset_window_hscroll);
2739 defsubr (&Swindow_edges);
2740 defsubr (&Scoordinates_in_window_p);
2741 defsubr (&Swindow_at);
2742 defsubr (&Swindow_point);
2743 defsubr (&Swindow_start);
2744 defsubr (&Swindow_end);
2745 defsubr (&Sset_window_point);
2746 defsubr (&Sset_window_start);
2747 defsubr (&Swindow_dedicated_p);
2748 defsubr (&Sset_window_dedicated_p);
2749 defsubr (&Swindow_display_table);
2750 defsubr (&Sset_window_display_table);
2751 defsubr (&Snext_window);
2752 defsubr (&Sprevious_window);
2753 defsubr (&Sother_window);
2754 defsubr (&Sget_lru_window);
2755 defsubr (&Sget_largest_window);
2756 defsubr (&Sget_buffer_window);
2757 defsubr (&Sdelete_other_windows);
2758 defsubr (&Sdelete_windows_on);
2759 defsubr (&Sreplace_buffer_in_windows);
2760 defsubr (&Sdelete_window);
2761 defsubr (&Sset_window_buffer);
2762 defsubr (&Sselect_window);
2763 defsubr (&Sdisplay_buffer);
2764 defsubr (&Ssplit_window);
2765 defsubr (&Senlarge_window);
2766 defsubr (&Sshrink_window);
2767 defsubr (&Sscroll_up);
2768 defsubr (&Sscroll_down);
2769 defsubr (&Sscroll_left);
2770 defsubr (&Sscroll_right);
2771 defsubr (&Sscroll_other_window);
2772 defsubr (&Srecenter);
2773 defsubr (&Smove_to_window_line);
2774 defsubr (&Swindow_configuration_p);
2775 defsubr (&Sset_window_configuration);
2776 defsubr (&Scurrent_window_configuration);
2777 defsubr (&Ssave_window_excursion);
2780 keys_of_window ()
2782 initial_define_key (control_x_map, '1', "delete-other-windows");
2783 initial_define_key (control_x_map, '2', "split-window");
2784 initial_define_key (control_x_map, '0', "delete-window");
2785 initial_define_key (control_x_map, 'o', "other-window");
2786 initial_define_key (control_x_map, '^', "enlarge-window");
2787 initial_define_key (control_x_map, '<', "scroll-left");
2788 initial_define_key (control_x_map, '>', "scroll-right");
2790 initial_define_key (global_map, Ctl ('V'), "scroll-up");
2791 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
2792 initial_define_key (meta_map, 'v', "scroll-down");
2794 initial_define_key (global_map, Ctl('L'), "recenter");
2795 initial_define_key (meta_map, 'r', "move-to-window-line");