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