(Fselect_window): Use Fhandle_switch_frame.
[bpt/emacs.git] / src / window.c
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1992, 1993 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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.
11
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.
16
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. */
20
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"
31
32 Lisp_Object Qwindowp, Qwindow_live_p;
33
34 Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
35 Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
36
37 void delete_all_subwindows ();
38 static struct window *decode_window();
39
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.
44
45 This value is always the same as
46 FRAME_SELECTED_WINDOW (selected_frame). */
47
48 Lisp_Object selected_window;
49
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;
55
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;
59
60 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
61 Lisp_Object Vother_window_scroll_buffer;
62
63 /* Last mouse click data structure (nil if no mouse support). */
64 Lisp_Object Vmouse_event;
65
66 /* Non-nil means it's function to call to display temp buffers. */
67 Lisp_Object Vtemp_buffer_show_function;
68
69 /* If a window gets smaller than either of these, it is removed. */
70 int window_min_height;
71 int window_min_width;
72
73 /* Nonzero implies Fdisplay_buffer should create windows. */
74 int pop_up_windows;
75
76 /* Nonzero implies make new frames for Fdisplay_buffer. */
77 int pop_up_frames;
78
79 /* Non-nil means use this function instead of default */
80 Lisp_Object Vpop_up_frame_function;
81
82 /* Function to call to handle Fdisplay_buffer. */
83 Lisp_Object Vdisplay_buffer_function;
84
85 /* Fdisplay_buffer always splits the largest window
86 if that window is more than this high. */
87 int split_height_threshold;
88
89 /* Number of lines of continuity in scrolling by screenfuls. */
90 int next_screen_context_lines;
91
92 /* Incremented for each window created. */
93 static int sequence_number;
94
95 #define min(a, b) ((a) < (b) ? (a) : (b))
96 \f
97 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
98 "Returns t if OBJ is a window.")
99 (obj)
100 Lisp_Object obj;
101 {
102 return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
103 }
104
105 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
106 "Returns t if OBJ is a window which is currently visible.")
107 (obj)
108 Lisp_Object obj;
109 {
110 return ((XTYPE (obj) == Lisp_Window
111 && ! NILP (XWINDOW (obj)->buffer))
112 ? Qt : Qnil);
113 }
114
115 Lisp_Object
116 make_window ()
117 {
118 register Lisp_Object val;
119 register struct window *p;
120
121 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
122 includes the first element. */
123 val = Fmake_vector (
124 make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)
125 + sizeof (Lisp_Object))
126 / sizeof (Lisp_Object)),
127 Qnil);
128 XSETTYPE (val, Lisp_Window);
129 p = XWINDOW (val);
130 XFASTINT (p->sequence_number) = ++sequence_number;
131 XFASTINT (p->left) = XFASTINT (p->top)
132 = XFASTINT (p->height) = XFASTINT (p->width)
133 = XFASTINT (p->hscroll) = 0;
134 XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
135 p->start = Fmake_marker ();
136 p->pointm = Fmake_marker ();
137 XFASTINT (p->use_time) = 0;
138 p->frame = Qnil;
139 p->display_table = Qnil;
140 p->dedicated = Qnil;
141 return val;
142 }
143
144 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
145 "Return the window that the cursor now appears in and commands apply to.")
146 ()
147 {
148 return selected_window;
149 }
150
151 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
152 "Return the window used now for minibuffers.\n\
153 If the optional argument FRAME is specified, return the minibuffer window\n\
154 used by that frame.")
155 (frame)
156 Lisp_Object frame;
157 {
158 #ifdef MULTI_FRAME
159 if (NILP (frame))
160 XSET (frame, Lisp_Frame, selected_frame);
161 else
162 CHECK_LIVE_FRAME (frame, 0);
163 #endif
164
165 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
166 }
167
168 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
169 "Returns non-nil if WINDOW is a minibuffer window.")
170 (window)
171 Lisp_Object window;
172 {
173 struct window *w = decode_window (window);
174 return (MINI_WINDOW_P (w) ? Qt : Qnil);
175 }
176
177 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
178 Spos_visible_in_window_p, 0, 2, 0,
179 "Return t if position POS is currently on the frame in WINDOW.\n\
180 Returns nil if that position is scrolled vertically out of view.\n\
181 POS defaults to point; WINDOW, to the selected window.")
182 (pos, window)
183 Lisp_Object pos, window;
184 {
185 register struct window *w;
186 register int top;
187 register int height;
188 register int posint;
189 register struct buffer *buf;
190 struct position posval;
191
192 if (NILP (pos))
193 posint = point;
194 else
195 {
196 CHECK_NUMBER_COERCE_MARKER (pos, 0);
197 posint = XINT (pos);
198 }
199
200 w = decode_window (window);
201 top = marker_position (w->start);
202
203 if (posint < top)
204 return Qnil;
205
206 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
207
208 buf = XBUFFER (w->buffer);
209 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
210 {
211 /* If frame is up to date,
212 use the info recorded about how much text fit on it. */
213 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
214 || (XFASTINT (w->window_end_vpos) < height))
215 return Qt;
216 return Qnil;
217 }
218 else
219 {
220 if (posint > BUF_Z (buf))
221 return Qnil;
222
223 /* If that info is not correct, calculate afresh */
224 posval = *compute_motion (top, 0, 0, posint, height, 0,
225 window_internal_width (w) - 1,
226 XINT (w->hscroll), 0);
227
228 return posval.vpos < height ? Qt : Qnil;
229 }
230 }
231 \f
232 static struct window *
233 decode_window (window)
234 register Lisp_Object window;
235 {
236 if (NILP (window))
237 return XWINDOW (selected_window);
238
239 CHECK_LIVE_WINDOW (window, 0);
240 return XWINDOW (window);
241 }
242
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;
247 {
248 return decode_window (window)->buffer;
249 }
250
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;
255 {
256 return decode_window (window)->height;
257 }
258
259 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
260 "Return the number of columns in WINDOW.")
261 (window)
262 Lisp_Object window;
263 {
264 register struct window *w = decode_window (window);
265 register int width = XFASTINT (w->width);
266
267 return make_number (window_internal_width (w));
268 }
269
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;
274 {
275 return decode_window (window)->hscroll;
276 }
277
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;
283 {
284 register struct window *w;
285
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;
295 }
296
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;
305 {
306 register struct window *w = decode_window (window);
307
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))));
313 }
314
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;
328 {
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);
333
334 if ( *x < left || *x >= left + width
335 || *y < top || *y >= top + window_height)
336 return 0;
337
338 /* Is the character is the mode line? */
339 if (*y == top + window_height - 1
340 && ! MINI_WINDOW_P (w))
341 return 2;
342
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;
347
348 *x -= left;
349 *y -= top;
350 return 1;
351 }
352
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;
367 {
368 int x, y;
369
370 CHECK_LIVE_WINDOW (window, 0);
371 CHECK_CONS (coordinates, 1);
372 x = XINT (Fcar (coordinates));
373 y = XINT (Fcdr (coordinates));
374
375 switch (coordinates_in_window (XWINDOW (window), &x, &y))
376 {
377 case 0: /* NOT in window at all. */
378 return Qnil;
379
380 case 1: /* In text part of window. */
381 return Fcons (x, y);
382
383 case 2: /* In mode line of window. */
384 return Qmode_line;
385
386 case 3: /* On right border of window. */
387 return Qvertical_line;
388
389 default:
390 abort ();
391 }
392 }
393
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;
404 {
405 register Lisp_Object tem, first;
406
407 tem = first = FRAME_SELECTED_WINDOW (frame);
408
409 do
410 {
411 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
412
413 if (found)
414 {
415 *part = found - 1;
416 return tem;
417 }
418
419 tem = Fnext_window (tem, Qt, Qlambda);
420 }
421 while (! EQ (tem, first));
422
423 return Qnil;
424 }
425
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;
433 {
434 int part;
435
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);
444
445 return window_from_coordinates (XFRAME (frame),
446 XINT (x), XINT (y),
447 &part);
448 }
449
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\
454 \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;
462 {
463 register struct window *w = decode_window (window);
464
465 if (w == XWINDOW (selected_window)
466 && current_buffer == XBUFFER (w->buffer))
467 return Fpoint ();
468 return Fmarker_position (w->pointm);
469 }
470
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;
475 {
476 return Fmarker_position (decode_window (window)->start);
477 }
478
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;
483 {
484 Lisp_Object value;
485 struct window *w = decode_window (window);
486
487 XSET (value, Lisp_Int,
488 BUF_Z (current_buffer) - XFASTINT (w->window_end_pos));
489
490 return value;
491 }
492
493 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
494 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
495 (window, pos)
496 Lisp_Object window, pos;
497 {
498 register struct window *w = decode_window (window);
499
500 CHECK_NUMBER_COERCE_MARKER (pos, 1);
501 if (w == XWINDOW (selected_window))
502 Fgoto_char (pos);
503 else
504 set_marker_restricted (w->pointm, pos, w->buffer);
505
506 return pos;
507 }
508
509 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
510 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
511 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
512 from overriding motion of point in order to display at this exact start.")
513 (window, pos, noforce)
514 Lisp_Object window, pos, noforce;
515 {
516 register struct window *w = decode_window (window);
517
518 CHECK_NUMBER_COERCE_MARKER (pos, 1);
519 set_marker_restricted (w->start, pos, w->buffer);
520 /* this is not right, but much easier than doing what is right. */
521 w->start_at_line_beg = Qnil;
522 if (NILP (noforce))
523 w->force_start = Qt;
524 w->update_mode_line = Qt;
525 XFASTINT (w->last_modified) = 0;
526 if (!EQ (window, selected_window))
527 windows_or_buffers_changed++;
528 return pos;
529 }
530
531 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
532 1, 1, 0,
533 "Return WINDOW's dedicated object, usually t or nil.\n\
534 See also `set-window-buffer-dedicated'.")
535 (window)
536 Lisp_Object window;
537 {
538 return decode_window (window)->dedicated;
539 }
540
541 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
542 Sset_window_dedicated_p, 2, 2, 0,
543 "Control whether WINDOW is dedicated to the buffer it displays.\n\
544 If it is dedicated, Emacs will not automatically change\n\
545 which buffer appears in it.\n\
546 The second argument is the new value for the dedication flag;\n\
547 non-nil means yes.")
548 (window, arg)
549 Lisp_Object window, arg;
550 {
551 register struct window *w = decode_window (window);
552
553 if (NILP (arg))
554 w->dedicated = Qnil;
555 else
556 w->dedicated = Qt;
557
558 return w->dedicated;
559 }
560
561 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
562 0, 1, 0,
563 "Return the display-table that WINDOW is using.")
564 (window)
565 Lisp_Object window;
566 {
567 return decode_window (window)->display_table;
568 }
569
570 /* Get the display table for use currently on window W.
571 This is either W's display table or W's buffer's display table.
572 Ignore the specified tables if they are not valid;
573 if no valid table is specified, return 0. */
574
575 struct Lisp_Vector *
576 window_display_table (w)
577 struct window *w;
578 {
579 Lisp_Object tem;
580 tem = w->display_table;
581 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
582 return XVECTOR (tem);
583 tem = XBUFFER (w->buffer)->display_table;
584 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
585 return XVECTOR (tem);
586 tem = Vstandard_display_table;
587 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
588 return XVECTOR (tem);
589 return 0;
590 }
591
592 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
593 "Set WINDOW's display-table to TABLE.")
594 (window, table)
595 register Lisp_Object window, table;
596 {
597 register struct window *w;
598 register Lisp_Object z; /* Return value. */
599
600 w = decode_window (window);
601 w->display_table = table;
602 return table;
603 }
604 \f
605 /* Record info on buffer window w is displaying
606 when it is about to cease to display that buffer. */
607 static
608 unshow_buffer (w)
609 register struct window *w;
610 {
611 Lisp_Object buf = w->buffer;
612
613 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
614 abort ();
615
616 if (w == XWINDOW (selected_window)
617 || ! EQ (buf, XWINDOW (selected_window)->buffer))
618 /* Do this except when the selected window's buffer
619 is being removed from some other window. */
620 XBUFFER (buf)->last_window_start = marker_position (w->start);
621
622 /* Point in the selected window's buffer
623 is actually stored in that buffer, and the window's pointm isn't used.
624 So don't clobber point in that buffer. */
625 if (! EQ (buf, XWINDOW (selected_window)->buffer))
626 BUF_PT (XBUFFER (buf))
627 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
628 marker_position (w->pointm),
629 BUF_ZV (XBUFFER (buf)));
630 }
631
632 /* Put replacement into the window structure in place of old. */
633 static
634 replace_window (old, replacement)
635 Lisp_Object old, replacement;
636 {
637 register Lisp_Object tem;
638 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
639
640 /* If OLD is its frame's root_window, then replacement is the new
641 root_window for that frame. */
642
643 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
644 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
645
646 p->left = o->left;
647 p->top = o->top;
648 p->width = o->width;
649 p->height = o->height;
650
651 p->next = tem = o->next;
652 if (!NILP (tem))
653 XWINDOW (tem)->prev = replacement;
654
655 p->prev = tem = o->prev;
656 if (!NILP (tem))
657 XWINDOW (tem)->next = replacement;
658
659 p->parent = tem = o->parent;
660 if (!NILP (tem))
661 {
662 if (EQ (XWINDOW (tem)->vchild, old))
663 XWINDOW (tem)->vchild = replacement;
664 if (EQ (XWINDOW (tem)->hchild, old))
665 XWINDOW (tem)->hchild = replacement;
666 }
667
668 /*** Here, if replacement is a vertical combination
669 and so is its new parent, we should make replacement's
670 children be children of that parent instead. ***/
671 }
672
673 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
674 "Remove WINDOW from the display. Default is selected window.")
675 (window)
676 register Lisp_Object window;
677 {
678 register Lisp_Object tem, parent, sib;
679 register struct window *p;
680 register struct window *par;
681
682 /* Because this function is called by other C code on non-leaf
683 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
684 so we can't decode_window here. */
685 if (NILP (window))
686 window = selected_window;
687 else
688 CHECK_WINDOW (window, 0);
689 p = XWINDOW (window);
690
691 /* It's okay to delete an already-deleted window. */
692 if (NILP (p->buffer)
693 && NILP (p->hchild)
694 && NILP (p->vchild))
695 return Qnil;
696
697 parent = p->parent;
698 if (NILP (parent))
699 error ("Attempt to delete minibuffer or sole ordinary window");
700 par = XWINDOW (parent);
701
702 windows_or_buffers_changed++;
703
704 /* Are we trying to delete any frame's selected window? */
705 {
706 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
707
708 if (EQ (window, FRAME_SELECTED_WINDOW (XFRAME (frame))))
709 {
710 Lisp_Object alternative = Fnext_window (window, Qlambda, Qnil);
711
712 /* If we're about to delete the selected window on the
713 selected frame, then we should use Fselect_window to select
714 the new window. On the other hand, if we're about to
715 delete the selected window on any other frame, we shouldn't do
716 anything but set the frame's selected_window slot. */
717 if (EQ (window, selected_window))
718 Fselect_window (alternative);
719 else
720 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
721 }
722 }
723
724 tem = p->buffer;
725 /* tem is null for dummy parent windows
726 (which have inferiors but not any contents themselves) */
727 if (!NILP (tem))
728 {
729 unshow_buffer (p);
730 unchain_marker (p->pointm);
731 unchain_marker (p->start);
732 }
733
734 tem = p->next;
735 if (!NILP (tem))
736 XWINDOW (tem)->prev = p->prev;
737
738 tem = p->prev;
739 if (!NILP (tem))
740 XWINDOW (tem)->next = p->next;
741
742 if (EQ (window, par->hchild))
743 par->hchild = p->next;
744 if (EQ (window, par->vchild))
745 par->vchild = p->next;
746
747 /* Find one of our siblings to give our space to. */
748 sib = p->prev;
749 if (NILP (sib))
750 {
751 /* If p gives its space to its next sibling, that sibling needs
752 to have its top/left side pulled back to where p's is.
753 set_window_{height,width} will re-position the sibling's
754 children. */
755 sib = p->next;
756 XWINDOW (sib)->top = p->top;
757 XWINDOW (sib)->left = p->left;
758 }
759
760 /* Stretch that sibling. */
761 if (!NILP (par->vchild))
762 set_window_height (sib,
763 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
764 1);
765 if (!NILP (par->hchild))
766 set_window_width (sib,
767 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
768 1);
769
770 /* If parent now has only one child,
771 put the child into the parent's place. */
772 tem = par->hchild;
773 if (NILP (tem))
774 tem = par->vchild;
775 if (NILP (XWINDOW (tem)->next))
776 replace_window (parent, tem);
777
778 /* Since we may be deleting combination windows, we must make sure that
779 not only p but all its children have been marked as deleted. */
780 if (! NILP (p->hchild))
781 delete_all_subwindows (XWINDOW (p->hchild));
782 else if (! NILP (p->vchild))
783 delete_all_subwindows (XWINDOW (p->vchild));
784
785 /* Mark this window as deleted. */
786 p->buffer = p->hchild = p->vchild = Qnil;
787
788 return Qnil;
789 }
790 \f
791
792 extern Lisp_Object next_frame (), prev_frame ();
793
794 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
795 "Return next window after WINDOW in canonical ordering of windows.\n\
796 If omitted, WINDOW defaults to the selected window.\n\
797 \n\
798 Optional second arg MINIBUF t means count the minibuffer window even\n\
799 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
800 it is active. MINIBUF neither t nor nil means not to count the\n\
801 minibuffer even if it is active.\n\
802 \n\
803 Several frames may share a single minibuffer; if the minibuffer\n\
804 counts, all windows on all frames that share that minibuffer count\n\
805 too. This means that next-window may be used to iterate through the\n\
806 set of windows even when the minibuffer is on another frame. If the\n\
807 minibuffer does not count, only windows from WINDOW's frame count.\n\
808 \n\
809 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
810 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
811 above. If neither nil nor t, restrict to WINDOW's frame.\n\
812 \n\
813 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
814 `next-window' to iterate through the entire cycle of acceptable\n\
815 windows, eventually ending up back at the window you started with.\n\
816 `previous-window' traverses the same cycle, in the reverse order.")
817 (window, minibuf, all_frames)
818 register Lisp_Object window, minibuf, all_frames;
819 {
820 register Lisp_Object tem;
821 Lisp_Object start_window;
822
823 if (NILP (window))
824 window = selected_window;
825 else
826 CHECK_LIVE_WINDOW (window, 0);
827
828 start_window = window;
829
830 /* minibuf == nil may or may not include minibuffers.
831 Decide if it does. */
832 if (NILP (minibuf))
833 minibuf = (minibuf_level ? Qt : Qlambda);
834
835 /* all_frames == nil doesn't specify which frames to include.
836 Decide which frames it includes. */
837 if (NILP (all_frames))
838 all_frames = (EQ (minibuf, Qt)
839 ? (FRAME_MINIBUF_WINDOW
840 (XFRAME
841 (WINDOW_FRAME
842 (XWINDOW (window)))))
843 : Qnil);
844 else if (! EQ (all_frames, Qt))
845 all_frames = Qnil;
846
847 /* Do this loop at least once, to get the next window, and perhaps
848 again, if we hit the minibuffer and that is not acceptable. */
849 do
850 {
851 /* Find a window that actually has a next one. This loop
852 climbs up the tree. */
853 while (tem = XWINDOW (window)->next, NILP (tem))
854 if (tem = XWINDOW (window)->parent, !NILP (tem))
855 window = tem;
856 else
857 {
858 /* We've reached the end of this frame.
859 Which other frames are acceptable? */
860 tem = WINDOW_FRAME (XWINDOW (window));
861 #ifdef MULTI_FRAME
862 if (! NILP (all_frames))
863 tem = next_frame (tem, all_frames);
864 #endif
865 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
866
867 break;
868 }
869
870 window = tem;
871
872 /* If we're in a combination window, find its first child and
873 recurse on that. Otherwise, we've found the window we want. */
874 while (1)
875 {
876 if (!NILP (XWINDOW (window)->hchild))
877 window = XWINDOW (window)->hchild;
878 else if (!NILP (XWINDOW (window)->vchild))
879 window = XWINDOW (window)->vchild;
880 else break;
881 }
882 }
883 /* Which windows are acceptible?
884 Exit the loop and accept this window if
885 this isn't a minibuffer window, or
886 we're accepting minibuffer windows, or
887 we've come all the way around and we're back at the original window. */
888 while (MINI_WINDOW_P (XWINDOW (window))
889 && ! EQ (minibuf, Qt)
890 && ! EQ (window, start_window));
891
892 return window;
893 }
894
895 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
896 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
897 If omitted, WINDOW defaults to the selected window.\n\
898 \n\
899 Optional second arg MINIBUF t means count the minibuffer window even\n\
900 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
901 it is active. MINIBUF neither t nor nil means not to count the\n\
902 minibuffer even if it is active.\n\
903 \n\
904 Several frames may share a single minibuffer; if the minibuffer\n\
905 counts, all windows on all frames that share that minibuffer count\n\
906 too. This means that previous-window may be used to iterate through\n\
907 the set of windows even when the minibuffer is on another frame. If\n\
908 the minibuffer does not count, only windows from WINDOW's frame\n\
909 count.\n\
910 \n\
911 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
912 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
913 above. If neither nil nor t, restrict to WINDOW's frame.\n\
914 \n\
915 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
916 `previous-window' to iterate through the entire cycle of acceptable\n\
917 windows, eventually ending up back at the window you started with.\n\
918 `next-window' traverses the same cycle, in the reverse order.")
919 (window, minibuf, all_frames)
920 register Lisp_Object window, minibuf, all_frames;
921 {
922 register Lisp_Object tem;
923 Lisp_Object start_window;
924
925 if (NILP (window))
926 window = selected_window;
927 else
928 CHECK_LIVE_WINDOW (window, 0);
929
930 start_window = window;
931
932 /* minibuf == nil may or may not include minibuffers.
933 Decide if it does. */
934 if (NILP (minibuf))
935 minibuf = (minibuf_level ? Qt : Qlambda);
936
937 /* all_frames == nil doesn't specify which frames to include.
938 Decide which frames it includes. */
939 if (NILP (all_frames))
940 all_frames = (EQ (minibuf, Qt)
941 ? (FRAME_MINIBUF_WINDOW
942 (XFRAME
943 (WINDOW_FRAME
944 (XWINDOW (window)))))
945 : Qnil);
946 else if (! EQ (all_frames, Qt))
947 all_frames = Qnil;
948
949 /* Do this loop at least once, to get the previous window, and perhaps
950 again, if we hit the minibuffer and that is not acceptable. */
951 do
952 {
953 /* Find a window that actually has a previous one. This loop
954 climbs up the tree. */
955 while (tem = XWINDOW (window)->prev, NILP (tem))
956 if (tem = XWINDOW (window)->parent, !NILP (tem))
957 window = tem;
958 else
959 {
960 /* We have found the top window on the frame.
961 Which frames are acceptable? */
962 tem = WINDOW_FRAME (XWINDOW (window));
963 #ifdef MULTI_FRAME
964 if (! NILP (all_frames))
965 /* It's actually important that we use prev_frame here,
966 rather than next_frame. All the windows acceptable
967 according to the given parameters should form a ring;
968 Fnext_window and Fprevious_window should go back and
969 forth around the ring. If we use next_frame here,
970 then Fnext_window and Fprevious_window take different
971 paths through the set of acceptable windows.
972 window_loop assumes that these `ring' requirement are
973 met. */
974 tem = prev_frame (tem, all_frames);
975 #endif
976 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
977
978 break;
979 }
980
981 window = tem;
982 /* If we're in a combination window, find its last child and
983 recurse on that. Otherwise, we've found the window we want. */
984 while (1)
985 {
986 if (!NILP (XWINDOW (window)->hchild))
987 window = XWINDOW (window)->hchild;
988 else if (!NILP (XWINDOW (window)->vchild))
989 window = XWINDOW (window)->vchild;
990 else break;
991 while (tem = XWINDOW (window)->next, !NILP (tem))
992 window = tem;
993 }
994 }
995 /* Which windows are acceptable?
996 Exit the loop and accept this window if
997 this isn't a minibuffer window, or
998 we're accepting minibuffer windows, or
999 we've come all the way around and we're back at the original window. */
1000 while (MINI_WINDOW_P (XWINDOW (window))
1001 && !EQ (minibuf, Qt)
1002 && !EQ (window, start_window));
1003
1004 return window;
1005 }
1006
1007 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1008 "Select the ARG'th different window on this frame.\n\
1009 All windows on current frame are arranged in a cyclic order.\n\
1010 This command selects the window ARG steps away in that order.\n\
1011 A negative ARG moves in the opposite order. If the optional second\n\
1012 argument ALL_FRAMES is non-nil, cycle through all frames.")
1013 (n, all_frames)
1014 register Lisp_Object n, all_frames;
1015 {
1016 register int i;
1017 register Lisp_Object w;
1018
1019 CHECK_NUMBER (n, 0);
1020 w = selected_window;
1021 i = XINT (n);
1022
1023 while (i > 0)
1024 {
1025 w = Fnext_window (w, Qnil, all_frames);
1026 i--;
1027 }
1028 while (i < 0)
1029 {
1030 w = Fprevious_window (w, Qnil, all_frames);
1031 i++;
1032 }
1033 Fselect_window (w);
1034 return Qnil;
1035 }
1036 \f
1037 /* Look at all windows, performing an operation specified by TYPE
1038 with argument OBJ.
1039 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
1040 frame. If FRAMES is a frame, just look at windows on that frame.
1041 If MINI is non-zero, perform the operation on minibuffer windows too.
1042 */
1043
1044 enum window_loop
1045 {
1046 WINDOW_LOOP_UNUSED,
1047 GET_BUFFER_WINDOW, /* Arg is buffer */
1048 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1049 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1050 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1051 GET_LARGEST_WINDOW,
1052 UNSHOW_BUFFER, /* Arg is buffer */
1053 };
1054
1055 static Lisp_Object
1056 window_loop (type, obj, mini, frames)
1057 enum window_loop type;
1058 register Lisp_Object obj, frames;
1059 int mini;
1060 {
1061 register Lisp_Object w;
1062 register Lisp_Object best_window;
1063 register Lisp_Object next_window;
1064 register Lisp_Object last_window;
1065 FRAME_PTR frame;
1066
1067 #ifdef MULTI_FRAME
1068 /* If we're only looping through windows on a particular frame,
1069 frame points to that frame. If we're looping through windows
1070 on all frames, frame is 0. */
1071 if (FRAMEP (frames))
1072 frame = XFRAME (frames);
1073 else if (NILP (frames))
1074 frame = selected_frame;
1075 else
1076 frame = 0;
1077 #else
1078 frame = 0;
1079 #endif
1080
1081 /* Pick a window to start with. */
1082 if (XTYPE (obj) == Lisp_Window)
1083 w = obj;
1084 else if (frame)
1085 w = FRAME_SELECTED_WINDOW (frame);
1086 else
1087 w = FRAME_SELECTED_WINDOW (selected_frame);
1088
1089 /* Figure out the last window we're going to mess with. Since
1090 Fnext_window, given the same options, is guaranteed to go in a
1091 ring, we can just use Fprevious_window to find the last one.
1092
1093 We can't just wait until we hit the first window again, because
1094 it might be deleted. */
1095
1096 #ifdef MULTI_FRAME
1097 if (frame)
1098 last_window = Fprevious_window (w, (mini ? Qt : Qnil), Qlambda);
1099 else
1100 #endif /* MULTI_FRAME */
1101 /* We know frame is 0, so we're looping through all frames.
1102 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1103 last_window = Fprevious_window (w, mini ? Qt : Qnil, Qt);
1104
1105 best_window = Qnil;
1106 for (;;)
1107 {
1108 /* Pick the next window now, since some operations will delete
1109 the current window. */
1110 #ifdef MULTI_FRAME
1111 if (frame)
1112 next_window = Fnext_window (w, (mini ? Qt : Qnil), Qlambda);
1113 else
1114 #endif /* MULTI_FRAME */
1115 /* We know frame is 0, so we're looping through all frames.
1116 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1117 next_window = Fnext_window (w, mini ? Qt : Qnil, Qt);
1118
1119 if (!MINI_WINDOW_P (XWINDOW (w))
1120 || (mini && minibuf_level > 0))
1121 switch (type)
1122 {
1123 case GET_BUFFER_WINDOW:
1124 #if 0
1125 /* Ignore invisible and iconified frames. */
1126 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1127 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1128 break;
1129 #endif
1130 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1131 return w;
1132 break;
1133
1134 case GET_LRU_WINDOW:
1135 /* t as arg means consider only full-width windows */
1136 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
1137 != FRAME_WIDTH (frame))
1138 break;
1139 #if 0
1140 /* Ignore invisible and iconified frames. */
1141 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1142 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1143 break;
1144 #endif
1145 /* Ignore dedicated windows and minibuffers. */
1146 if (MINI_WINDOW_P (XWINDOW (w))
1147 || !NILP (XWINDOW (w)->dedicated))
1148 break;
1149 if (NILP (best_window)
1150 || (XFASTINT (XWINDOW (best_window)->use_time)
1151 > XFASTINT (XWINDOW (w)->use_time)))
1152 best_window = w;
1153 break;
1154
1155 case DELETE_OTHER_WINDOWS:
1156 if (XWINDOW (w) != XWINDOW (obj))
1157 Fdelete_window (w);
1158 break;
1159
1160 case DELETE_BUFFER_WINDOWS:
1161 if (EQ (XWINDOW (w)->buffer, obj))
1162 {
1163 /* If we're deleting the buffer displayed in the only window
1164 on the frame, find a new buffer to display there. */
1165 if (NILP (XWINDOW (w)->parent))
1166 {
1167 Lisp_Object new_buffer = Fother_buffer (obj, Qnil);
1168 if (NILP (new_buffer))
1169 new_buffer
1170 = Fget_buffer_create (build_string ("*scratch*"));
1171 Fset_window_buffer (w, new_buffer);
1172 Fset_buffer (XWINDOW (w)->buffer);
1173 }
1174 else
1175 Fdelete_window (w);
1176 }
1177 break;
1178
1179 case GET_LARGEST_WINDOW:
1180 #if 0
1181 /* Ignore invisible and iconified frames. */
1182 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1183 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1184 break;
1185 #endif
1186 /* Ignore dedicated windows and minibuffers. */
1187 if (MINI_WINDOW_P (XWINDOW (w))
1188 || !NILP (XWINDOW (w)->dedicated))
1189 break;
1190 {
1191 struct window *best_window_ptr = XWINDOW (best_window);
1192 struct window *w_ptr = XWINDOW (w);
1193 if (NILP (best_window) ||
1194 (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width))
1195 > (XFASTINT (best_window_ptr->height)
1196 * XFASTINT (best_window_ptr->width)))
1197 best_window = w;
1198 }
1199 break;
1200
1201 case UNSHOW_BUFFER:
1202 if (EQ (XWINDOW (w)->buffer, obj))
1203 {
1204 /* Find another buffer to show in this window. */
1205 Lisp_Object another_buffer = Fother_buffer (obj, Qnil);
1206 if (NILP (another_buffer))
1207 another_buffer
1208 = Fget_buffer_create (build_string ("*scratch*"));
1209 Fset_window_buffer (w, another_buffer);
1210 if (EQ (w, selected_window))
1211 Fset_buffer (XWINDOW (w)->buffer);
1212 }
1213 break;
1214 }
1215
1216 if (EQ (w, last_window))
1217 break;
1218
1219 w = next_window;
1220 }
1221
1222 return best_window;
1223 }
1224
1225 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1226 "Return the window least recently selected or used for display.\n\
1227 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1228 frame, search only that frame.\n")
1229 (frames)
1230 Lisp_Object frames;
1231 {
1232 register Lisp_Object w;
1233 /* First try for a window that is full-width */
1234 w = window_loop (GET_LRU_WINDOW, Qt, 0, frames);
1235 if (!NILP (w) && !EQ (w, selected_window))
1236 return w;
1237 /* If none of them, try the rest */
1238 return window_loop (GET_LRU_WINDOW, Qnil, 0, frames);
1239 }
1240
1241 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1242 "Return the largest window in area.\n\
1243 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1244 frame, search only that frame.\n")
1245 (frame)
1246 Lisp_Object frame;
1247 {
1248 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1249 frame);
1250 }
1251
1252 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1253 "Return a window currently displaying BUFFER, or nil if none.\n\
1254 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1255 frame, search only that frame.\n")
1256 (buffer, frame)
1257 Lisp_Object buffer, frame;
1258 {
1259 buffer = Fget_buffer (buffer);
1260 if (XTYPE (buffer) == Lisp_Buffer)
1261 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1262 else
1263 return Qnil;
1264 }
1265
1266 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1267 0, 1, "",
1268 "Make WINDOW (or the selected window) fill its frame.\n\
1269 Only the frame WINDOW is on is affected.")
1270 (window)
1271 Lisp_Object window;
1272 {
1273 struct window *w;
1274 int opoint = point;
1275 struct buffer *obuf = current_buffer;
1276 int top;
1277
1278 if (NILP (window))
1279 window = selected_window;
1280 else
1281 CHECK_LIVE_WINDOW (window, 0);
1282
1283 w = XWINDOW (window);
1284 top = XFASTINT (w->top);
1285
1286 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1287
1288 Fset_buffer (w->buffer);
1289 SET_PT (marker_position (w->start));
1290 Frecenter (make_number (top - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)))));
1291
1292 set_buffer_internal (obuf);
1293 SET_PT (opoint);
1294 return Qnil;
1295 }
1296
1297 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1298 1, 1, "bDelete windows on (buffer): ",
1299 "Delete all windows showing BUFFER.")
1300 (buffer)
1301 Lisp_Object buffer;
1302 {
1303 if (!NILP (buffer))
1304 {
1305 buffer = Fget_buffer (buffer);
1306 CHECK_BUFFER (buffer, 0);
1307 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, Qt);
1308 }
1309 return Qnil;
1310 }
1311
1312 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1313 Sreplace_buffer_in_windows,
1314 1, 1, "bReplace buffer in windows: ",
1315 "Replace BUFFER with some other buffer in all windows showing it.")
1316 (buffer)
1317 Lisp_Object buffer;
1318 {
1319 if (!NILP (buffer))
1320 {
1321 buffer = Fget_buffer (buffer);
1322 CHECK_BUFFER (buffer, 0);
1323 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1324 }
1325 return Qnil;
1326 }
1327 \f
1328 /* Set the height of WINDOW and all its inferiors. */
1329
1330 /* The smallest acceptable dimensions for a window. Anything smaller
1331 might crash Emacs. */
1332 #define MIN_SAFE_WINDOW_WIDTH (2)
1333 #define MIN_SAFE_WINDOW_HEIGHT (2)
1334
1335 /* Make sure that window_min_height and window_min_width are
1336 not too small; if they are, set them to safe minima. */
1337
1338 static void
1339 check_min_window_sizes ()
1340 {
1341 /* Smaller values might permit a crash. */
1342 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1343 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1344 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1345 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1346 }
1347
1348 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1349 minimum allowable size. */
1350 void
1351 check_frame_size (frame, rows, cols)
1352 FRAME_PTR frame;
1353 int *rows, *cols;
1354 {
1355 /* For height, we have to see whether the frame has a minibuffer, and
1356 whether it wants a mode line. */
1357 int min_height =
1358 ((FRAME_MINIBUF_ONLY_P (frame)
1359 || ! FRAME_HAS_MINIBUF_P (frame))
1360 ? MIN_SAFE_WINDOW_HEIGHT
1361 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1362
1363 if (*rows < min_height)
1364 *rows = min_height;
1365 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1366 *cols = MIN_SAFE_WINDOW_WIDTH;
1367 }
1368
1369 /* Normally the window is deleted if it gets too small.
1370 nodelete nonzero means do not do this.
1371 (The caller should check later and do so if appropriate) */
1372
1373 set_window_height (window, height, nodelete)
1374 Lisp_Object window;
1375 int height;
1376 int nodelete;
1377 {
1378 register struct window *w = XWINDOW (window);
1379 register struct window *c;
1380 int oheight = XFASTINT (w->height);
1381 int top, pos, lastbot, opos, lastobot;
1382 Lisp_Object child;
1383
1384 check_min_window_sizes ();
1385
1386 if (!nodelete
1387 && ! NILP (w->parent)
1388 && height < window_min_height)
1389 {
1390 Fdelete_window (window);
1391 return;
1392 }
1393
1394 XFASTINT (w->last_modified) = 0;
1395 windows_or_buffers_changed++;
1396 XFASTINT (w->height) = height;
1397 if (!NILP (w->hchild))
1398 {
1399 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1400 {
1401 XWINDOW (child)->top = w->top;
1402 set_window_height (child, height, nodelete);
1403 }
1404 }
1405 else if (!NILP (w->vchild))
1406 {
1407 lastbot = top = XFASTINT (w->top);
1408 lastobot = 0;
1409 for (child = w->vchild; !NILP (child); child = c->next)
1410 {
1411 c = XWINDOW (child);
1412
1413 opos = lastobot + XFASTINT (c->height);
1414
1415 XFASTINT (c->top) = lastbot;
1416
1417 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1418
1419 /* Avoid confusion: inhibit deletion of child if becomes too small */
1420 set_window_height (child, pos + top - lastbot, 1);
1421
1422 /* Now advance child to next window,
1423 and set lastbot if child was not just deleted. */
1424 lastbot = pos + top;
1425 lastobot = opos;
1426 }
1427 /* Now delete any children that became too small. */
1428 if (!nodelete)
1429 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1430 {
1431 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1432 }
1433 }
1434 }
1435
1436 /* Recursively set width of WINDOW and its inferiors. */
1437
1438 set_window_width (window, width, nodelete)
1439 Lisp_Object window;
1440 int width;
1441 int nodelete;
1442 {
1443 register struct window *w = XWINDOW (window);
1444 register struct window *c;
1445 int owidth = XFASTINT (w->width);
1446 int left, pos, lastright, opos, lastoright;
1447 Lisp_Object child;
1448
1449 if (!nodelete && width < window_min_width)
1450 {
1451 Fdelete_window (window);
1452 return;
1453 }
1454
1455 XFASTINT (w->last_modified) = 0;
1456 windows_or_buffers_changed++;
1457 XFASTINT (w->width) = width;
1458 if (!NILP (w->vchild))
1459 {
1460 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1461 {
1462 XWINDOW (child)->left = w->left;
1463 set_window_width (child, width, nodelete);
1464 }
1465 }
1466 else if (!NILP (w->hchild))
1467 {
1468 lastright = left = XFASTINT (w->left);
1469 lastoright = 0;
1470 for (child = w->hchild; !NILP (child); child = c->next)
1471 {
1472 c = XWINDOW (child);
1473
1474 opos = lastoright + XFASTINT (c->width);
1475
1476 XFASTINT (c->left) = lastright;
1477
1478 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1479
1480 /* Inhibit deletion for becoming too small */
1481 set_window_width (child, pos + left - lastright, 1);
1482
1483 /* Now advance child to next window,
1484 and set lastright if child was not just deleted. */
1485 lastright = pos + left, lastoright = opos;
1486 }
1487 /* Delete children that became too small */
1488 if (!nodelete)
1489 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1490 {
1491 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1492 }
1493 }
1494 }
1495 \f
1496 int window_select_count;
1497
1498 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1499 "Make WINDOW display BUFFER as its contents.\n\
1500 BUFFER can be a buffer or buffer name.")
1501 (window, buffer)
1502 register Lisp_Object window, buffer;
1503 {
1504 register Lisp_Object tem;
1505 register struct window *w = decode_window (window);
1506
1507 buffer = Fget_buffer (buffer);
1508 CHECK_BUFFER (buffer, 1);
1509
1510 if (NILP (XBUFFER (buffer)->name))
1511 error ("Attempt to display deleted buffer");
1512
1513 tem = w->buffer;
1514 if (NILP (tem))
1515 error ("Window is deleted");
1516 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1517 is first being set up. */
1518 {
1519 if (!NILP (w->dedicated) && !EQ (tem, buffer))
1520 error ("Window is dedicated to %s\n", tem);
1521
1522 unshow_buffer (w);
1523 }
1524
1525 w->buffer = buffer;
1526 Fset_marker (w->pointm,
1527 make_number (BUF_PT (XBUFFER (buffer))),
1528 buffer);
1529 set_marker_restricted (w->start,
1530 make_number (XBUFFER (buffer)->last_window_start),
1531 buffer);
1532 w->start_at_line_beg = Qnil;
1533 XFASTINT (w->last_modified) = 0;
1534 windows_or_buffers_changed++;
1535 if (EQ (window, selected_window))
1536 Fset_buffer (buffer);
1537
1538 return Qnil;
1539 }
1540
1541 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1542 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1543 The main editor command loop selects the buffer of the selected window\n\
1544 before each command.")
1545 (window)
1546 register Lisp_Object window;
1547 {
1548 register struct window *w;
1549 register struct window *ow = XWINDOW (selected_window);
1550
1551 CHECK_LIVE_WINDOW (window, 0);
1552
1553 w = XWINDOW (window);
1554
1555 if (NILP (w->buffer))
1556 error ("Trying to select deleted window or non-leaf window");
1557
1558 XFASTINT (w->use_time) = ++window_select_count;
1559 if (EQ (window, selected_window))
1560 return window;
1561
1562 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1563 ow->buffer);
1564
1565 selected_window = window;
1566 #ifdef MULTI_FRAME
1567 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
1568 {
1569 XFRAME (WINDOW_FRAME (w))->selected_window = window;
1570 Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
1571 }
1572 else
1573 selected_frame->selected_window = window;
1574 #endif
1575
1576 record_buffer (w->buffer);
1577 Fset_buffer (w->buffer);
1578
1579 /* Go to the point recorded in the window.
1580 This is important when the buffer is in more
1581 than one window. It also matters when
1582 redisplay_window has altered point after scrolling,
1583 because it makes the change only in the window. */
1584 {
1585 register int new_point = marker_position (w->pointm);
1586 if (new_point < BEGV)
1587 SET_PT (BEGV);
1588 if (new_point > ZV)
1589 SET_PT (ZV);
1590 else
1591 SET_PT (new_point);
1592 }
1593
1594 windows_or_buffers_changed++;
1595 return window;
1596 }
1597
1598 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
1599 "BDisplay buffer:\nP",
1600 "Make BUFFER appear in some window but don't select it.\n\
1601 BUFFER can be a buffer or a buffer name.\n\
1602 If BUFFER is shown already in some window, just use that one,\n\
1603 unless the window is the selected window and the optional second\n\
1604 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
1605 Returns the window displaying BUFFER.")
1606 (buffer, not_this_window)
1607 register Lisp_Object buffer, not_this_window;
1608 {
1609 register Lisp_Object window;
1610
1611 buffer = Fget_buffer (buffer);
1612 CHECK_BUFFER (buffer, 0);
1613
1614 if (!NILP (Vdisplay_buffer_function))
1615 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1616
1617 if (NILP (not_this_window)
1618 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1619 return selected_window;
1620
1621 window = Fget_buffer_window (buffer, Qnil);
1622 if (!NILP (window)
1623 && (NILP (not_this_window) || !EQ (window, selected_window)))
1624 return window;
1625
1626 #ifdef MULTI_FRAME
1627 /* If there are no frames open that have more than a minibuffer,
1628 we need to create a new frame. */
1629 if (pop_up_frames || last_nonminibuf_frame == 0)
1630 {
1631 window
1632 = Fframe_selected_window (call0 (Vpop_up_frame_function));
1633 Fset_window_buffer (window, buffer);
1634 #if 0
1635 Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
1636 #endif
1637 return window;
1638 }
1639 #endif /* MULTI_FRAME */
1640
1641 if (pop_up_windows
1642 #ifdef MULTI_FRAME
1643 || FRAME_MINIBUF_ONLY_P (selected_frame)
1644 #endif
1645 )
1646 {
1647 Lisp_Object frames = Qnil;
1648
1649 #ifdef MULTI_FRAME
1650 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1651 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
1652 #endif
1653 /* Don't try to create a window if would get an error */
1654 if (split_height_threshold < window_min_height << 1)
1655 split_height_threshold = window_min_height << 1;
1656
1657 window = Fget_largest_window (frames);
1658
1659 if (!NILP (window)
1660 && window_height (window) >= split_height_threshold
1661 && (XFASTINT (XWINDOW (window)->width)
1662 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
1663 window = Fsplit_window (window, Qnil, Qnil);
1664 else
1665 {
1666 window = Fget_lru_window (frames);
1667 if ((EQ (window, selected_window)
1668 || EQ (XWINDOW (window)->parent, Qnil))
1669 && window_height (window) >= window_min_height << 1)
1670 window = Fsplit_window (window, Qnil, Qnil);
1671 }
1672 }
1673 else
1674 window = Fget_lru_window (Qnil);
1675
1676 Fset_window_buffer (window, buffer);
1677 return window;
1678 }
1679
1680 void
1681 temp_output_buffer_show (buf)
1682 register Lisp_Object buf;
1683 {
1684 register struct buffer *old = current_buffer;
1685 register Lisp_Object window;
1686 register struct window *w;
1687
1688 Fset_buffer (buf);
1689 XBUFFER (buf)->save_modified = MODIFF;
1690 BEGV = BEG;
1691 ZV = Z;
1692 SET_PT (BEG);
1693 clip_changed = 1;
1694 set_buffer_internal (old);
1695
1696 if (!EQ (Vtemp_buffer_show_function, Qnil))
1697 call1 (Vtemp_buffer_show_function, buf);
1698 else
1699 {
1700 window = Fdisplay_buffer (buf, Qnil);
1701
1702 #ifdef MULTI_FRAME
1703 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1704 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1705 #endif /* MULTI_FRAME */
1706 Vminibuf_scroll_window = window;
1707 w = XWINDOW (window);
1708 XFASTINT (w->hscroll) = 0;
1709 set_marker_restricted (w->start, make_number (1), buf);
1710 set_marker_restricted (w->pointm, make_number (1), buf);
1711 }
1712 }
1713 \f
1714 static
1715 make_dummy_parent (window)
1716 Lisp_Object window;
1717 {
1718 register Lisp_Object old, new;
1719 register struct window *o, *p;
1720
1721 old = window;
1722 XSETTYPE (old, Lisp_Vector);
1723 new = Fcopy_sequence (old);
1724 XSETTYPE (new, Lisp_Window);
1725
1726 o = XWINDOW (old);
1727 p = XWINDOW (new);
1728 XFASTINT (p->sequence_number) = ++sequence_number;
1729
1730 /* Put new into window structure in place of window */
1731 replace_window (window, new);
1732
1733 o->next = Qnil;
1734 o->prev = Qnil;
1735 o->vchild = Qnil;
1736 o->hchild = Qnil;
1737 o->parent = new;
1738
1739 p->start = Qnil;
1740 p->pointm = Qnil;
1741 p->buffer = Qnil;
1742 }
1743
1744 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1745 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1746 WINDOW defaults to selected one and SIZE to half its size.\n\
1747 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1748 and put SIZE columns in the first of the pair.")
1749 (window, chsize, horflag)
1750 Lisp_Object window, chsize, horflag;
1751 {
1752 register Lisp_Object new;
1753 register struct window *o, *p;
1754 register int size;
1755
1756 if (NILP (window))
1757 window = selected_window;
1758 else
1759 CHECK_LIVE_WINDOW (window, 0);
1760
1761 o = XWINDOW (window);
1762
1763 if (NILP (chsize))
1764 {
1765 if (!NILP (horflag))
1766 /* Round odd size up, since this is for the left-hand window,
1767 and it will lose a column for the separators. */
1768 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1769 else
1770 size = XFASTINT (o->height) >> 1;
1771 }
1772 else
1773 {
1774 CHECK_NUMBER (chsize, 1);
1775 size = XINT (chsize);
1776 }
1777
1778 if (MINI_WINDOW_P (o))
1779 error ("Attempt to split minibuffer window");
1780 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1781 error ("Attempt to split unsplittable frame");
1782
1783 check_min_window_sizes ();
1784
1785 if (NILP (horflag))
1786 {
1787 if (size < window_min_height
1788 || size + window_min_height > XFASTINT (o->height))
1789 args_out_of_range_3 (window, chsize, horflag);
1790 if (NILP (o->parent)
1791 || NILP (XWINDOW (o->parent)->vchild))
1792 {
1793 make_dummy_parent (window);
1794 new = o->parent;
1795 XWINDOW (new)->vchild = window;
1796 }
1797 }
1798 else
1799 {
1800 if (size < window_min_width
1801 || size + window_min_width > XFASTINT (o->width))
1802 args_out_of_range_3 (window, chsize, horflag);
1803 if (NILP (o->parent)
1804 || NILP (XWINDOW (o->parent)->hchild))
1805 {
1806 make_dummy_parent (window);
1807 new = o->parent;
1808 XWINDOW (new)->hchild = window;
1809 }
1810 }
1811
1812 /* Now we know that window's parent is a vertical combination
1813 if we are dividing vertically, or a horizontal combination
1814 if we are making side-by-side windows */
1815
1816 windows_or_buffers_changed++;
1817 new = make_window ();
1818 p = XWINDOW (new);
1819
1820 p->frame = o->frame;
1821 p->next = o->next;
1822 if (!NILP (p->next))
1823 XWINDOW (p->next)->prev = new;
1824 p->prev = window;
1825 o->next = new;
1826 p->parent = o->parent;
1827 p->buffer = Qt;
1828
1829 Fset_window_buffer (new, o->buffer);
1830
1831 /* Apportion the available frame space among the two new windows */
1832
1833 if (!NILP (horflag))
1834 {
1835 p->height = o->height;
1836 p->top = o->top;
1837 XFASTINT (p->width) = XFASTINT (o->width) - size;
1838 XFASTINT (o->width) = size;
1839 XFASTINT (p->left) = XFASTINT (o->left) + size;
1840 }
1841 else
1842 {
1843 p->left = o->left;
1844 p->width = o->width;
1845 XFASTINT (p->height) = XFASTINT (o->height) - size;
1846 XFASTINT (o->height) = size;
1847 XFASTINT (p->top) = XFASTINT (o->top) + size;
1848 }
1849
1850 return new;
1851 }
1852 \f
1853 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1854 "Make current window ARG lines bigger.\n\
1855 From program, optional second arg non-nil means grow sideways ARG columns.")
1856 (n, side)
1857 register Lisp_Object n, side;
1858 {
1859 CHECK_NUMBER (n, 0);
1860 change_window_height (XINT (n), !NILP (side));
1861 return Qnil;
1862 }
1863
1864 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1865 "Make current window ARG lines smaller.\n\
1866 From program, optional second arg non-nil means shrink sideways ARG columns.")
1867 (n, side)
1868 register Lisp_Object n, side;
1869 {
1870 CHECK_NUMBER (n, 0);
1871 change_window_height (-XINT (n), !NILP (side));
1872 return Qnil;
1873 }
1874
1875 int
1876 window_height (window)
1877 Lisp_Object window;
1878 {
1879 register struct window *p = XWINDOW (window);
1880 return XFASTINT (p->height);
1881 }
1882
1883 int
1884 window_width (window)
1885 Lisp_Object window;
1886 {
1887 register struct window *p = XWINDOW (window);
1888 return XFASTINT (p->width);
1889 }
1890
1891 #define MINSIZE(w) \
1892 (widthflag \
1893 ? window_min_width \
1894 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
1895
1896 #define CURBEG(w) \
1897 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
1898
1899 #define CURSIZE(w) \
1900 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
1901
1902 /* Unlike set_window_height, this function
1903 also changes the heights of the siblings so as to
1904 keep everything consistent. */
1905
1906 change_window_height (delta, widthflag)
1907 register int delta;
1908 int widthflag;
1909 {
1910 register Lisp_Object parent;
1911 Lisp_Object window;
1912 register struct window *p;
1913 int *sizep;
1914 int (*sizefun) () = widthflag ? window_width : window_height;
1915 register int (*setsizefun) () = (widthflag
1916 ? set_window_width
1917 : set_window_height);
1918
1919 check_min_window_sizes ();
1920
1921 window = selected_window;
1922 while (1)
1923 {
1924 p = XWINDOW (window);
1925 parent = p->parent;
1926 if (NILP (parent))
1927 {
1928 if (widthflag)
1929 error ("No other window to side of this one");
1930 break;
1931 }
1932 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
1933 : !NILP (XWINDOW (parent)->vchild))
1934 break;
1935 window = parent;
1936 }
1937
1938 sizep = &CURSIZE (window);
1939
1940 if (*sizep + delta < MINSIZE (window))
1941 {
1942 Fdelete_window (window);
1943 return;
1944 }
1945
1946 {
1947 register int maxdelta;
1948
1949 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
1950 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
1951 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
1952 /* This is a frame with only one window, a minibuffer-only
1953 or a minibufferless frame. */
1954 : (delta = 0));
1955
1956 if (delta > maxdelta)
1957 /* This case traps trying to make the minibuffer
1958 the full frame, or make the only window aside from the
1959 minibuffer the full frame. */
1960 delta = maxdelta;
1961
1962 if (delta == 0)
1963 return;
1964 }
1965
1966 if (!NILP (p->next) &&
1967 (*sizefun) (p->next) - delta >= MINSIZE (p->next))
1968 {
1969 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
1970 (*setsizefun) (window, *sizep + delta, 0);
1971 CURBEG (p->next) += delta;
1972 /* This does not change size of p->next,
1973 but it propagates the new top edge to its children */
1974 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
1975 }
1976 else if (!NILP (p->prev) &&
1977 (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
1978 {
1979 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
1980 CURBEG (window) -= delta;
1981 (*setsizefun) (window, *sizep + delta, 0);
1982 }
1983 else
1984 {
1985 register int delta1;
1986 register int opht = (*sizefun) (parent);
1987
1988 /* If trying to grow this window to or beyond size of the parent,
1989 make delta1 so big that, on shrinking back down,
1990 all the siblings end up with less than one line and are deleted. */
1991 if (opht <= *sizep + delta)
1992 delta1 = opht * opht * 2;
1993 /* Otherwise, make delta1 just right so that if we add delta1
1994 lines to this window and to the parent, and then shrink
1995 the parent back to its original size, the new proportional
1996 size of this window will increase by delta. */
1997 else
1998 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
1999
2000 /* Add delta1 lines or columns to this window, and to the parent,
2001 keeping things consistent while not affecting siblings. */
2002 CURSIZE (parent) = opht + delta1;
2003 (*setsizefun) (window, *sizep + delta1, 0);
2004
2005 /* Squeeze out delta1 lines or columns from our parent,
2006 shriking this window and siblings proportionately.
2007 This brings parent back to correct size.
2008 Delta1 was calculated so this makes this window the desired size,
2009 taking it all out of the siblings. */
2010 (*setsizefun) (parent, opht, 0);
2011 }
2012
2013 XFASTINT (p->last_modified) = 0;
2014 }
2015 #undef MINSIZE
2016 #undef CURBEG
2017 #undef CURSIZE
2018
2019 \f
2020 /* Return number of lines of text (not counting mode line) in W. */
2021
2022 int
2023 window_internal_height (w)
2024 struct window *w;
2025 {
2026 int ht = XFASTINT (w->height);
2027
2028 if (MINI_WINDOW_P (w))
2029 return ht;
2030
2031 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2032 || !NILP (w->next) || !NILP (w->prev)
2033 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
2034 return ht - 1;
2035
2036 return ht;
2037 }
2038
2039
2040 /* Return the number of columns in W.
2041 Don't count columns occupied by scroll bars or the vertical bar
2042 separating W from the sibling to its right. */
2043 int
2044 window_internal_width (w)
2045 struct window *w;
2046 {
2047 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2048 int left = XINT (w->left);
2049 int width = XINT (w->width);
2050
2051 /* If this window is flush against the right edge of the frame, its
2052 internal width is its full width. */
2053 if (left + width >= FRAME_WIDTH (f))
2054 return width;
2055
2056 /* If we are not flush right, then our rightmost columns are
2057 occupied by some sort of separator. */
2058
2059 /* Scroll bars occupy a few columns. */
2060 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2061 return width - VERTICAL_SCROLL_BAR_WIDTH;
2062
2063 /* The column of `|' characters separating side-by-side windows
2064 occupies one column only. */
2065 return width - 1;
2066 }
2067
2068
2069 /* Scroll contents of window WINDOW up N lines. */
2070
2071 void
2072 window_scroll (window, n, noerror)
2073 Lisp_Object window;
2074 int n;
2075 int noerror;
2076 {
2077 register struct window *w = XWINDOW (window);
2078 register int opoint = point;
2079 register int pos;
2080 register int ht = window_internal_height (w);
2081 register Lisp_Object tem;
2082 int lose;
2083 Lisp_Object bolp, nmoved;
2084
2085 XFASTINT (tem) = point;
2086 tem = Fpos_visible_in_window_p (tem, window);
2087
2088 if (NILP (tem))
2089 {
2090 Fvertical_motion (make_number (- ht / 2));
2091 XFASTINT (tem) = point;
2092 Fset_marker (w->start, tem, w->buffer);
2093 w->force_start = Qt;
2094 }
2095
2096 SET_PT (marker_position (w->start));
2097 lose = n < 0 && point == BEGV;
2098 Fvertical_motion (make_number (n));
2099 pos = point;
2100 bolp = Fbolp ();
2101 SET_PT (opoint);
2102
2103 if (lose)
2104 {
2105 if (noerror)
2106 return;
2107 else
2108 Fsignal (Qbeginning_of_buffer, Qnil);
2109 }
2110
2111 if (pos < ZV)
2112 {
2113 set_marker_restricted (w->start, make_number (pos), w->buffer);
2114 w->start_at_line_beg = bolp;
2115 w->update_mode_line = Qt;
2116 XFASTINT (w->last_modified) = 0;
2117 if (pos > opoint)
2118 SET_PT (pos);
2119 if (n < 0)
2120 {
2121 SET_PT (pos);
2122 tem = Fvertical_motion (make_number (ht));
2123 if (point > opoint || XFASTINT (tem) < ht)
2124 SET_PT (opoint);
2125 else
2126 Fvertical_motion (make_number (-1));
2127 }
2128 }
2129 else
2130 {
2131 if (noerror)
2132 return;
2133 else
2134 Fsignal (Qend_of_buffer, Qnil);
2135 }
2136 }
2137 \f
2138 /* This is the guts of Fscroll_up and Fscroll_down. */
2139
2140 static void
2141 scroll_command (n, direction)
2142 register Lisp_Object n;
2143 int direction;
2144 {
2145 register int defalt;
2146 int count = specpdl_ptr - specpdl;
2147
2148 /* If selected window's buffer isn't current, make it current for the moment.
2149 But don't screw up if window_scroll gets an error. */
2150 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2151 {
2152 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2153 Fset_buffer (XWINDOW (selected_window)->buffer);
2154 }
2155
2156 defalt = (window_internal_height (XWINDOW (selected_window))
2157 - next_screen_context_lines);
2158 defalt = direction * (defalt < 1 ? 1 : defalt);
2159
2160 if (NILP (n))
2161 window_scroll (selected_window, defalt, 0);
2162 else if (EQ (n, Qminus))
2163 window_scroll (selected_window, - defalt, 0);
2164 else
2165 {
2166 n = Fprefix_numeric_value (n);
2167 window_scroll (selected_window, XINT (n) * direction, 0);
2168 }
2169
2170 unbind_to (count, Qnil);
2171 }
2172
2173 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2174 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2175 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2176 When calling from a program, supply a number as argument or nil.")
2177 (n)
2178 Lisp_Object n;
2179 {
2180 scroll_command (n, 1);
2181 return Qnil;
2182 }
2183
2184 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2185 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2186 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2187 When calling from a program, supply a number as argument or nil.")
2188 (n)
2189 Lisp_Object n;
2190 {
2191 scroll_command (n, -1);
2192 return Qnil;
2193 }
2194
2195 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2196 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2197 The next window is the one below the current one; or the one at the top\n\
2198 if the current one is at the bottom.\n\
2199 When calling from a program, supply a number as argument or nil.\n\
2200 \n\
2201 If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2202 specifies the window to scroll.\n\
2203 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2204 showing that buffer, popping the buffer up if necessary.")
2205 (n)
2206 register Lisp_Object n;
2207 {
2208 register Lisp_Object window;
2209 register int ht;
2210 register struct window *w;
2211 register int count = specpdl_ptr - specpdl;
2212
2213 if (MINI_WINDOW_P (XWINDOW (selected_window))
2214 && !NILP (Vminibuf_scroll_window))
2215 window = Vminibuf_scroll_window;
2216 /* If buffer is specified, scroll that buffer. */
2217 else if (!NILP (Vother_window_scroll_buffer))
2218 {
2219 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
2220 if (NILP (window))
2221 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2222 }
2223 else
2224 {
2225 /* Nothing specified; look for a neighboring window on the same
2226 frame. */
2227 window = Fnext_window (selected_window, Qnil, Qnil);
2228
2229 if (EQ (window, selected_window))
2230 /* That didn't get us anywhere; look for a window on another
2231 visible frame. */
2232 do
2233 window = Fnext_window (window, Qnil, Qt);
2234 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2235 && ! EQ (window, selected_window));
2236 }
2237
2238 CHECK_LIVE_WINDOW (window, 0);
2239
2240 if (EQ (window, selected_window))
2241 error ("There is no other window");
2242
2243 w = XWINDOW (window);
2244 ht = window_internal_height (w);
2245
2246 /* Don't screw up if window_scroll gets an error. */
2247 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2248
2249 Fset_buffer (w->buffer);
2250 SET_PT (marker_position (w->pointm));
2251
2252 if (NILP (n))
2253 window_scroll (window, ht - next_screen_context_lines, 1);
2254 else if (EQ (n, Qminus))
2255 window_scroll (window, next_screen_context_lines - ht, 1);
2256 else
2257 {
2258 if (XTYPE (n) == Lisp_Cons)
2259 n = Fcar (n);
2260 CHECK_NUMBER (n, 0);
2261 window_scroll (window, XINT (n), 1);
2262 }
2263
2264 Fset_marker (w->pointm, make_number (point), Qnil);
2265 unbind_to (count, Qnil);
2266
2267 return Qnil;
2268 }
2269 \f
2270 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
2271 "Scroll selected window display ARG columns left.\n\
2272 Default for ARG is window width minus 2.")
2273 (arg)
2274 register Lisp_Object arg;
2275 {
2276
2277 if (NILP (arg))
2278 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
2279 else
2280 arg = Fprefix_numeric_value (arg);
2281
2282 return
2283 Fset_window_hscroll (selected_window,
2284 make_number (XINT (XWINDOW (selected_window)->hscroll)
2285 + XINT (arg)));
2286 }
2287
2288 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
2289 "Scroll selected window display ARG columns right.\n\
2290 Default for ARG is window width minus 2.")
2291 (arg)
2292 register Lisp_Object arg;
2293 {
2294 if (NILP (arg))
2295 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
2296 else
2297 arg = Fprefix_numeric_value (arg);
2298
2299 return
2300 Fset_window_hscroll (selected_window,
2301 make_number (XINT (XWINDOW (selected_window)->hscroll)
2302 - XINT (arg)));
2303 }
2304
2305 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
2306 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2307 The desired position of point is always relative to the current window.\n\
2308 Just C-u as prefix means put point in the center of the window.\n\
2309 No arg (i.e., it is nil) erases the entire frame and then\n\
2310 redraws with point in the center of the current window.")
2311 (n)
2312 register Lisp_Object n;
2313 {
2314 register struct window *w = XWINDOW (selected_window);
2315 register int ht = window_internal_height (w);
2316 register int opoint = point;
2317
2318 if (NILP (n))
2319 {
2320 extern int frame_garbaged;
2321
2322 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
2323 XFASTINT (n) = ht / 2;
2324 }
2325 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2326 {
2327 XFASTINT (n) = ht / 2;
2328 }
2329 else
2330 {
2331 n = Fprefix_numeric_value (n);
2332 CHECK_NUMBER (n, 0);
2333 }
2334
2335 if (XINT (n) < 0)
2336 XSETINT (n, XINT (n) + ht);
2337
2338 XSETINT (n, - XINT (n));
2339
2340 Fvertical_motion (n);
2341 Fset_marker (w->start, make_number (point), w->buffer);
2342 w->start_at_line_beg = Fbolp ();
2343
2344 SET_PT (opoint);
2345 w->force_start = Qt;
2346
2347 return Qnil;
2348 }
2349 \f
2350 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2351 1, 1, "P",
2352 "Position point relative to window.\n\
2353 With no argument, position text at center of window.\n\
2354 An argument specifies frame line; zero means top of window,\n\
2355 negative means relative to bottom of window.")
2356 (arg)
2357 register Lisp_Object arg;
2358 {
2359 register struct window *w = XWINDOW (selected_window);
2360 register int height = window_internal_height (w);
2361 register int start;
2362
2363 if (NILP (arg))
2364 XFASTINT (arg) = height / 2;
2365 else
2366 {
2367 arg = Fprefix_numeric_value (arg);
2368 if (XINT (arg) < 0)
2369 XSETINT (arg, XINT (arg) + height);
2370 }
2371
2372 start = marker_position (w->start);
2373 if (start < BEGV || start > ZV)
2374 {
2375 Fvertical_motion (make_number (- height / 2));
2376 Fset_marker (w->start, make_number (point), w->buffer);
2377 w->start_at_line_beg = Fbolp ();
2378 w->force_start = Qt;
2379 }
2380 else
2381 SET_PT (start);
2382
2383 return Fvertical_motion (arg);
2384 }
2385 \f
2386 struct save_window_data
2387 {
2388 int size_from_Lisp_Vector_struct;
2389 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2390 Lisp_Object frame_width, frame_height;
2391 Lisp_Object selected_frame;
2392 Lisp_Object current_window;
2393 Lisp_Object current_buffer;
2394 Lisp_Object minibuf_scroll_window;
2395 Lisp_Object root_window;
2396 Lisp_Object focus_frame;
2397 /* A vector, interpreted as a struct saved_window */
2398 Lisp_Object saved_windows;
2399 };
2400
2401 /* Arg to Fmake_vector */
2402 #define SAVE_WINDOW_DATA_SIZE \
2403 ((sizeof (struct save_window_data) \
2404 - (sizeof (struct Lisp_Vector) \
2405 /* Don't count the contents member of the struct Lisp_Vector */ \
2406 - sizeof (Lisp_Object))) \
2407 / sizeof (Lisp_Object))
2408
2409 /* This is saved as a Lisp_Vector */
2410 struct saved_window
2411 {
2412 /* these first two must agree with struct Lisp_Vector in lisp.h */
2413 int size_from_Lisp_Vector_struct;
2414 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2415
2416 Lisp_Object window;
2417 Lisp_Object buffer, start, pointm, mark;
2418 Lisp_Object left, top, width, height, hscroll;
2419 Lisp_Object parent, prev;
2420 Lisp_Object start_at_line_beg;
2421 Lisp_Object display_table;
2422 };
2423 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2424
2425 #define SAVED_WINDOW_N(swv,n) \
2426 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2427
2428 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2429 "T if OBJECT is a window-configration object.")
2430 (obj)
2431 Lisp_Object obj;
2432 {
2433 if (XTYPE (obj) == Lisp_Window_Configuration)
2434 return Qt;
2435 return Qnil;
2436 }
2437
2438
2439 DEFUN ("set-window-configuration", Fset_window_configuration,
2440 Sset_window_configuration, 1, 1, 0,
2441 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2442 CONFIGURATION must be a value previously returned\n\
2443 by `current-window-configuration' (which see).")
2444 (configuration)
2445 Lisp_Object configuration;
2446 {
2447 register struct save_window_data *data;
2448 struct Lisp_Vector *saved_windows;
2449 Lisp_Object new_current_buffer;
2450 Lisp_Object frame;
2451 FRAME_PTR f;
2452
2453 while (XTYPE (configuration) != Lisp_Window_Configuration)
2454 {
2455 configuration = wrong_type_argument (intern ("window-configuration-p"),
2456 configuration);
2457 }
2458
2459 data = (struct save_window_data *) XVECTOR (configuration);
2460 saved_windows = XVECTOR (data->saved_windows);
2461
2462 new_current_buffer = data->current_buffer;
2463 if (NILP (XBUFFER (new_current_buffer)->name))
2464 new_current_buffer = Qnil;
2465
2466 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2467 f = XFRAME (frame);
2468
2469 /* If f is a dead frame, don't bother rebuilding its window tree.
2470 However, there is other stuff we should still try to do below. */
2471 if (FRAME_LIVE_P (f))
2472 {
2473 register struct window *w;
2474 register struct saved_window *p;
2475 int k;
2476
2477 /* If the frame has been resized since this window configuration was
2478 made, we change the frame to the size specified in the
2479 configuration, restore the configuration, and then resize it
2480 back. We keep track of the prevailing height in these variables. */
2481 int previous_frame_height = FRAME_HEIGHT (f);
2482 int previous_frame_width = FRAME_WIDTH (f);
2483
2484 if (XFASTINT (data->frame_height) != previous_frame_height
2485 || XFASTINT (data->frame_width) != previous_frame_width)
2486 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
2487
2488 windows_or_buffers_changed++;
2489
2490 /* Kludge Alert!
2491 Mark all windows now on frame as "deleted".
2492 Restoring the new configuration "undeletes" any that are in it.
2493
2494 Save their current buffers in their height fields, since we may
2495 need it later, if a buffer saved in the configuration is now
2496 dead. */
2497 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2498
2499 for (k = 0; k < saved_windows->size; k++)
2500 {
2501 p = SAVED_WINDOW_N (saved_windows, k);
2502 w = XWINDOW (p->window);
2503 w->next = Qnil;
2504
2505 if (!NILP (p->parent))
2506 w->parent = SAVED_WINDOW_N (saved_windows,
2507 XFASTINT (p->parent))->window;
2508 else
2509 w->parent = Qnil;
2510
2511 if (!NILP (p->prev))
2512 {
2513 w->prev = SAVED_WINDOW_N (saved_windows,
2514 XFASTINT (p->prev))->window;
2515 XWINDOW (w->prev)->next = p->window;
2516 }
2517 else
2518 {
2519 w->prev = Qnil;
2520 if (!NILP (w->parent))
2521 {
2522 if (EQ (p->width, XWINDOW (w->parent)->width))
2523 {
2524 XWINDOW (w->parent)->vchild = p->window;
2525 XWINDOW (w->parent)->hchild = Qnil;
2526 }
2527 else
2528 {
2529 XWINDOW (w->parent)->hchild = p->window;
2530 XWINDOW (w->parent)->vchild = Qnil;
2531 }
2532 }
2533 }
2534
2535 /* If we squirreled away the buffer in the window's height,
2536 restore it now. */
2537 if (XTYPE (w->height) == Lisp_Buffer)
2538 w->buffer = w->height;
2539 w->left = p->left;
2540 w->top = p->top;
2541 w->width = p->width;
2542 w->height = p->height;
2543 w->hscroll = p->hscroll;
2544 w->display_table = p->display_table;
2545 XFASTINT (w->last_modified) = 0;
2546
2547 /* Reinstall the saved buffer and pointers into it. */
2548 if (NILP (p->buffer))
2549 w->buffer = p->buffer;
2550 else
2551 {
2552 if (!NILP (XBUFFER (p->buffer)->name))
2553 /* If saved buffer is alive, install it. */
2554 {
2555 w->buffer = p->buffer;
2556 w->start_at_line_beg = p->start_at_line_beg;
2557 set_marker_restricted (w->start,
2558 Fmarker_position (p->start),
2559 w->buffer);
2560 set_marker_restricted (w->pointm,
2561 Fmarker_position (p->pointm),
2562 w->buffer);
2563 Fset_marker (XBUFFER (w->buffer)->mark,
2564 Fmarker_position (p->mark), w->buffer);
2565
2566 /* As documented in Fcurrent_window_configuration, don't
2567 save the location of point in the buffer which was current
2568 when the window configuration was recorded. */
2569 if (!EQ (p->buffer, new_current_buffer) &&
2570 XBUFFER (p->buffer) == current_buffer)
2571 Fgoto_char (w->pointm);
2572 }
2573 else if (NILP (XBUFFER (w->buffer)->name))
2574 /* Else if window's old buffer is dead too, get a live one. */
2575 {
2576 w->buffer = Fcdr (Fcar (Vbuffer_alist));
2577 /* This will set the markers to beginning of visible
2578 range. */
2579 set_marker_restricted (w->start, make_number (0), w->buffer);
2580 set_marker_restricted (w->pointm, make_number (0),w->buffer);
2581 w->start_at_line_beg = Qt;
2582 }
2583 else
2584 /* Keeping window's old buffer; make sure the markers
2585 are real. Else if window's old buffer is dead too,
2586 get a live one. */
2587 {
2588 /* Set window markers at start of visible range. */
2589 if (XMARKER (w->start)->buffer == 0)
2590 set_marker_restricted (w->start, make_number (0),
2591 w->buffer);
2592 if (XMARKER (w->pointm)->buffer == 0)
2593 set_marker_restricted (w->pointm,
2594 (make_number
2595 (BUF_PT (XBUFFER (w->buffer)))),
2596 w->buffer);
2597 w->start_at_line_beg = Qt;
2598 }
2599 }
2600 }
2601
2602 FRAME_ROOT_WINDOW (f) = data->root_window;
2603 Fselect_window (data->current_window);
2604
2605 #ifdef MULTI_FRAME
2606 if (NILP (data->focus_frame)
2607 || (XTYPE (data->focus_frame) == Lisp_Frame
2608 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
2609 Fredirect_frame_focus (frame, data->focus_frame);
2610 #endif
2611
2612 #if 0 /* I don't understand why this is needed, and it causes problems
2613 when the frame's old selected window has been deleted. */
2614 #ifdef MULTI_FRAME
2615 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
2616 Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
2617 #endif
2618 #endif
2619
2620 /* Set the screen height to the value it had before this function. */
2621 if (previous_frame_height != FRAME_HEIGHT (f)
2622 || previous_frame_width != FRAME_WIDTH (f))
2623 change_frame_size (f, previous_frame_height, previous_frame_width,
2624 0, 0);
2625 }
2626
2627 #ifdef MULTI_FRAME
2628 /* Fselect_window will have made f the selected frame, so we
2629 reselect the proper frame here. Fhandle_switch_frame will change the
2630 selected window too, but that doesn't make the call to
2631 Fselect_window above totally superfluous; it still sets f's
2632 selected window. */
2633 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
2634 Fhandle_switch_frame (data->selected_frame, Qnil);
2635 #endif
2636
2637 if (!NILP (new_current_buffer))
2638 Fset_buffer (new_current_buffer);
2639
2640 Vminibuf_scroll_window = data->minibuf_scroll_window;
2641 return (Qnil);
2642 }
2643
2644 /* Mark all windows now on frame as deleted
2645 by setting their buffers to nil. */
2646
2647 void
2648 delete_all_subwindows (w)
2649 register struct window *w;
2650 {
2651 if (!NILP (w->next))
2652 delete_all_subwindows (XWINDOW (w->next));
2653 if (!NILP (w->vchild))
2654 delete_all_subwindows (XWINDOW (w->vchild));
2655 if (!NILP (w->hchild))
2656 delete_all_subwindows (XWINDOW (w->hchild));
2657
2658 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
2659
2660 /* We set all three of these fields to nil, to make sure that we can
2661 distinguish this dead window from any live window. Live leaf
2662 windows will have buffer set, and combination windows will have
2663 vchild or hchild set. */
2664 w->buffer = Qnil;
2665 w->vchild = Qnil;
2666 w->hchild = Qnil;
2667 }
2668 \f
2669 static int
2670 count_windows (window)
2671 register struct window *window;
2672 {
2673 register int count = 1;
2674 if (!NILP (window->next))
2675 count += count_windows (XWINDOW (window->next));
2676 if (!NILP (window->vchild))
2677 count += count_windows (XWINDOW (window->vchild));
2678 if (!NILP (window->hchild))
2679 count += count_windows (XWINDOW (window->hchild));
2680 return count;
2681 }
2682
2683 static int
2684 save_window_save (window, vector, i)
2685 Lisp_Object window;
2686 struct Lisp_Vector *vector;
2687 int i;
2688 {
2689 register struct saved_window *p;
2690 register struct window *w;
2691 register Lisp_Object tem;
2692
2693 for (;!NILP (window); window = w->next)
2694 {
2695 p = SAVED_WINDOW_N (vector, i);
2696 w = XWINDOW (window);
2697
2698 XFASTINT (w->temslot) = i++;
2699 p->window = window;
2700 p->buffer = w->buffer;
2701 p->left = w->left;
2702 p->top = w->top;
2703 p->width = w->width;
2704 p->height = w->height;
2705 p->hscroll = w->hscroll;
2706 p->display_table = w->display_table;
2707 if (!NILP (w->buffer))
2708 {
2709 /* Save w's value of point in the window configuration.
2710 If w is the selected window, then get the value of point
2711 from the buffer; pointm is garbage in the selected window. */
2712 if (EQ (window, selected_window))
2713 {
2714 p->pointm = Fmake_marker ();
2715 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
2716 w->buffer);
2717 }
2718 else
2719 p->pointm = Fcopy_marker (w->pointm);
2720
2721 p->start = Fcopy_marker (w->start);
2722 p->start_at_line_beg = w->start_at_line_beg;
2723
2724 tem = XBUFFER (w->buffer)->mark;
2725 p->mark = Fcopy_marker (tem);
2726 }
2727 else
2728 {
2729 p->pointm = Qnil;
2730 p->start = Qnil;
2731 p->mark = Qnil;
2732 p->start_at_line_beg = Qnil;
2733 }
2734
2735 if (NILP (w->parent))
2736 p->parent = Qnil;
2737 else
2738 p->parent = XWINDOW (w->parent)->temslot;
2739
2740 if (NILP (w->prev))
2741 p->prev = Qnil;
2742 else
2743 p->prev = XWINDOW (w->prev)->temslot;
2744
2745 if (!NILP (w->vchild))
2746 i = save_window_save (w->vchild, vector, i);
2747 if (!NILP (w->hchild))
2748 i = save_window_save (w->hchild, vector, i);
2749 }
2750
2751 return i;
2752 }
2753
2754 DEFUN ("current-window-configuration",
2755 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
2756 "Return an object representing the current window configuration of FRAME.\n\
2757 If FRAME is nil or omitted, use the selected frame.\n\
2758 This describes the number of windows, their sizes and current buffers,\n\
2759 and for each displayed buffer, where display starts, and the positions of\n\
2760 point and mark. An exception is made for point in the current buffer:\n\
2761 its value is -not- saved.\n\
2762 This also records the currently selected frame, and FRAME's focus\n\
2763 redirection (see `redirect-frame-focus').")
2764 (frame)
2765 Lisp_Object frame;
2766 {
2767 register Lisp_Object tem;
2768 register int n_windows;
2769 register struct save_window_data *data;
2770 register int i;
2771 FRAME_PTR f;
2772
2773 if (NILP (frame))
2774 f = selected_frame;
2775 else
2776 {
2777 CHECK_LIVE_FRAME (frame, 0);
2778 f = XFRAME (frame);
2779 }
2780
2781 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2782 data = (struct save_window_data *)
2783 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2784 Qnil));
2785 XFASTINT (data->frame_width) = FRAME_WIDTH (f);
2786 XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
2787 #ifdef MULTI_FRAME
2788 XSET (data->selected_frame, Lisp_Frame, selected_frame);
2789 #endif
2790 data->current_window = FRAME_SELECTED_WINDOW (f);
2791 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2792 data->minibuf_scroll_window = Vminibuf_scroll_window;
2793 data->root_window = FRAME_ROOT_WINDOW (f);
2794 data->focus_frame = FRAME_FOCUS_FRAME (f);
2795 tem = Fmake_vector (make_number (n_windows), Qnil);
2796 data->saved_windows = tem;
2797 for (i = 0; i < n_windows; i++)
2798 XVECTOR (tem)->contents[i]
2799 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
2800 save_window_save (FRAME_ROOT_WINDOW (f),
2801 XVECTOR (tem), 0);
2802 XSET (tem, Lisp_Window_Configuration, data);
2803 return (tem);
2804 }
2805
2806 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
2807 0, UNEVALLED, 0,
2808 "Execute body, preserving window sizes and contents.\n\
2809 Restores which buffer appears in which window, where display starts,\n\
2810 as well as the current buffer.\n\
2811 Does not restore the value of point in current buffer.")
2812 (args)
2813 Lisp_Object args;
2814 {
2815 register Lisp_Object val;
2816 register int count = specpdl_ptr - specpdl;
2817
2818 record_unwind_protect (Fset_window_configuration,
2819 Fcurrent_window_configuration (Qnil));
2820 val = Fprogn (args);
2821 return unbind_to (count, val);
2822 }
2823 \f
2824 init_window_once ()
2825 {
2826 #ifdef MULTI_FRAME
2827 selected_frame = make_terminal_frame ();
2828 minibuf_window = selected_frame->minibuffer_window;
2829 selected_window = selected_frame->selected_window;
2830 last_nonminibuf_frame = selected_frame;
2831 #else /* not MULTI_FRAME */
2832 extern Lisp_Object get_minibuffer ();
2833
2834 minibuf_window = make_window ();
2835 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
2836
2837 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
2838 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
2839 XWINDOW (minibuf_window)->mini_p = Qt;
2840
2841 /* These values 9 and 10 are arbitrary,
2842 just so that there is "something there."
2843 Correct values are put in in init_xdisp */
2844
2845 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
2846 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
2847
2848 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
2849 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
2850 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
2851
2852 /* Prevent error in Fset_window_buffer. */
2853 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
2854 XWINDOW (minibuf_window)->buffer = Qt;
2855
2856 /* Now set them up for real. */
2857 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
2858 Fcurrent_buffer ());
2859 Fset_window_buffer (minibuf_window, get_minibuffer (0));
2860
2861 selected_window = FRAME_ROOT_WINDOW (selected_frame);
2862 /* Make sure this window seems more recently used than
2863 a newly-created, never-selected window. Increment
2864 window_select_count so the first selection ever will get
2865 something newer than this. */
2866 XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
2867 #endif /* not MULTI_FRAME */
2868 }
2869
2870 syms_of_window ()
2871 {
2872 Qwindowp = intern ("windowp");
2873 staticpro (&Qwindowp);
2874
2875 Qwindow_live_p = intern ("window-live-p");
2876 staticpro (&Qwindow_live_p);
2877
2878 #ifndef MULTI_FRAME
2879 /* Make sure all windows get marked */
2880 staticpro (&minibuf_window);
2881 #endif
2882
2883 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
2884 "Non-nil means call as function to display a help buffer.\n\
2885 Used by `with-output-to-temp-buffer'.");
2886 Vtemp_buffer_show_function = Qnil;
2887
2888 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
2889 "If non-nil, function to call to handle `display-buffer'.\n\
2890 It will receive two args, the buffer and a flag which if non-nil means\n\
2891 that the currently selected window is not acceptable.\n\
2892 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2893 work using this function.");
2894 Vdisplay_buffer_function = Qnil;
2895
2896 DEFVAR_LISP ("mouse-event", &Vmouse_event,
2897 "The last mouse-event object. A list of four elements:\n\
2898 ((X-POS Y-POS) WINDOW FRAME-PART KEYSEQ).\n\
2899 KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2900 WINDOW is the window that the click applies do.\n\
2901 If FRAME-PART is non-nil, the event was on a scroll bar;\n\
2902 then Y-POS is really the total length of the scroll bar, while X-POS is\n\
2903 the relative position of the scroll bar's value within that total length.\n\
2904 FRAME-PART is one of the following symbols:\n\
2905 `vertical-scroll-bar', `vertical-slider',\n\
2906 `vertical-thumbup', `vertical-thumbdown',\n\
2907 `horizontal-scroll-bar', `horizontal-slider',\n\
2908 `horizontal-thumbleft', `horizontal-thumbright'");
2909 Vmouse_event = Qnil;
2910
2911 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
2912 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2913 Vminibuf_scroll_window = Qnil;
2914
2915 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
2916 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2917 Vother_window_scroll_buffer = Qnil;
2918
2919 #ifdef MULTI_FRAME
2920 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
2921 "*Non-nil means `display-buffer' should make a separate frame.");
2922 pop_up_frames = 0;
2923
2924 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
2925 "*If non-nil, function to call to handle automatic new frame creation.\n\
2926 It is called with no arguments and should return a newly created frame.\n\
2927 \n\
2928 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
2929 where `pop-up-frame-alist' would hold the default frame parameters.");
2930 Vpop_up_frame_function = Qnil;
2931 #endif
2932
2933 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
2934 "*Non-nil means display-buffer should make new windows.");
2935 pop_up_windows = 1;
2936
2937 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
2938 "*Number of lines of continuity when scrolling by screenfuls.");
2939 next_screen_context_lines = 2;
2940
2941 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
2942 "*display-buffer would prefer to split the largest window if this large.\n\
2943 If there is only one window, it is split regardless of this value.");
2944 split_height_threshold = 500;
2945
2946 DEFVAR_INT ("window-min-height", &window_min_height,
2947 "*Delete any window less than this tall (including its mode line).");
2948 window_min_height = 4;
2949
2950 DEFVAR_INT ("window-min-width", &window_min_width,
2951 "*Delete any window less than this wide.");
2952 window_min_width = 10;
2953
2954 defsubr (&Sselected_window);
2955 defsubr (&Sminibuffer_window);
2956 defsubr (&Swindow_minibuffer_p);
2957 defsubr (&Swindowp);
2958 defsubr (&Swindow_live_p);
2959 defsubr (&Spos_visible_in_window_p);
2960 defsubr (&Swindow_buffer);
2961 defsubr (&Swindow_height);
2962 defsubr (&Swindow_width);
2963 defsubr (&Swindow_hscroll);
2964 defsubr (&Sset_window_hscroll);
2965 defsubr (&Swindow_edges);
2966 defsubr (&Scoordinates_in_window_p);
2967 defsubr (&Swindow_at);
2968 defsubr (&Swindow_point);
2969 defsubr (&Swindow_start);
2970 defsubr (&Swindow_end);
2971 defsubr (&Sset_window_point);
2972 defsubr (&Sset_window_start);
2973 defsubr (&Swindow_dedicated_p);
2974 defsubr (&Sset_window_dedicated_p);
2975 defsubr (&Swindow_display_table);
2976 defsubr (&Sset_window_display_table);
2977 defsubr (&Snext_window);
2978 defsubr (&Sprevious_window);
2979 defsubr (&Sother_window);
2980 defsubr (&Sget_lru_window);
2981 defsubr (&Sget_largest_window);
2982 defsubr (&Sget_buffer_window);
2983 defsubr (&Sdelete_other_windows);
2984 defsubr (&Sdelete_windows_on);
2985 defsubr (&Sreplace_buffer_in_windows);
2986 defsubr (&Sdelete_window);
2987 defsubr (&Sset_window_buffer);
2988 defsubr (&Sselect_window);
2989 defsubr (&Sdisplay_buffer);
2990 defsubr (&Ssplit_window);
2991 defsubr (&Senlarge_window);
2992 defsubr (&Sshrink_window);
2993 defsubr (&Sscroll_up);
2994 defsubr (&Sscroll_down);
2995 defsubr (&Sscroll_left);
2996 defsubr (&Sscroll_right);
2997 defsubr (&Sscroll_other_window);
2998 defsubr (&Srecenter);
2999 defsubr (&Smove_to_window_line);
3000 defsubr (&Swindow_configuration_p);
3001 defsubr (&Sset_window_configuration);
3002 defsubr (&Scurrent_window_configuration);
3003 defsubr (&Ssave_window_excursion);
3004 }
3005
3006 keys_of_window ()
3007 {
3008 initial_define_key (control_x_map, '1', "delete-other-windows");
3009 initial_define_key (control_x_map, '2', "split-window");
3010 initial_define_key (control_x_map, '0', "delete-window");
3011 initial_define_key (control_x_map, 'o', "other-window");
3012 initial_define_key (control_x_map, '^', "enlarge-window");
3013 initial_define_key (control_x_map, '<', "scroll-left");
3014 initial_define_key (control_x_map, '>', "scroll-right");
3015
3016 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3017 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3018 initial_define_key (meta_map, 'v', "scroll-down");
3019
3020 initial_define_key (global_map, Ctl('L'), "recenter");
3021 initial_define_key (meta_map, 'r', "move-to-window-line");
3022 }