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