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