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