(bat-generic-mode-keymap): Added thio variable
[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 "dispextern.h"
33 #include "blockinput.h"
34 #include "intervals.h"
35
36 #ifdef HAVE_X_WINDOWS
37 #include "xterm.h"
38 #endif /* HAVE_X_WINDOWS */
39
40 #ifndef max
41 #define max(a, b) ((a) < (b) ? (b) : (a))
42 #endif
43
44
45 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
46 Lisp_Object Qwindow_size_fixed, Qleft_bitmap_area, Qright_bitmap_area;
47 extern Lisp_Object Qheight, Qwidth;
48
49 static struct window *decode_window P_ ((Lisp_Object));
50 static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
51 static int count_windows P_ ((struct window *));
52 static int get_leaf_windows P_ ((struct window *, struct window **, int));
53 static void window_scroll P_ ((Lisp_Object, int, int, int));
54 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
55 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
56 static int window_min_size_1 P_ ((struct window *, int));
57 static int window_min_size P_ ((struct window *, int, int, int *));
58 static void size_window P_ ((Lisp_Object, int, int, int));
59 static void foreach_window_1 P_ ((struct window *, void (*fn) (), int, int,
60 int, int));
61 static void freeze_window_start P_ ((struct window *, int));
62 static int window_fixed_size_p P_ ((struct window *, int, int));
63 static void enlarge_window P_ ((Lisp_Object, int, int));
64
65
66 /* This is the window in which the terminal's cursor should
67 be left when nothing is being done with it. This must
68 always be a leaf window, and its buffer is selected by
69 the top level editing loop at the end of each command.
70
71 This value is always the same as
72 FRAME_SELECTED_WINDOW (selected_frame). */
73
74 Lisp_Object selected_window;
75
76 /* The mini-buffer window of the selected frame.
77 Note that you cannot test for mini-bufferness of an arbitrary window
78 by comparing against this; but you can test for mini-bufferness of
79 the selected window. */
80
81 Lisp_Object minibuf_window;
82
83 /* Non-nil means it is the window for C-M-v to scroll
84 when the mini-buffer is selected. */
85
86 Lisp_Object Vminibuf_scroll_window;
87
88 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
89
90 Lisp_Object Vother_window_scroll_buffer;
91
92 /* Non-nil means it's function to call to display temp buffers. */
93
94 Lisp_Object Vtemp_buffer_show_function;
95
96 /* If a window gets smaller than either of these, it is removed. */
97
98 int window_min_height;
99 int window_min_width;
100
101 /* Nonzero implies Fdisplay_buffer should create windows. */
102
103 int pop_up_windows;
104
105 /* Nonzero implies make new frames for Fdisplay_buffer. */
106
107 int pop_up_frames;
108
109 /* Non-nil means use this function instead of default */
110
111 Lisp_Object Vpop_up_frame_function;
112
113 /* Function to call to handle Fdisplay_buffer. */
114
115 Lisp_Object Vdisplay_buffer_function;
116
117 /* List of buffer *names* for buffers that should have their own frames. */
118
119 Lisp_Object Vspecial_display_buffer_names;
120
121 /* List of regexps for buffer names that should have their own frames. */
122
123 Lisp_Object Vspecial_display_regexps;
124
125 /* Function to pop up a special frame. */
126
127 Lisp_Object Vspecial_display_function;
128
129 /* List of buffer *names* for buffers to appear in selected window. */
130
131 Lisp_Object Vsame_window_buffer_names;
132
133 /* List of regexps for buffer names to appear in selected window. */
134
135 Lisp_Object Vsame_window_regexps;
136
137 /* Hook run at end of temp_output_buffer_show. */
138
139 Lisp_Object Qtemp_buffer_show_hook;
140
141 /* Fdisplay_buffer always splits the largest window
142 if that window is more than this high. */
143
144 int split_height_threshold;
145
146 /* Number of lines of continuity in scrolling by screenfuls. */
147
148 int next_screen_context_lines;
149
150 /* Incremented for each window created. */
151
152 static int sequence_number;
153
154 /* Nonzero after init_window_once has finished. */
155
156 static int window_initialized;
157
158 /* Hook to run when window config changes. */
159
160 Lisp_Object Qwindow_configuration_change_hook;
161 Lisp_Object Vwindow_configuration_change_hook;
162
163 /* Nonzero means scroll commands try to put point
164 at the same screen height as previously. */
165
166 Lisp_Object Vscroll_preserve_screen_position;
167
168 #if 0 /* This isn't used anywhere. */
169 /* Nonzero means we can split a frame even if it is "unsplittable". */
170 static int inhibit_frame_unsplittable;
171 #endif /* 0 */
172
173 #define min(a, b) ((a) < (b) ? (a) : (b))
174
175 extern int scroll_margin;
176
177 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
178 \f
179 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
180 "Returns t if OBJECT is a window.")
181 (object)
182 Lisp_Object object;
183 {
184 return WINDOWP (object) ? Qt : Qnil;
185 }
186
187 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
188 "Returns t if OBJECT is a window which is currently visible.")
189 (object)
190 Lisp_Object object;
191 {
192 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
193 }
194
195 Lisp_Object
196 make_window ()
197 {
198 Lisp_Object val;
199 register struct window *p;
200 register struct Lisp_Vector *vec;
201 int i;
202
203 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
204 for (i = 0; i < VECSIZE (struct window); i++)
205 vec->contents[i] = Qnil;
206 vec->size = VECSIZE (struct window);
207 p = (struct window *) vec;
208 XSETFASTINT (p->sequence_number, ++sequence_number);
209 XSETFASTINT (p->left, 0);
210 XSETFASTINT (p->top, 0);
211 XSETFASTINT (p->height, 0);
212 XSETFASTINT (p->width, 0);
213 XSETFASTINT (p->hscroll, 0);
214 p->orig_top = p->orig_height = Qnil;
215 p->start = Fmake_marker ();
216 p->pointm = Fmake_marker ();
217 XSETFASTINT (p->use_time, 0);
218 p->frame = Qnil;
219 p->display_table = Qnil;
220 p->dedicated = Qnil;
221 p->pseudo_window_p = 0;
222 bzero (&p->cursor, sizeof (p->cursor));
223 bzero (&p->last_cursor, sizeof (p->last_cursor));
224 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
225 p->desired_matrix = p->current_matrix = 0;
226 p->phys_cursor_type = -1;
227 p->must_be_updated_p = 0;
228 XSETFASTINT (p->window_end_vpos, 0);
229 XSETFASTINT (p->window_end_pos, 0);
230 p->window_end_valid = Qnil;
231 p->vscroll = 0;
232 XSETWINDOW (val, p);
233 XSETFASTINT (p->last_point, 0);
234 p->frozen_window_start_p = 0;
235 return val;
236 }
237
238 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
239 "Return the window that the cursor now appears in and commands apply to.")
240 ()
241 {
242 return selected_window;
243 }
244
245 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
246 "Return the window used now for minibuffers.\n\
247 If the optional argument FRAME is specified, return the minibuffer window\n\
248 used by that frame.")
249 (frame)
250 Lisp_Object frame;
251 {
252 if (NILP (frame))
253 frame = selected_frame;
254 CHECK_LIVE_FRAME (frame, 0);
255 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
256 }
257
258 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
259 "Returns non-nil if WINDOW is a minibuffer window.")
260 (window)
261 Lisp_Object window;
262 {
263 struct window *w = decode_window (window);
264 return (MINI_WINDOW_P (w) ? Qt : Qnil);
265 }
266
267 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
268 Spos_visible_in_window_p, 0, 2, 0,
269 "Return t if position POS is currently on the frame in WINDOW.\n\
270 Returns nil if that position is scrolled vertically out of view.\n\
271 POS defaults to point; WINDOW, to the selected window.")
272 (pos, window)
273 Lisp_Object pos, window;
274 {
275 register struct window *w;
276 register int posint;
277 register struct buffer *buf;
278 struct text_pos top;
279 Lisp_Object in_window;
280
281 if (NILP (pos))
282 posint = PT;
283 else
284 {
285 CHECK_NUMBER_COERCE_MARKER (pos, 0);
286 posint = XINT (pos);
287 }
288
289 w = decode_window (window);
290 buf = XBUFFER (w->buffer);
291 SET_TEXT_POS_FROM_MARKER (top, w->start);
292
293 /* If position above window, it's not visible. */
294 if (posint < CHARPOS (top))
295 in_window = Qnil;
296 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
297 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
298 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
299 /* If frame is up to date, and POSINT is < window end pos, use
300 that info. This doesn't work for POSINT == end pos, because
301 the window end pos is actually the position _after_ the last
302 char in the window. */
303 in_window = Qt;
304 else if (posint > BUF_ZV (buf))
305 in_window = Qnil;
306 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
307 /* If window start is out of range, do something reasonable. */
308 in_window = Qnil;
309 else
310 {
311 struct it it;
312 start_display (&it, w, top);
313 move_it_to (&it, posint, 0, it.last_visible_y, -1,
314 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
315 in_window = IT_CHARPOS (it) == posint ? Qt : Qnil;
316 }
317
318 return in_window;
319 }
320 \f
321 static struct window *
322 decode_window (window)
323 register Lisp_Object window;
324 {
325 if (NILP (window))
326 return XWINDOW (selected_window);
327
328 CHECK_LIVE_WINDOW (window, 0);
329 return XWINDOW (window);
330 }
331
332 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
333 "Return the buffer that WINDOW is displaying.")
334 (window)
335 Lisp_Object window;
336 {
337 return decode_window (window)->buffer;
338 }
339
340 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
341 "Return the number of lines in WINDOW (including its mode line).")
342 (window)
343 Lisp_Object window;
344 {
345 return decode_window (window)->height;
346 }
347
348 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
349 "Return the number of display columns in WINDOW.\n\
350 This is the width that is usable columns available for text in WINDOW.\n\
351 If you want to find out how many columns WINDOW takes up,\n\
352 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
353 (window)
354 Lisp_Object window;
355 {
356 return make_number (window_internal_width (decode_window (window)));
357 }
358
359 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
360 "Return the number of columns by which WINDOW is scrolled from left margin.")
361 (window)
362 Lisp_Object window;
363 {
364 return decode_window (window)->hscroll;
365 }
366
367 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
368 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
369 NCOL should be zero or positive.")
370 (window, ncol)
371 register Lisp_Object window, ncol;
372 {
373 register struct window *w;
374
375 CHECK_NUMBER (ncol, 1);
376 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
377 w = decode_window (window);
378 if (XINT (w->hscroll) != XINT (ncol))
379 /* Prevent redisplay shortcuts */
380 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
381 w->hscroll = ncol;
382 return ncol;
383 }
384
385 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
386 Swindow_redisplay_end_trigger, 0, 1, 0,
387 "Return WINDOW's redisplay end trigger value.\n\
388 See `set-window-redisplay-end-trigger' for more information.")
389 (window)
390 Lisp_Object window;
391 {
392 return decode_window (window)->redisplay_end_trigger;
393 }
394
395 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
396 Sset_window_redisplay_end_trigger, 2, 2, 0,
397 "Set WINDOW's redisplay end trigger value to VALUE.\n\
398 VALUE should be a buffer position (typically a marker) or nil.\n\
399 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
400 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
401 with two arguments: WINDOW, and the end trigger value.\n\
402 Afterwards the end-trigger value is reset to nil.")
403 (window, value)
404 register Lisp_Object window, value;
405 {
406 register struct window *w;
407
408 w = decode_window (window);
409 w->redisplay_end_trigger = value;
410 return value;
411 }
412
413 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
414 "Return a list of the edge coordinates of WINDOW.\n\
415 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
416 RIGHT is one more than the rightmost column used by WINDOW,\n\
417 and BOTTOM is one more than the bottommost row used by WINDOW\n\
418 and its mode-line.")
419 (window)
420 Lisp_Object window;
421 {
422 register struct window *w = decode_window (window);
423
424 return Fcons (w->left, Fcons (w->top,
425 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
426 Fcons (make_number (XFASTINT (w->top)
427 + XFASTINT (w->height)),
428 Qnil))));
429 }
430
431 /* Test if the character at column *X, row *Y is within window W.
432 If it is not, return 0;
433 if it is in the window's text area,
434 set *x and *y to its location relative to the upper left corner
435 of the window, and
436 return 1;
437 if it is on the window's modeline, return 2;
438 if it is on the border between the window and its right sibling,
439 return 3.
440 if it is on the window's top line, return 4;
441 if it is in the bitmap area to the left/right of the window,
442 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
443
444 X and Y are frame relative pixel coordinates. */
445
446 static int
447 coordinates_in_window (w, x, y)
448 register struct window *w;
449 register int *x, *y;
450 {
451 struct frame *f = XFRAME (WINDOW_FRAME (w));
452 int left_x, right_x, top_y, bottom_y;
453 int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
454
455 if (w->pseudo_window_p)
456 {
457 left_x = 0;
458 right_x = XFASTINT (w->width) * CANON_Y_UNIT (f);
459 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
460 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
461 }
462 else
463 {
464 left_x = WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
465 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w);
466 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
467 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
468 }
469
470 if (*y < top_y
471 || *y >= bottom_y
472 || *x < (left_x
473 - flags_area_width
474 - (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
475 * CANON_X_UNIT (f)))
476 || *x > right_x + flags_area_width)
477 /* Completely outside anything interesting. */
478 return 0;
479 else if (WINDOW_WANTS_MODELINE_P (w)
480 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
481 /* On the mode line. */
482 return 2;
483 else if (WINDOW_WANTS_HEADER_LINE_P (w)
484 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
485 /* On the top line. */
486 return 4;
487 else if (*x < left_x || *x >= right_x)
488 {
489 /* Other lines than the mode line don't include flags areas and
490 scroll bars on the left. */
491
492 /* Convert X and Y to window-relative pixel coordinates. */
493 *x -= left_x;
494 *y -= top_y;
495 return *x < left_x ? 5 : 6;
496 }
497 else if (!w->pseudo_window_p
498 && !WINDOW_RIGHTMOST_P (w)
499 && *x >= right_x - CANON_X_UNIT (f))
500 /* On the border on the right side of the window? Assume that
501 this area begins at RIGHT_X minus a canonical char width. */
502 return 3;
503 else
504 {
505 /* Convert X and Y to window-relative pixel coordinates. */
506 *x -= left_x;
507 *y -= top_y;
508 return 1;
509 }
510 }
511
512 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
513 Scoordinates_in_window_p, 2, 2, 0,
514 "Return non-nil if COORDINATES are in WINDOW.\n\
515 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
516 measured in characters from the upper-left corner of the frame.\n\
517 (0 . 0) denotes the character in the upper left corner of the\n\
518 frame.\n\
519 If COORDINATES are in the text portion of WINDOW,\n\
520 the coordinates relative to the window are returned.\n\
521 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
522 If they are in the top mode line of WINDOW, `header-line' is returned.\n\
523 If they are in the bitmap-area to the left of the window,\n\
524 `left-bitmap-area' is returned, if they are in the area on the right of\n\
525 the window, `right-bitmap-area' is returned.\n\
526 If they are on the border between WINDOW and its right sibling,\n\
527 `vertical-line' is returned.")
528 (coordinates, window)
529 register Lisp_Object coordinates, window;
530 {
531 struct window *w;
532 struct frame *f;
533 int x, y;
534 Lisp_Object lx, ly;
535
536 CHECK_LIVE_WINDOW (window, 0);
537 w = XWINDOW (window);
538 f = XFRAME (w->frame);
539 CHECK_CONS (coordinates, 1);
540 lx = Fcar (coordinates);
541 ly = Fcdr (coordinates);
542 CHECK_NUMBER_OR_FLOAT (lx, 1);
543 CHECK_NUMBER_OR_FLOAT (ly, 1);
544 x = PIXEL_X_FROM_CANON_X (f, lx);
545 y = PIXEL_Y_FROM_CANON_Y (f, ly);
546
547 switch (coordinates_in_window (w, &x, &y))
548 {
549 case 0: /* NOT in window at all. */
550 return Qnil;
551
552 case 1: /* In text part of window. */
553 /* X and Y are now window relative pixel coordinates.
554 Convert them to canonical char units before returning
555 them. */
556 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
557 CANON_Y_FROM_PIXEL_Y (f, y));
558
559 case 2: /* In mode line of window. */
560 return Qmode_line;
561
562 case 3: /* On right border of window. */
563 return Qvertical_line;
564
565 case 4:
566 return Qheader_line;
567
568 case 5:
569 return Qleft_bitmap_area;
570
571 case 6:
572 return Qright_bitmap_area;
573
574 default:
575 abort ();
576 }
577 }
578
579 /* Find the window containing frame-relative pixel position X/Y and
580 return it as a Lisp_Object. If X, Y is on the window's modeline,
581 set *PART to 1; if it is on the separating line between the window
582 and its right sibling, set it to 2; otherwise set it to 0. If
583 there is no window under X, Y return nil and leave *PART
584 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows. */
585
586 Lisp_Object
587 window_from_coordinates (frame, x, y, part, tool_bar_p)
588 FRAME_PTR frame;
589 int x, y;
590 int *part;
591 int tool_bar_p;
592 {
593 register Lisp_Object tem, first;
594 int found;
595
596 tem = first = FRAME_SELECTED_WINDOW (frame);
597
598 do
599 {
600 found = coordinates_in_window (XWINDOW (tem), &x, &y);
601
602 if (found)
603 {
604 *part = found - 1;
605 return tem;
606 }
607
608 tem = Fnext_window (tem, Qt, Qlambda);
609 }
610 while (!EQ (tem, first));
611
612 /* See if it's in the tool bar window, if a tool bar exists. */
613 if (tool_bar_p
614 && WINDOWP (frame->tool_bar_window)
615 && XFASTINT (XWINDOW (frame->tool_bar_window)->height)
616 && coordinates_in_window (XWINDOW (frame->tool_bar_window), &x, &y))
617 {
618 *part = 0;
619 return frame->tool_bar_window;
620 }
621
622 return Qnil;
623 }
624
625 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
626 "Return window containing coordinates X and Y on FRAME.\n\
627 If omitted, FRAME defaults to the currently selected frame.\n\
628 The top left corner of the frame is considered to be row 0,\n\
629 column 0.")
630 (x, y, frame)
631 Lisp_Object x, y, frame;
632 {
633 int part;
634 struct frame *f;
635
636 if (NILP (frame))
637 frame = selected_frame;
638 CHECK_LIVE_FRAME (frame, 2);
639 f = XFRAME (frame);
640
641 /* Check that arguments are integers or floats. */
642 CHECK_NUMBER_OR_FLOAT (x, 0);
643 CHECK_NUMBER_OR_FLOAT (y, 1);
644
645 return window_from_coordinates (f,
646 PIXEL_X_FROM_CANON_X (f, x),
647 PIXEL_Y_FROM_CANON_Y (f, y),
648 &part, 0);
649 }
650
651 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
652 "Return current value of point in WINDOW.\n\
653 For a nonselected window, this is the value point would have\n\
654 if that window were selected.\n\
655 \n\
656 Note that, when WINDOW is the selected window and its buffer\n\
657 is also currently selected, the value returned is the same as (point).\n\
658 It would be more strictly correct to return the `top-level' value\n\
659 of point, outside of any save-excursion forms.\n\
660 But that is hard to define.")
661 (window)
662 Lisp_Object window;
663 {
664 register struct window *w = decode_window (window);
665
666 if (w == XWINDOW (selected_window)
667 && current_buffer == XBUFFER (w->buffer))
668 return Fpoint ();
669 return Fmarker_position (w->pointm);
670 }
671
672 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
673 "Return position at which display currently starts in WINDOW.\n\
674 This is updated by redisplay or by calling `set-window-start'.")
675 (window)
676 Lisp_Object window;
677 {
678 return Fmarker_position (decode_window (window)->start);
679 }
680
681 /* This is text temporarily removed from the doc string below.
682
683 This function returns nil if the position is not currently known.\n\
684 That happens when redisplay is preempted and doesn't finish.\n\
685 If in that case you want to compute where the end of the window would\n\
686 have been if redisplay had finished, do this:\n\
687 (save-excursion\n\
688 (goto-char (window-start window))\n\
689 (vertical-motion (1- (window-height window)) window)\n\
690 (point))") */
691
692 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
693 "Return position at which display currently ends in WINDOW.\n\
694 This is updated by redisplay, when it runs to completion.\n\
695 Simply changing the buffer text or setting `window-start'\n\
696 does not update this value.\n\
697 If UP-TO-DATE is non-nil, compute the up-to-date position\n\
698 if it isn't already recorded.")
699 (window, update)
700 Lisp_Object window, update;
701 {
702 Lisp_Object value;
703 struct window *w = decode_window (window);
704 Lisp_Object buf;
705
706 buf = w->buffer;
707 CHECK_BUFFER (buf, 0);
708
709 #if 0 /* This change broke some things. We should make it later. */
710 /* If we don't know the end position, return nil.
711 The user can compute it with vertical-motion if he wants to.
712 It would be nicer to do it automatically,
713 but that's so slow that it would probably bother people. */
714 if (NILP (w->window_end_valid))
715 return Qnil;
716 #endif
717
718 if (! NILP (update)
719 && ! (! NILP (w->window_end_valid)
720 && XFASTINT (w->last_modified) >= MODIFF))
721 {
722 int opoint = PT, opoint_byte = PT_BYTE;
723 TEMP_SET_PT_BOTH (XMARKER (w->start)->charpos,
724 XMARKER (w->start)->bytepos);
725 Fvertical_motion (make_number (window_internal_height (w)), Qnil);
726 XSETINT (value, PT);
727 TEMP_SET_PT_BOTH (opoint, opoint_byte);
728 }
729 else
730 XSETINT (value,
731 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
732
733 return value;
734 }
735
736 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
737 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
738 (window, pos)
739 Lisp_Object window, pos;
740 {
741 register struct window *w = decode_window (window);
742
743 CHECK_NUMBER_COERCE_MARKER (pos, 1);
744 if (w == XWINDOW (selected_window)
745 && XBUFFER (w->buffer) == current_buffer)
746 Fgoto_char (pos);
747 else
748 set_marker_restricted (w->pointm, pos, w->buffer);
749
750 return pos;
751 }
752
753 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
754 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
755 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
756 from overriding motion of point in order to display at this exact start.")
757 (window, pos, noforce)
758 Lisp_Object window, pos, noforce;
759 {
760 register struct window *w = decode_window (window);
761
762 CHECK_NUMBER_COERCE_MARKER (pos, 1);
763 set_marker_restricted (w->start, pos, w->buffer);
764 /* this is not right, but much easier than doing what is right. */
765 w->start_at_line_beg = Qnil;
766 if (NILP (noforce))
767 w->force_start = Qt;
768 w->update_mode_line = Qt;
769 XSETFASTINT (w->last_modified, 0);
770 XSETFASTINT (w->last_overlay_modified, 0);
771 if (!EQ (window, selected_window))
772 windows_or_buffers_changed++;
773
774 return pos;
775 }
776
777 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
778 1, 1, 0,
779 "Return WINDOW's dedicated object, usually t or nil.\n\
780 See also `set-window-dedicated-p'.")
781 (window)
782 Lisp_Object window;
783 {
784 return decode_window (window)->dedicated;
785 }
786
787 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
788 Sset_window_dedicated_p, 2, 2, 0,
789 "Control whether WINDOW is dedicated to the buffer it displays.\n\
790 If it is dedicated, Emacs will not automatically change\n\
791 which buffer appears in it.\n\
792 The second argument is the new value for the dedication flag;\n\
793 non-nil means yes.")
794 (window, arg)
795 Lisp_Object window, arg;
796 {
797 register struct window *w = decode_window (window);
798
799 if (NILP (arg))
800 w->dedicated = Qnil;
801 else
802 w->dedicated = Qt;
803
804 return w->dedicated;
805 }
806
807 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
808 0, 1, 0,
809 "Return the display-table that WINDOW is using.")
810 (window)
811 Lisp_Object window;
812 {
813 return decode_window (window)->display_table;
814 }
815
816 /* Get the display table for use on window W. This is either W's
817 display table or W's buffer's display table. Ignore the specified
818 tables if they are not valid; if no valid table is specified,
819 return 0. */
820
821 struct Lisp_Char_Table *
822 window_display_table (w)
823 struct window *w;
824 {
825 Lisp_Object tem;
826 tem = w->display_table;
827 if (DISP_TABLE_P (tem))
828 return XCHAR_TABLE (tem);
829 if (NILP (w->buffer))
830 return 0;
831
832 tem = XBUFFER (w->buffer)->display_table;
833 if (DISP_TABLE_P (tem))
834 return XCHAR_TABLE (tem);
835 tem = Vstandard_display_table;
836 if (DISP_TABLE_P (tem))
837 return XCHAR_TABLE (tem);
838 return 0;
839 }
840
841 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
842 "Set WINDOW's display-table to TABLE.")
843 (window, table)
844 register Lisp_Object window, table;
845 {
846 register struct window *w;
847
848 w = decode_window (window);
849 w->display_table = table;
850 return table;
851 }
852 \f
853 /* Record info on buffer window w is displaying
854 when it is about to cease to display that buffer. */
855 static void
856 unshow_buffer (w)
857 register struct window *w;
858 {
859 Lisp_Object buf;
860 struct buffer *b;
861
862 buf = w->buffer;
863 b = XBUFFER (buf);
864 if (b != XMARKER (w->pointm)->buffer)
865 abort ();
866
867 if (w == XWINDOW (b->last_selected_window))
868 b->last_selected_window = Qnil;
869
870 #if 0
871 if (w == XWINDOW (selected_window)
872 || ! EQ (buf, XWINDOW (selected_window)->buffer))
873 /* Do this except when the selected window's buffer
874 is being removed from some other window. */
875 #endif
876 /* last_window_start records the start position that this buffer
877 had in the last window to be disconnected from it.
878 Now that this statement is unconditional,
879 it is possible for the buffer to be displayed in the
880 selected window, while last_window_start reflects another
881 window which was recently showing the same buffer.
882 Some people might say that might be a good thing. Let's see. */
883 b->last_window_start = marker_position (w->start);
884
885 /* Point in the selected window's buffer
886 is actually stored in that buffer, and the window's pointm isn't used.
887 So don't clobber point in that buffer. */
888 if (! EQ (buf, XWINDOW (selected_window)->buffer))
889 temp_set_point_both (b,
890 clip_to_bounds (BUF_BEGV (b),
891 XMARKER (w->pointm)->charpos,
892 BUF_ZV (b)),
893 clip_to_bounds (BUF_BEGV_BYTE (b),
894 marker_byte_position (w->pointm),
895 BUF_ZV_BYTE (b)));
896 }
897
898 /* Put replacement into the window structure in place of old. */
899 static void
900 replace_window (old, replacement)
901 Lisp_Object old, replacement;
902 {
903 register Lisp_Object tem;
904 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
905
906 /* If OLD is its frame's root_window, then replacement is the new
907 root_window for that frame. */
908
909 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
910 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
911
912 p->left = o->left;
913 p->top = o->top;
914 p->width = o->width;
915 p->height = o->height;
916 p->desired_matrix = p->current_matrix = 0;
917 p->vscroll = 0;
918 bzero (&p->cursor, sizeof (p->cursor));
919 bzero (&p->last_cursor, sizeof (p->last_cursor));
920 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
921 p->phys_cursor_type = -1;
922 p->must_be_updated_p = 0;
923 p->pseudo_window_p = 0;
924 XSETFASTINT (p->window_end_vpos, 0);
925 XSETFASTINT (p->window_end_pos, 0);
926 p->window_end_valid = Qnil;
927 p->frozen_window_start_p = 0;
928 p->orig_top = p->orig_height = Qnil;
929
930 p->next = tem = o->next;
931 if (!NILP (tem))
932 XWINDOW (tem)->prev = replacement;
933
934 p->prev = tem = o->prev;
935 if (!NILP (tem))
936 XWINDOW (tem)->next = replacement;
937
938 p->parent = tem = o->parent;
939 if (!NILP (tem))
940 {
941 if (EQ (XWINDOW (tem)->vchild, old))
942 XWINDOW (tem)->vchild = replacement;
943 if (EQ (XWINDOW (tem)->hchild, old))
944 XWINDOW (tem)->hchild = replacement;
945 }
946
947 /*** Here, if replacement is a vertical combination
948 and so is its new parent, we should make replacement's
949 children be children of that parent instead. ***/
950 }
951
952 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
953 "Remove WINDOW from the display. Default is selected window.")
954 (window)
955 register Lisp_Object window;
956 {
957 delete_window (window);
958
959 if (! NILP (Vwindow_configuration_change_hook)
960 && ! NILP (Vrun_hooks))
961 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
962
963 return Qnil;
964 }
965
966 void
967 delete_window (window)
968 register Lisp_Object window;
969 {
970 register Lisp_Object tem, parent, sib;
971 register struct window *p;
972 register struct window *par;
973 FRAME_PTR frame;
974
975 /* Because this function is called by other C code on non-leaf
976 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
977 so we can't decode_window here. */
978 if (NILP (window))
979 window = selected_window;
980 else
981 CHECK_WINDOW (window, 0);
982 p = XWINDOW (window);
983
984 /* It's okay to delete an already-deleted window. */
985 if (NILP (p->buffer)
986 && NILP (p->hchild)
987 && NILP (p->vchild))
988 return;
989
990 parent = p->parent;
991 if (NILP (parent))
992 error ("Attempt to delete minibuffer or sole ordinary window");
993 par = XWINDOW (parent);
994
995 windows_or_buffers_changed++;
996 frame = XFRAME (WINDOW_FRAME (p));
997 FRAME_WINDOW_SIZES_CHANGED (frame) = 1;
998
999 /* Are we trying to delete any frame's selected window? */
1000 {
1001 Lisp_Object frame, pwindow;
1002
1003 /* See if the frame's selected window is either WINDOW
1004 or any subwindow of it, by finding all that window's parents
1005 and comparing each one with WINDOW. */
1006 frame = WINDOW_FRAME (XWINDOW (window));
1007 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
1008
1009 while (!NILP (pwindow))
1010 {
1011 if (EQ (window, pwindow))
1012 break;
1013 pwindow = XWINDOW (pwindow)->parent;
1014 }
1015
1016 if (EQ (window, pwindow))
1017 {
1018 Lisp_Object alternative;
1019 alternative = Fnext_window (window, Qlambda, Qnil);
1020
1021 /* If we're about to delete the selected window on the
1022 selected frame, then we should use Fselect_window to select
1023 the new window. On the other hand, if we're about to
1024 delete the selected window on any other frame, we shouldn't do
1025 anything but set the frame's selected_window slot. */
1026 if (EQ (window, selected_window))
1027 Fselect_window (alternative);
1028 else
1029 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
1030 }
1031 }
1032
1033 tem = p->buffer;
1034 /* tem is null for dummy parent windows
1035 (which have inferiors but not any contents themselves) */
1036 if (!NILP (tem))
1037 {
1038 unshow_buffer (p);
1039 unchain_marker (p->pointm);
1040 unchain_marker (p->start);
1041 }
1042
1043 /* Free window glyph matrices.
1044 It is sure that they are allocated again when ADJUST_GLYPHS
1045 is called. */
1046 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (frame)));
1047
1048 tem = p->next;
1049 if (!NILP (tem))
1050 XWINDOW (tem)->prev = p->prev;
1051
1052 tem = p->prev;
1053 if (!NILP (tem))
1054 XWINDOW (tem)->next = p->next;
1055
1056 if (EQ (window, par->hchild))
1057 par->hchild = p->next;
1058 if (EQ (window, par->vchild))
1059 par->vchild = p->next;
1060
1061 /* Find one of our siblings to give our space to. */
1062 sib = p->prev;
1063 if (NILP (sib))
1064 {
1065 /* If p gives its space to its next sibling, that sibling needs
1066 to have its top/left side pulled back to where p's is.
1067 set_window_{height,width} will re-position the sibling's
1068 children. */
1069 sib = p->next;
1070 XWINDOW (sib)->top = p->top;
1071 XWINDOW (sib)->left = p->left;
1072 }
1073
1074 /* Stretch that sibling. */
1075 if (!NILP (par->vchild))
1076 set_window_height (sib,
1077 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1078 1);
1079 if (!NILP (par->hchild))
1080 set_window_width (sib,
1081 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1082 1);
1083
1084 /* If parent now has only one child,
1085 put the child into the parent's place. */
1086 tem = par->hchild;
1087 if (NILP (tem))
1088 tem = par->vchild;
1089 if (NILP (XWINDOW (tem)->next))
1090 replace_window (parent, tem);
1091
1092 /* Since we may be deleting combination windows, we must make sure that
1093 not only p but all its children have been marked as deleted. */
1094 if (! NILP (p->hchild))
1095 delete_all_subwindows (XWINDOW (p->hchild));
1096 else if (! NILP (p->vchild))
1097 delete_all_subwindows (XWINDOW (p->vchild));
1098
1099 /* Mark this window as deleted. */
1100 p->buffer = p->hchild = p->vchild = Qnil;
1101
1102 /* Adjust glyph matrices. */
1103 adjust_glyphs (frame);
1104 }
1105 \f
1106
1107 extern Lisp_Object next_frame (), prev_frame ();
1108
1109 /* This comment supplies the doc string for `next-window',
1110 for make-docfile to see. We cannot put this in the real DEFUN
1111 due to limits in the Unix cpp.
1112
1113 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
1114 "Return next window after WINDOW in canonical ordering of windows.\n\
1115 If omitted, WINDOW defaults to the selected window.\n\
1116 \n\
1117 Optional second arg MINIBUF t means count the minibuffer window even\n\
1118 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1119 it is active. MINIBUF neither t nor nil means not to count the\n\
1120 minibuffer even if it is active.\n\
1121 \n\
1122 Several frames may share a single minibuffer; if the minibuffer\n\
1123 counts, all windows on all frames that share that minibuffer count\n\
1124 too. Therefore, `next-window' can be used to iterate through the\n\
1125 set of windows even when the minibuffer is on another frame. If the\n\
1126 minibuffer does not count, only windows from WINDOW's frame count.\n\
1127 \n\
1128 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1129 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1130 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1131 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1132 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1133 Anything else means restrict to WINDOW's frame.\n\
1134 \n\
1135 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1136 `next-window' to iterate through the entire cycle of acceptable\n\
1137 windows, eventually ending up back at the window you started with.\n\
1138 `previous-window' traverses the same cycle, in the reverse order.")
1139 (window, minibuf, all_frames) */
1140
1141 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1142 0)
1143 (window, minibuf, all_frames)
1144 register Lisp_Object window, minibuf, all_frames;
1145 {
1146 register Lisp_Object tem;
1147 Lisp_Object start_window;
1148
1149 if (NILP (window))
1150 window = selected_window;
1151 else
1152 CHECK_LIVE_WINDOW (window, 0);
1153
1154 start_window = window;
1155
1156 /* minibuf == nil may or may not include minibuffers.
1157 Decide if it does. */
1158 if (NILP (minibuf))
1159 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1160 else if (! EQ (minibuf, Qt))
1161 minibuf = Qlambda;
1162 /* Now minibuf can be t => count all minibuffer windows,
1163 lambda => count none of them,
1164 or a specific minibuffer window (the active one) to count. */
1165
1166 /* all_frames == nil doesn't specify which frames to include. */
1167 if (NILP (all_frames))
1168 all_frames = (! EQ (minibuf, Qlambda)
1169 ? (FRAME_MINIBUF_WINDOW
1170 (XFRAME
1171 (WINDOW_FRAME
1172 (XWINDOW (window)))))
1173 : Qnil);
1174 else if (EQ (all_frames, Qvisible))
1175 ;
1176 else if (XFASTINT (all_frames) == 0)
1177 ;
1178 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1179 /* If all_frames is a frame and window arg isn't on that frame, just
1180 return the first window on the frame. */
1181 return Fframe_first_window (all_frames);
1182 else if (! EQ (all_frames, Qt))
1183 all_frames = Qnil;
1184 /* Now all_frames is t meaning search all frames,
1185 nil meaning search just current frame,
1186 visible meaning search just visible frames,
1187 0 meaning search visible and iconified frames,
1188 or a window, meaning search the frame that window belongs to. */
1189
1190 /* Do this loop at least once, to get the next window, and perhaps
1191 again, if we hit the minibuffer and that is not acceptable. */
1192 do
1193 {
1194 /* Find a window that actually has a next one. This loop
1195 climbs up the tree. */
1196 while (tem = XWINDOW (window)->next, NILP (tem))
1197 if (tem = XWINDOW (window)->parent, !NILP (tem))
1198 window = tem;
1199 else
1200 {
1201 /* We've reached the end of this frame.
1202 Which other frames are acceptable? */
1203 tem = WINDOW_FRAME (XWINDOW (window));
1204 if (! NILP (all_frames))
1205 {
1206 Lisp_Object tem1;
1207
1208 tem1 = tem;
1209 tem = next_frame (tem, all_frames);
1210 /* In the case where the minibuffer is active,
1211 and we include its frame as well as the selected one,
1212 next_frame may get stuck in that frame.
1213 If that happens, go back to the selected frame
1214 so we can complete the cycle. */
1215 if (EQ (tem, tem1))
1216 tem = selected_frame;
1217 }
1218 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1219
1220 break;
1221 }
1222
1223 window = tem;
1224
1225 /* If we're in a combination window, find its first child and
1226 recurse on that. Otherwise, we've found the window we want. */
1227 while (1)
1228 {
1229 if (!NILP (XWINDOW (window)->hchild))
1230 window = XWINDOW (window)->hchild;
1231 else if (!NILP (XWINDOW (window)->vchild))
1232 window = XWINDOW (window)->vchild;
1233 else break;
1234 }
1235 }
1236 /* Which windows are acceptable?
1237 Exit the loop and accept this window if
1238 this isn't a minibuffer window,
1239 or we're accepting all minibuffer windows,
1240 or this is the active minibuffer and we are accepting that one, or
1241 we've come all the way around and we're back at the original window. */
1242 while (MINI_WINDOW_P (XWINDOW (window))
1243 && ! EQ (minibuf, Qt)
1244 && ! EQ (minibuf, window)
1245 && ! EQ (window, start_window));
1246
1247 return window;
1248 }
1249
1250 /* This comment supplies the doc string for `previous-window',
1251 for make-docfile to see. We cannot put this in the real DEFUN
1252 due to limits in the Unix cpp.
1253
1254 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1255 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1256 If omitted, WINDOW defaults to the selected window.\n\
1257 \n\
1258 Optional second arg MINIBUF t means count the minibuffer window even\n\
1259 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1260 it is active. MINIBUF neither t nor nil means not to count the\n\
1261 minibuffer even if it is active.\n\
1262 \n\
1263 Several frames may share a single minibuffer; if the minibuffer\n\
1264 counts, all windows on all frames that share that minibuffer count\n\
1265 too. Therefore, `previous-window' can be used to iterate through\n\
1266 the set of windows even when the minibuffer is on another frame. If\n\
1267 the minibuffer does not count, only windows from WINDOW's frame count\n\
1268 \n\
1269 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1270 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1271 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1272 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1273 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1274 Anything else means restrict to WINDOW's frame.\n\
1275 \n\
1276 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1277 `previous-window' to iterate through the entire cycle of acceptable\n\
1278 windows, eventually ending up back at the window you started with.\n\
1279 `next-window' traverses the same cycle, in the reverse order.")
1280 (window, minibuf, all_frames) */
1281
1282
1283 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1284 0)
1285 (window, minibuf, all_frames)
1286 register Lisp_Object window, minibuf, all_frames;
1287 {
1288 register Lisp_Object tem;
1289 Lisp_Object start_window;
1290
1291 if (NILP (window))
1292 window = selected_window;
1293 else
1294 CHECK_LIVE_WINDOW (window, 0);
1295
1296 start_window = window;
1297
1298 /* minibuf == nil may or may not include minibuffers.
1299 Decide if it does. */
1300 if (NILP (minibuf))
1301 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1302 else if (! EQ (minibuf, Qt))
1303 minibuf = Qlambda;
1304 /* Now minibuf can be t => count all minibuffer windows,
1305 lambda => count none of them,
1306 or a specific minibuffer window (the active one) to count. */
1307
1308 /* all_frames == nil doesn't specify which frames to include.
1309 Decide which frames it includes. */
1310 if (NILP (all_frames))
1311 all_frames = (! EQ (minibuf, Qlambda)
1312 ? (FRAME_MINIBUF_WINDOW
1313 (XFRAME
1314 (WINDOW_FRAME
1315 (XWINDOW (window)))))
1316 : Qnil);
1317 else if (EQ (all_frames, Qvisible))
1318 ;
1319 else if (XFASTINT (all_frames) == 0)
1320 ;
1321 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1322 /* If all_frames is a frame and window arg isn't on that frame, just
1323 return the first window on the frame. */
1324 return Fframe_first_window (all_frames);
1325 else if (! EQ (all_frames, Qt))
1326 all_frames = Qnil;
1327 /* Now all_frames is t meaning search all frames,
1328 nil meaning search just current frame,
1329 visible meaning search just visible frames,
1330 0 meaning search visible and iconified frames,
1331 or a window, meaning search the frame that window belongs to. */
1332
1333 /* Do this loop at least once, to get the previous window, and perhaps
1334 again, if we hit the minibuffer and that is not acceptable. */
1335 do
1336 {
1337 /* Find a window that actually has a previous one. This loop
1338 climbs up the tree. */
1339 while (tem = XWINDOW (window)->prev, NILP (tem))
1340 if (tem = XWINDOW (window)->parent, !NILP (tem))
1341 window = tem;
1342 else
1343 {
1344 /* We have found the top window on the frame.
1345 Which frames are acceptable? */
1346 tem = WINDOW_FRAME (XWINDOW (window));
1347 if (! NILP (all_frames))
1348 /* It's actually important that we use prev_frame here,
1349 rather than next_frame. All the windows acceptable
1350 according to the given parameters should form a ring;
1351 Fnext_window and Fprevious_window should go back and
1352 forth around the ring. If we use next_frame here,
1353 then Fnext_window and Fprevious_window take different
1354 paths through the set of acceptable windows.
1355 window_loop assumes that these `ring' requirement are
1356 met. */
1357 {
1358 Lisp_Object tem1;
1359
1360 tem1 = tem;
1361 tem = prev_frame (tem, all_frames);
1362 /* In the case where the minibuffer is active,
1363 and we include its frame as well as the selected one,
1364 next_frame may get stuck in that frame.
1365 If that happens, go back to the selected frame
1366 so we can complete the cycle. */
1367 if (EQ (tem, tem1))
1368 tem = selected_frame;
1369 }
1370 /* If this frame has a minibuffer, find that window first,
1371 because it is conceptually the last window in that frame. */
1372 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1373 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1374 else
1375 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1376
1377 break;
1378 }
1379
1380 window = tem;
1381 /* If we're in a combination window, find its last child and
1382 recurse on that. Otherwise, we've found the window we want. */
1383 while (1)
1384 {
1385 if (!NILP (XWINDOW (window)->hchild))
1386 window = XWINDOW (window)->hchild;
1387 else if (!NILP (XWINDOW (window)->vchild))
1388 window = XWINDOW (window)->vchild;
1389 else break;
1390 while (tem = XWINDOW (window)->next, !NILP (tem))
1391 window = tem;
1392 }
1393 }
1394 /* Which windows are acceptable?
1395 Exit the loop and accept this window if
1396 this isn't a minibuffer window,
1397 or we're accepting all minibuffer windows,
1398 or this is the active minibuffer and we are accepting that one, or
1399 we've come all the way around and we're back at the original window. */
1400 while (MINI_WINDOW_P (XWINDOW (window))
1401 && ! EQ (minibuf, Qt)
1402 && ! EQ (minibuf, window)
1403 && ! EQ (window, start_window));
1404
1405 return window;
1406 }
1407
1408 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1409 "Select the ARG'th different window on this frame.\n\
1410 All windows on current frame are arranged in a cyclic order.\n\
1411 This command selects the window ARG steps away in that order.\n\
1412 A negative ARG moves in the opposite order. If the optional second\n\
1413 argument ALL_FRAMES is non-nil, cycle through all frames.")
1414 (arg, all_frames)
1415 register Lisp_Object arg, all_frames;
1416 {
1417 register int i;
1418 register Lisp_Object w;
1419
1420 CHECK_NUMBER (arg, 0);
1421 w = selected_window;
1422 i = XINT (arg);
1423
1424 while (i > 0)
1425 {
1426 w = Fnext_window (w, Qnil, all_frames);
1427 i--;
1428 }
1429 while (i < 0)
1430 {
1431 w = Fprevious_window (w, Qnil, all_frames);
1432 i++;
1433 }
1434 Fselect_window (w);
1435 return Qnil;
1436 }
1437 \f
1438 /* Look at all windows, performing an operation specified by TYPE
1439 with argument OBJ.
1440 If FRAMES is Qt, look at all frames;
1441 Qnil, look at just the selected frame;
1442 Qvisible, look at visible frames;
1443 a frame, just look at windows on that frame.
1444 If MINI is non-zero, perform the operation on minibuffer windows too.
1445 */
1446
1447 enum window_loop
1448 {
1449 WINDOW_LOOP_UNUSED,
1450 GET_BUFFER_WINDOW, /* Arg is buffer */
1451 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1452 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1453 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1454 GET_LARGEST_WINDOW,
1455 UNSHOW_BUFFER, /* Arg is buffer */
1456 CHECK_ALL_WINDOWS
1457 };
1458
1459 static Lisp_Object
1460 window_loop (type, obj, mini, frames)
1461 enum window_loop type;
1462 register Lisp_Object obj, frames;
1463 int mini;
1464 {
1465 register Lisp_Object w;
1466 register Lisp_Object best_window;
1467 register Lisp_Object next_window;
1468 register Lisp_Object last_window;
1469 FRAME_PTR frame;
1470 Lisp_Object frame_arg;
1471 frame_arg = Qt;
1472
1473 /* If we're only looping through windows on a particular frame,
1474 frame points to that frame. If we're looping through windows
1475 on all frames, frame is 0. */
1476 if (FRAMEP (frames))
1477 frame = XFRAME (frames);
1478 else if (NILP (frames))
1479 frame = SELECTED_FRAME ();
1480 else
1481 frame = 0;
1482 if (frame)
1483 frame_arg = Qlambda;
1484 else if (XFASTINT (frames) == 0)
1485 frame_arg = frames;
1486 else if (EQ (frames, Qvisible))
1487 frame_arg = frames;
1488
1489 /* frame_arg is Qlambda to stick to one frame,
1490 Qvisible to consider all visible frames,
1491 or Qt otherwise. */
1492
1493 /* Pick a window to start with. */
1494 if (WINDOWP (obj))
1495 w = obj;
1496 else if (frame)
1497 w = FRAME_SELECTED_WINDOW (frame);
1498 else
1499 w = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1500
1501 /* Figure out the last window we're going to mess with. Since
1502 Fnext_window, given the same options, is guaranteed to go in a
1503 ring, we can just use Fprevious_window to find the last one.
1504
1505 We can't just wait until we hit the first window again, because
1506 it might be deleted. */
1507
1508 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
1509
1510 best_window = Qnil;
1511 for (;;)
1512 {
1513 /* Pick the next window now, since some operations will delete
1514 the current window. */
1515 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
1516
1517 /* Note that we do not pay attention here to whether
1518 the frame is visible, since Fnext_window skips non-visible frames
1519 if that is desired, under the control of frame_arg. */
1520 if (! MINI_WINDOW_P (XWINDOW (w))
1521 /* For UNSHOW_BUFFER, we must always consider all windows. */
1522 || type == UNSHOW_BUFFER
1523 || (mini && minibuf_level > 0))
1524 switch (type)
1525 {
1526 case GET_BUFFER_WINDOW:
1527 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj)
1528 /* Don't find any minibuffer window
1529 except the one that is currently in use. */
1530 && (MINI_WINDOW_P (XWINDOW (w))
1531 ? EQ (w, minibuf_window) : 1))
1532 return w;
1533 break;
1534
1535 case GET_LRU_WINDOW:
1536 /* t as arg means consider only full-width windows */
1537 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (XWINDOW (w)))
1538 break;
1539 /* Ignore dedicated windows and minibuffers. */
1540 if (MINI_WINDOW_P (XWINDOW (w))
1541 || !NILP (XWINDOW (w)->dedicated))
1542 break;
1543 if (NILP (best_window)
1544 || (XFASTINT (XWINDOW (best_window)->use_time)
1545 > XFASTINT (XWINDOW (w)->use_time)))
1546 best_window = w;
1547 break;
1548
1549 case DELETE_OTHER_WINDOWS:
1550 if (XWINDOW (w) != XWINDOW (obj))
1551 Fdelete_window (w);
1552 break;
1553
1554 case DELETE_BUFFER_WINDOWS:
1555 if (EQ (XWINDOW (w)->buffer, obj))
1556 {
1557 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1558
1559 /* If this window is dedicated, and in a frame of its own,
1560 kill the frame. */
1561 if (EQ (w, FRAME_ROOT_WINDOW (f))
1562 && !NILP (XWINDOW (w)->dedicated)
1563 && other_visible_frames (f))
1564 {
1565 /* Skip the other windows on this frame.
1566 There might be one, the minibuffer! */
1567 if (! EQ (w, last_window))
1568 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1569 {
1570 /* As we go, check for the end of the loop.
1571 We mustn't start going around a second time. */
1572 if (EQ (next_window, last_window))
1573 {
1574 last_window = w;
1575 break;
1576 }
1577 next_window = Fnext_window (next_window,
1578 mini ? Qt : Qnil,
1579 frame_arg);
1580 }
1581 /* Now we can safely delete the frame. */
1582 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1583 }
1584 else
1585 /* If we're deleting the buffer displayed in the only window
1586 on the frame, find a new buffer to display there. */
1587 if (NILP (XWINDOW (w)->parent))
1588 {
1589 Lisp_Object new_buffer;
1590 new_buffer = Fother_buffer (obj, Qnil,
1591 XWINDOW (w)->frame);
1592 if (NILP (new_buffer))
1593 new_buffer
1594 = Fget_buffer_create (build_string ("*scratch*"));
1595 Fset_window_buffer (w, new_buffer);
1596 if (EQ (w, selected_window))
1597 Fset_buffer (XWINDOW (w)->buffer);
1598 }
1599 else
1600 Fdelete_window (w);
1601 }
1602 break;
1603
1604 case GET_LARGEST_WINDOW:
1605 /* Ignore dedicated windows and minibuffers. */
1606 if (MINI_WINDOW_P (XWINDOW (w))
1607 || !NILP (XWINDOW (w)->dedicated))
1608 break;
1609 {
1610 struct window *best_window_ptr = XWINDOW (best_window);
1611 struct window *w_ptr = XWINDOW (w);
1612 if (NILP (best_window)
1613 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
1614 > (XFASTINT (best_window_ptr->height)
1615 * XFASTINT (best_window_ptr->width))))
1616 best_window = w;
1617 }
1618 break;
1619
1620 case UNSHOW_BUFFER:
1621 if (EQ (XWINDOW (w)->buffer, obj))
1622 {
1623 /* Find another buffer to show in this window. */
1624 Lisp_Object another_buffer;
1625 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1626 another_buffer = Fother_buffer (obj, Qnil, XWINDOW (w)->frame);
1627 if (NILP (another_buffer))
1628 another_buffer
1629 = Fget_buffer_create (build_string ("*scratch*"));
1630 /* If this window is dedicated, and in a frame of its own,
1631 kill the frame. */
1632 if (EQ (w, FRAME_ROOT_WINDOW (f))
1633 && !NILP (XWINDOW (w)->dedicated)
1634 && other_visible_frames (f))
1635 {
1636 /* Skip the other windows on this frame.
1637 There might be one, the minibuffer! */
1638 if (! EQ (w, last_window))
1639 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1640 {
1641 /* As we go, check for the end of the loop.
1642 We mustn't start going around a second time. */
1643 if (EQ (next_window, last_window))
1644 {
1645 last_window = w;
1646 break;
1647 }
1648 next_window = Fnext_window (next_window,
1649 mini ? Qt : Qnil,
1650 frame_arg);
1651 }
1652 /* Now we can safely delete the frame. */
1653 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1654 }
1655 else
1656 {
1657 /* Otherwise show a different buffer in the window. */
1658 XWINDOW (w)->dedicated = Qnil;
1659 Fset_window_buffer (w, another_buffer);
1660 if (EQ (w, selected_window))
1661 Fset_buffer (XWINDOW (w)->buffer);
1662 }
1663 }
1664 break;
1665
1666 /* Check for a window that has a killed buffer. */
1667 case CHECK_ALL_WINDOWS:
1668 if (! NILP (XWINDOW (w)->buffer)
1669 && NILP (XBUFFER (XWINDOW (w)->buffer)->name))
1670 abort ();
1671 }
1672
1673 if (EQ (w, last_window))
1674 break;
1675
1676 w = next_window;
1677 }
1678
1679 return best_window;
1680 }
1681
1682 /* Used for debugging. Abort if any window has a dead buffer. */
1683
1684 void
1685 check_all_windows ()
1686 {
1687 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1688 }
1689
1690 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1691 "Return the window least recently selected or used for display.\n\
1692 If optional argument FRAME is `visible', search all visible frames.\n\
1693 If FRAME is 0, search all visible and iconified frames.\n\
1694 If FRAME is t, search all frames.\n\
1695 If FRAME is nil, search only the selected frame.\n\
1696 If FRAME is a frame, search only that frame.")
1697 (frame)
1698 Lisp_Object frame;
1699 {
1700 register Lisp_Object w;
1701 /* First try for a window that is full-width */
1702 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1703 if (!NILP (w) && !EQ (w, selected_window))
1704 return w;
1705 /* If none of them, try the rest */
1706 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1707 }
1708
1709 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1710 "Return the largest window in area.\n\
1711 If optional argument FRAME is `visible', search all visible frames.\n\
1712 If FRAME is 0, search all visible and iconified frames.\n\
1713 If FRAME is t, search all frames.\n\
1714 If FRAME is nil, search only the selected frame.\n\
1715 If FRAME is a frame, search only that frame.")
1716 (frame)
1717 Lisp_Object frame;
1718 {
1719 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1720 frame);
1721 }
1722
1723 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1724 "Return a window currently displaying BUFFER, or nil if none.\n\
1725 If optional argument FRAME is `visible', search all visible frames.\n\
1726 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1727 If FRAME is t, search all frames.\n\
1728 If FRAME is nil, search only the selected frame.\n\
1729 If FRAME is a frame, search only that frame.")
1730 (buffer, frame)
1731 Lisp_Object buffer, frame;
1732 {
1733 buffer = Fget_buffer (buffer);
1734 if (BUFFERP (buffer))
1735 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1736 else
1737 return Qnil;
1738 }
1739
1740 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1741 0, 1, "",
1742 "Make WINDOW (or the selected window) fill its frame.\n\
1743 Only the frame WINDOW is on is affected.\n\
1744 This function tries to reduce display jumps\n\
1745 by keeping the text previously visible in WINDOW\n\
1746 in the same place on the frame. Doing this depends on\n\
1747 the value of (window-start WINDOW), so if calling this function\n\
1748 in a program gives strange scrolling, make sure the window-start\n\
1749 value is reasonable when this function is called.")
1750 (window)
1751 Lisp_Object window;
1752 {
1753 struct window *w;
1754 int startpos;
1755 int top;
1756
1757 if (NILP (window))
1758 window = selected_window;
1759 else
1760 CHECK_LIVE_WINDOW (window, 0);
1761
1762 w = XWINDOW (window);
1763
1764 startpos = marker_position (w->start);
1765 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
1766
1767 if (MINI_WINDOW_P (w) && top > 0)
1768 error ("Can't expand minibuffer to full frame");
1769
1770 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1771
1772 /* Try to minimize scrolling, by setting the window start to the point
1773 will cause the text at the old window start to be at the same place
1774 on the frame. But don't try to do this if the window start is
1775 outside the visible portion (as might happen when the display is
1776 not current, due to typeahead). */
1777 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1778 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1779 {
1780 struct position pos;
1781 struct buffer *obuf = current_buffer;
1782
1783 Fset_buffer (w->buffer);
1784 /* This computation used to temporarily move point, but that can
1785 have unwanted side effects due to text properties. */
1786 pos = *vmotion (startpos, -top, w);
1787
1788 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
1789 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
1790 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
1791 : Qnil);
1792 /* We need to do this, so that the window-scroll-functions
1793 get called. */
1794 w->optional_new_start = Qt;
1795
1796 set_buffer_internal (obuf);
1797 }
1798
1799 return Qnil;
1800 }
1801
1802 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1803 1, 2, "bDelete windows on (buffer): ",
1804 "Delete all windows showing BUFFER.\n\
1805 Optional second argument FRAME controls which frames are affected.\n\
1806 If optional argument FRAME is `visible', search all visible frames.\n\
1807 If FRAME is 0, search all visible and iconified frames.\n\
1808 If FRAME is nil, search all frames.\n\
1809 If FRAME is t, search only the selected frame.\n\
1810 If FRAME is a frame, search only that frame.")
1811 (buffer, frame)
1812 Lisp_Object buffer, frame;
1813 {
1814 /* FRAME uses t and nil to mean the opposite of what window_loop
1815 expects. */
1816 if (NILP (frame))
1817 frame = Qt;
1818 else if (EQ (frame, Qt))
1819 frame = Qnil;
1820
1821 if (!NILP (buffer))
1822 {
1823 buffer = Fget_buffer (buffer);
1824 CHECK_BUFFER (buffer, 0);
1825 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1826 }
1827
1828 return Qnil;
1829 }
1830
1831 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1832 Sreplace_buffer_in_windows,
1833 1, 1, "bReplace buffer in windows: ",
1834 "Replace BUFFER with some other buffer in all windows showing it.")
1835 (buffer)
1836 Lisp_Object buffer;
1837 {
1838 if (!NILP (buffer))
1839 {
1840 buffer = Fget_buffer (buffer);
1841 CHECK_BUFFER (buffer, 0);
1842 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1843 }
1844 return Qnil;
1845 }
1846
1847 /* Replace BUFFER with some other buffer in all windows
1848 of all frames, even those on other keyboards. */
1849
1850 void
1851 replace_buffer_in_all_windows (buffer)
1852 Lisp_Object buffer;
1853 {
1854 #ifdef MULTI_KBOARD
1855 Lisp_Object tail, frame;
1856
1857 /* A single call to window_loop won't do the job
1858 because it only considers frames on the current keyboard.
1859 So loop manually over frames, and handle each one. */
1860 FOR_EACH_FRAME (tail, frame)
1861 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
1862 #else
1863 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
1864 #endif
1865 }
1866 \f
1867 /* Set the height of WINDOW and all its inferiors. */
1868
1869 /* The smallest acceptable dimensions for a window. Anything smaller
1870 might crash Emacs. */
1871
1872 #define MIN_SAFE_WINDOW_WIDTH (2)
1873 #define MIN_SAFE_WINDOW_HEIGHT (2)
1874
1875 /* Make sure that window_min_height and window_min_width are
1876 not too small; if they are, set them to safe minima. */
1877
1878 static void
1879 check_min_window_sizes ()
1880 {
1881 /* Smaller values might permit a crash. */
1882 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1883 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1884 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1885 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1886 }
1887
1888 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1889 minimum allowable size. */
1890
1891 void
1892 check_frame_size (frame, rows, cols)
1893 FRAME_PTR frame;
1894 int *rows, *cols;
1895 {
1896 /* For height, we have to see:
1897 whether the frame has a minibuffer,
1898 whether it wants a mode line, and
1899 whether it has a menu bar. */
1900 int min_height =
1901 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1902 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
1903 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1904
1905 if (FRAME_TOP_MARGIN (frame) > 0)
1906 min_height += FRAME_TOP_MARGIN (frame);
1907
1908 if (*rows < min_height)
1909 *rows = min_height;
1910 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1911 *cols = MIN_SAFE_WINDOW_WIDTH;
1912 }
1913
1914
1915 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
1916 check if W's width can be changed, otherwise check W's height.
1917 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
1918 siblings, too. If none of the siblings is resizable, WINDOW isn't
1919 either. */
1920
1921 static int
1922 window_fixed_size_p (w, width_p, check_siblings_p)
1923 struct window *w;
1924 int width_p, check_siblings_p;
1925 {
1926 int fixed_p;
1927 struct window *c;
1928
1929 if (!NILP (w->hchild))
1930 {
1931 c = XWINDOW (w->hchild);
1932
1933 if (width_p)
1934 {
1935 /* A horiz. combination is fixed-width if all of if its
1936 children are. */
1937 while (c && window_fixed_size_p (c, width_p, 0))
1938 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1939 fixed_p = c == NULL;
1940 }
1941 else
1942 {
1943 /* A horiz. combination is fixed-height if one of if its
1944 children is. */
1945 while (c && !window_fixed_size_p (c, width_p, 0))
1946 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1947 fixed_p = c != NULL;
1948 }
1949 }
1950 else if (!NILP (w->vchild))
1951 {
1952 c = XWINDOW (w->vchild);
1953
1954 if (width_p)
1955 {
1956 /* A vert. combination is fixed-width if one of if its
1957 children is. */
1958 while (c && !window_fixed_size_p (c, width_p, 0))
1959 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1960 fixed_p = c != NULL;
1961 }
1962 else
1963 {
1964 /* A vert. combination is fixed-height if all of if its
1965 children are. */
1966 while (c && window_fixed_size_p (c, width_p, 0))
1967 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1968 fixed_p = c == NULL;
1969 }
1970 }
1971 else if (BUFFERP (w->buffer))
1972 {
1973 if (w->height_fixed_p && !width_p)
1974 fixed_p = 1;
1975 else
1976 {
1977 struct buffer *old = current_buffer;
1978 Lisp_Object val;
1979
1980 current_buffer = XBUFFER (w->buffer);
1981 val = find_symbol_value (Qwindow_size_fixed);
1982 current_buffer = old;
1983
1984 fixed_p = 0;
1985 if (!EQ (val, Qunbound))
1986 {
1987 fixed_p = !NILP (val);
1988
1989 if (fixed_p
1990 && ((EQ (val, Qheight) && width_p)
1991 || (EQ (val, Qwidth) && !width_p)))
1992 fixed_p = 0;
1993 }
1994 }
1995
1996 /* Can't tell if this one is resizable without looking at
1997 siblings. If all siblings are fixed-size this one is too. */
1998 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
1999 {
2000 Lisp_Object child;
2001
2002 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2003 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2004 break;
2005
2006 if (NILP (child))
2007 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2008 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2009 break;
2010
2011 if (NILP (child))
2012 fixed_p = 1;
2013 }
2014 }
2015 else
2016 fixed_p = 1;
2017
2018 return fixed_p;
2019 }
2020
2021
2022 /* Return the minimum size of window W, not taking fixed-width windows
2023 into account. WIDTH_P non-zero means return the minimum width,
2024 otherwise return the minimum height. If W is a combination window,
2025 compute the minimum size from the minimum sizes of W's children. */
2026
2027 static int
2028 window_min_size_1 (w, width_p)
2029 struct window *w;
2030 int width_p;
2031 {
2032 struct window *c;
2033 int size;
2034
2035 if (!NILP (w->hchild))
2036 {
2037 c = XWINDOW (w->hchild);
2038 size = 0;
2039
2040 if (width_p)
2041 {
2042 /* The min width of a horizontal combination is
2043 the sum of the min widths of its children. */
2044 while (c)
2045 {
2046 size += window_min_size_1 (c, width_p);
2047 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2048 }
2049 }
2050 else
2051 {
2052 /* The min height a horizontal combination equals
2053 the maximum of all min height of its children. */
2054 while (c)
2055 {
2056 int min_size = window_min_size_1 (c, width_p);
2057 size = max (min_size, size);
2058 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2059 }
2060 }
2061 }
2062 else if (!NILP (w->vchild))
2063 {
2064 c = XWINDOW (w->vchild);
2065 size = 0;
2066
2067 if (width_p)
2068 {
2069 /* The min width of a vertical combination is
2070 the maximum of the min widths of its children. */
2071 while (c)
2072 {
2073 int min_size = window_min_size_1 (c, width_p);
2074 size = max (min_size, size);
2075 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2076 }
2077 }
2078 else
2079 {
2080 /* The min height of a vertical combination equals
2081 the sum of the min height of its children. */
2082 while (c)
2083 {
2084 size += window_min_size_1 (c, width_p);
2085 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2086 }
2087 }
2088 }
2089 else
2090 {
2091 if (width_p)
2092 size = window_min_width;
2093 else
2094 {
2095 if (MINI_WINDOW_P (w)
2096 || (!WINDOW_WANTS_MODELINE_P (w)
2097 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2098 size = 1;
2099 else
2100 size = window_min_height;
2101 }
2102 }
2103
2104 return size;
2105 }
2106
2107
2108 /* Return the minimum size of window W, taking fixed-size windows into
2109 account. WIDTH_P non-zero means return the minimum width,
2110 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2111 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2112 unless FIXED is null. */
2113
2114 static int
2115 window_min_size (w, width_p, ignore_fixed_p, fixed)
2116 struct window *w;
2117 int width_p, ignore_fixed_p, *fixed;
2118 {
2119 int size, fixed_p;
2120
2121 if (ignore_fixed_p)
2122 fixed_p = 0;
2123 else
2124 fixed_p = window_fixed_size_p (w, width_p, 1);
2125
2126 if (fixed)
2127 *fixed = fixed_p;
2128
2129 if (fixed_p)
2130 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2131 else
2132 size = window_min_size_1 (w, width_p);
2133
2134 return size;
2135 }
2136
2137
2138 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2139 WINDOW's width. Resize WINDOW's children, if any, so that they
2140 keep their proportionate size relative to WINDOW. Propagate
2141 WINDOW's top or left edge position to children. Delete windows
2142 that become too small unless NODELETE_P is non-zero. */
2143
2144 static void
2145 size_window (window, size, width_p, nodelete_p)
2146 Lisp_Object window;
2147 int size, width_p, nodelete_p;
2148 {
2149 struct window *w = XWINDOW (window);
2150 struct window *c;
2151 Lisp_Object child, *forward, *sideward;
2152 int old_size, min_size;
2153
2154 check_min_window_sizes ();
2155
2156 /* If the window has been "too small" at one point,
2157 don't delete it for being "too small" in the future.
2158 Preserve it as long as that is at all possible. */
2159 if (width_p)
2160 {
2161 old_size = XFASTINT (w->width);
2162 min_size = window_min_width;
2163 }
2164 else
2165 {
2166 old_size = XFASTINT (w->height);
2167 min_size = window_min_height;
2168 }
2169
2170 if (old_size < window_min_width)
2171 w->too_small_ok = Qt;
2172
2173 /* Maybe delete WINDOW if it's too small. */
2174 if (!nodelete_p && !NILP (w->parent))
2175 {
2176 int min_size;
2177
2178 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2179 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2180 else
2181 min_size = width_p ? window_min_width : window_min_height;
2182
2183 if (size < min_size)
2184 {
2185 delete_window (window);
2186 return;
2187 }
2188 }
2189
2190 /* Set redisplay hints. */
2191 XSETFASTINT (w->last_modified, 0);
2192 XSETFASTINT (w->last_overlay_modified, 0);
2193 windows_or_buffers_changed++;
2194 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
2195
2196 if (width_p)
2197 {
2198 sideward = &w->vchild;
2199 forward = &w->hchild;
2200 XSETFASTINT (w->width, size);
2201 }
2202 else
2203 {
2204 sideward = &w->hchild;
2205 forward = &w->vchild;
2206 XSETFASTINT (w->height, size);
2207 }
2208
2209 if (!NILP (*sideward))
2210 {
2211 for (child = *sideward; !NILP (child); child = c->next)
2212 {
2213 c = XWINDOW (child);
2214 if (width_p)
2215 c->left = w->left;
2216 else
2217 c->top = w->top;
2218 size_window (child, size, width_p, nodelete_p);
2219 }
2220 }
2221 else if (!NILP (*forward))
2222 {
2223 int fixed_size, each, extra, n;
2224 int resize_fixed_p, nfixed;
2225 int last_pos, first_pos, nchildren;
2226
2227 /* Determine the fixed-size portion of the this window, and the
2228 number of child windows. */
2229 fixed_size = nchildren = nfixed = 0;
2230 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2231 {
2232 c = XWINDOW (child);
2233 if (window_fixed_size_p (c, width_p, 0))
2234 {
2235 fixed_size += (width_p
2236 ? XFASTINT (c->width) : XFASTINT (c->height));
2237 ++nfixed;
2238 }
2239 }
2240
2241 /* If the new size is smaller than fixed_size, or if there
2242 aren't any resizable windows, allow resizing fixed-size
2243 windows. */
2244 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2245
2246 /* Compute how many lines/columns to add to each child. The
2247 value of extra takes care of rounding errors. */
2248 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2249 each = (size - old_size) / n;
2250 extra = (size - old_size) - n * each;
2251
2252 /* Compute new children heights and edge positions. */
2253 first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
2254 last_pos = first_pos;
2255 for (child = *forward; !NILP (child); child = c->next)
2256 {
2257 int new_size, old_size;
2258
2259 c = XWINDOW (child);
2260 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2261 new_size = old_size;
2262
2263 /* The top or left edge position of this child equals the
2264 bottom or right edge of its predecessor. */
2265 if (width_p)
2266 c->left = make_number (last_pos);
2267 else
2268 c->top = make_number (last_pos);
2269
2270 /* If this child can be resized, do it. */
2271 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2272 {
2273 new_size = old_size + each + extra;
2274 extra = 0;
2275 }
2276
2277 /* Set new height. Note that size_window also propagates
2278 edge positions to children, so it's not a no-op if we
2279 didn't change the child's size. */
2280 size_window (child, new_size, width_p, 1);
2281
2282 /* Remember the bottom/right edge position of this child; it
2283 will be used to set the top/left edge of the next child. */
2284 last_pos += new_size;
2285 }
2286
2287 /* We should have covered the parent exactly with child windows. */
2288 xassert (size == last_pos - first_pos);
2289
2290 /* Now delete any children that became too small. */
2291 if (!nodelete_p)
2292 for (child = *forward; !NILP (child); child = c->next)
2293 {
2294 int child_size;
2295 c = XWINDOW (child);
2296 child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2297 size_window (child, child_size, width_p, 0);
2298 }
2299 }
2300 }
2301
2302 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2303 WINDOW's children. NODELETE non-zero means don't delete windows
2304 that become too small in the process. (The caller should check
2305 later and do so if appropriate.) */
2306
2307 void
2308 set_window_height (window, height, nodelete)
2309 Lisp_Object window;
2310 int height;
2311 int nodelete;
2312 {
2313 size_window (window, height, 0, nodelete);
2314 }
2315
2316
2317 /* Set WINDOW's width to WIDTH, and recursively change the width of
2318 WINDOW's children. NODELETE non-zero means don't delete windows
2319 that become too small in the process. (The caller should check
2320 later and do so if appropriate.) */
2321
2322 void
2323 set_window_width (window, width, nodelete)
2324 Lisp_Object window;
2325 int width;
2326 int nodelete;
2327 {
2328 size_window (window, width, 1, nodelete);
2329 }
2330
2331 \f
2332 int window_select_count;
2333
2334 Lisp_Object
2335 Fset_window_buffer_unwind (obuf)
2336 Lisp_Object obuf;
2337 {
2338 Fset_buffer (obuf);
2339 return Qnil;
2340 }
2341
2342
2343 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2344 means it's allowed to run hooks. See make_frame for a case where
2345 it's not allowed. */
2346
2347 void
2348 set_window_buffer (window, buffer, run_hooks_p)
2349 Lisp_Object window, buffer;
2350 int run_hooks_p;
2351 {
2352 struct window *w = XWINDOW (window);
2353 struct buffer *b = XBUFFER (buffer);
2354 int count = specpdl_ptr - specpdl;
2355
2356 w->buffer = buffer;
2357
2358 if (EQ (window, selected_window))
2359 b->last_selected_window = window;
2360
2361 /* Update time stamps of buffer display. */
2362 if (INTEGERP (b->display_count))
2363 XSETINT (b->display_count, XINT (b->display_count) + 1);
2364 b->display_time = Fcurrent_time ();
2365
2366 XSETFASTINT (w->window_end_pos, 0);
2367 XSETFASTINT (w->window_end_vpos, 0);
2368 bzero (&w->last_cursor, sizeof w->last_cursor);
2369 w->window_end_valid = Qnil;
2370 XSETFASTINT (w->hscroll, 0);
2371 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2372 set_marker_restricted (w->start,
2373 make_number (b->last_window_start),
2374 buffer);
2375 w->start_at_line_beg = Qnil;
2376 w->force_start = Qnil;
2377 XSETFASTINT (w->last_modified, 0);
2378 XSETFASTINT (w->last_overlay_modified, 0);
2379 windows_or_buffers_changed++;
2380
2381 /* We must select BUFFER for running the window-scroll-functions.
2382 If WINDOW is selected, switch permanently.
2383 Otherwise, switch but go back to the ambient buffer afterward. */
2384 if (EQ (window, selected_window))
2385 Fset_buffer (buffer);
2386 /* We can't check ! NILP (Vwindow_scroll_functions) here
2387 because that might itself be a local variable. */
2388 else if (window_initialized)
2389 {
2390 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2391 Fset_buffer (buffer);
2392 }
2393
2394 /* Set left and right marginal area width from buffer. */
2395 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
2396
2397 if (run_hooks_p)
2398 {
2399 if (! NILP (Vwindow_scroll_functions))
2400 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2401 Fmarker_position (w->start));
2402
2403 if (! NILP (Vwindow_configuration_change_hook)
2404 && ! NILP (Vrun_hooks))
2405 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2406 }
2407
2408 unbind_to (count, Qnil);
2409 }
2410
2411
2412 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2413 "Make WINDOW display BUFFER as its contents.\n\
2414 BUFFER can be a buffer or buffer name.")
2415 (window, buffer)
2416 register Lisp_Object window, buffer;
2417 {
2418 register Lisp_Object tem;
2419 register struct window *w = decode_window (window);
2420
2421 buffer = Fget_buffer (buffer);
2422 CHECK_BUFFER (buffer, 1);
2423
2424 if (NILP (XBUFFER (buffer)->name))
2425 error ("Attempt to display deleted buffer");
2426
2427 tem = w->buffer;
2428 if (NILP (tem))
2429 error ("Window is deleted");
2430 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2431 is first being set up. */
2432 {
2433 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2434 error ("Window is dedicated to `%s'",
2435 XSTRING (XBUFFER (tem)->name)->data);
2436
2437 unshow_buffer (w);
2438 }
2439
2440 set_window_buffer (window, buffer, 1);
2441 return Qnil;
2442 }
2443
2444 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2445 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
2446 If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2447 Note that the main editor command loop\n\
2448 selects the buffer of the selected window before each command.")
2449 (window)
2450 register Lisp_Object window;
2451 {
2452 return select_window_1 (window, 1);
2453 }
2454 \f
2455 static Lisp_Object
2456 select_window_1 (window, recordflag)
2457 register Lisp_Object window;
2458 int recordflag;
2459 {
2460 register struct window *w;
2461 register struct window *ow = XWINDOW (selected_window);
2462 struct frame *sf;
2463
2464 CHECK_LIVE_WINDOW (window, 0);
2465
2466 w = XWINDOW (window);
2467
2468 if (NILP (w->buffer))
2469 error ("Trying to select deleted window or non-leaf window");
2470
2471 XSETFASTINT (w->use_time, ++window_select_count);
2472 if (EQ (window, selected_window))
2473 return window;
2474
2475 if (! NILP (ow->buffer))
2476 set_marker_both (ow->pointm, ow->buffer,
2477 BUF_PT (XBUFFER (ow->buffer)),
2478 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2479
2480 selected_window = window;
2481 sf = SELECTED_FRAME ();
2482 if (XFRAME (WINDOW_FRAME (w)) != sf)
2483 {
2484 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2485 /* Use this rather than Fhandle_switch_frame
2486 so that FRAME_FOCUS_FRAME is moved appropriately as we
2487 move around in the state where a minibuffer in a separate
2488 frame is active. */
2489 Fselect_frame (WINDOW_FRAME (w), Qnil);
2490 }
2491 else
2492 sf->selected_window = window;
2493
2494 if (recordflag)
2495 record_buffer (w->buffer);
2496 Fset_buffer (w->buffer);
2497
2498 XBUFFER (w->buffer)->last_selected_window = window;
2499
2500 /* Go to the point recorded in the window.
2501 This is important when the buffer is in more
2502 than one window. It also matters when
2503 redisplay_window has altered point after scrolling,
2504 because it makes the change only in the window. */
2505 {
2506 register int new_point = marker_position (w->pointm);
2507 if (new_point < BEGV)
2508 SET_PT (BEGV);
2509 else if (new_point > ZV)
2510 SET_PT (ZV);
2511 else
2512 SET_PT (new_point);
2513 }
2514
2515 windows_or_buffers_changed++;
2516 return window;
2517 }
2518 \f
2519 /* Deiconify the frame containing the window WINDOW,
2520 unless it is the selected frame;
2521 then return WINDOW.
2522
2523 The reason for the exception for the selected frame
2524 is that it seems better not to change the selected frames visibility
2525 merely because of displaying a different buffer in it.
2526 The deiconification is useful when a buffer gets shown in
2527 another frame that you were not using lately. */
2528
2529 static Lisp_Object
2530 display_buffer_1 (window)
2531 Lisp_Object window;
2532 {
2533 Lisp_Object frame = XWINDOW (window)->frame;
2534 FRAME_PTR f = XFRAME (frame);
2535
2536 FRAME_SAMPLE_VISIBILITY (f);
2537
2538 if (!EQ (frame, selected_frame))
2539 {
2540 if (FRAME_ICONIFIED_P (f))
2541 Fmake_frame_visible (frame);
2542 else if (FRAME_VISIBLE_P (f))
2543 Fraise_frame (frame);
2544 }
2545
2546 return window;
2547 }
2548
2549 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2550 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2551 The value is actually t if the frame should be called with default frame\n\
2552 parameters, and a list of frame parameters if they were specified.\n\
2553 See `special-display-buffer-names', and `special-display-regexps'.")
2554 (buffer_name)
2555 Lisp_Object buffer_name;
2556 {
2557 Lisp_Object tem;
2558
2559 CHECK_STRING (buffer_name, 1);
2560
2561 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2562 if (!NILP (tem))
2563 return Qt;
2564
2565 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2566 if (!NILP (tem))
2567 return XCDR (tem);
2568
2569 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2570 {
2571 Lisp_Object car = XCAR (tem);
2572 if (STRINGP (car)
2573 && fast_string_match (car, buffer_name) >= 0)
2574 return Qt;
2575 else if (CONSP (car)
2576 && STRINGP (XCAR (car))
2577 && fast_string_match (XCAR (car), buffer_name) >= 0)
2578 return XCDR (car);
2579 }
2580 return Qnil;
2581 }
2582
2583 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2584 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
2585 See `same-window-buffer-names' and `same-window-regexps'.")
2586 (buffer_name)
2587 Lisp_Object buffer_name;
2588 {
2589 Lisp_Object tem;
2590
2591 CHECK_STRING (buffer_name, 1);
2592
2593 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2594 if (!NILP (tem))
2595 return Qt;
2596
2597 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2598 if (!NILP (tem))
2599 return Qt;
2600
2601 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2602 {
2603 Lisp_Object car = XCAR (tem);
2604 if (STRINGP (car)
2605 && fast_string_match (car, buffer_name) >= 0)
2606 return Qt;
2607 else if (CONSP (car)
2608 && STRINGP (XCAR (car))
2609 && fast_string_match (XCAR (car), buffer_name) >= 0)
2610 return Qt;
2611 }
2612 return Qnil;
2613 }
2614
2615 /* Use B so the default is (other-buffer). */
2616 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2617 "BDisplay buffer: \nP",
2618 "Make BUFFER appear in some window but don't select it.\n\
2619 BUFFER can be a buffer or a buffer name.\n\
2620 If BUFFER is shown already in some window, just use that one,\n\
2621 unless the window is the selected window and the optional second\n\
2622 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
2623 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
2624 Returns the window displaying BUFFER.\n\
2625 \n\
2626 The variables `special-display-buffer-names', `special-display-regexps',\n\
2627 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
2628 buffer names are handled.\n\
2629 \n\
2630 If optional argument FRAME is `visible', search all visible frames.\n\
2631 If FRAME is 0, search all visible and iconified frames.\n\
2632 If FRAME is t, search all frames.\n\
2633 If FRAME is a frame, search only that frame.\n\
2634 If FRAME is nil, search only the selected frame\n\
2635 (actually the last nonminibuffer frame),\n\
2636 unless `pop-up-frames' is non-nil,\n\
2637 which means search visible and iconified frames.")
2638 (buffer, not_this_window, frame)
2639 register Lisp_Object buffer, not_this_window, frame;
2640 {
2641 register Lisp_Object window, tem, swp;
2642 struct frame *f;
2643
2644 swp = Qnil;
2645 buffer = Fget_buffer (buffer);
2646 CHECK_BUFFER (buffer, 0);
2647
2648 if (!NILP (Vdisplay_buffer_function))
2649 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2650
2651 if (NILP (not_this_window)
2652 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
2653 return display_buffer_1 (selected_window);
2654
2655 /* See if the user has specified this buffer should appear
2656 in the selected window. */
2657 if (NILP (not_this_window))
2658 {
2659 swp = Fsame_window_p (XBUFFER (buffer)->name);
2660 if (!NILP (swp) && !no_switch_window (selected_window))
2661 {
2662 Fswitch_to_buffer (buffer, Qnil);
2663 return display_buffer_1 (selected_window);
2664 }
2665 }
2666
2667 /* If pop_up_frames,
2668 look for a window showing BUFFER on any visible or iconified frame.
2669 Otherwise search only the current frame. */
2670 if (! NILP (frame))
2671 tem = frame;
2672 else if (pop_up_frames || last_nonminibuf_frame == 0)
2673 XSETFASTINT (tem, 0);
2674 else
2675 XSETFRAME (tem, last_nonminibuf_frame);
2676 window = Fget_buffer_window (buffer, tem);
2677 if (!NILP (window)
2678 && (NILP (not_this_window) || !EQ (window, selected_window)))
2679 {
2680 return display_buffer_1 (window);
2681 }
2682
2683 /* Certain buffer names get special handling. */
2684 if (!NILP (Vspecial_display_function) && NILP (swp))
2685 {
2686 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2687 if (EQ (tem, Qt))
2688 return call1 (Vspecial_display_function, buffer);
2689 if (CONSP (tem))
2690 return call2 (Vspecial_display_function, buffer, tem);
2691 }
2692
2693 /* If there are no frames open that have more than a minibuffer,
2694 we need to create a new frame. */
2695 if (pop_up_frames || last_nonminibuf_frame == 0)
2696 {
2697 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2698 Fset_window_buffer (window, buffer);
2699 return display_buffer_1 (window);
2700 }
2701
2702 f = SELECTED_FRAME ();
2703 if (pop_up_windows
2704 || FRAME_MINIBUF_ONLY_P (f)
2705 /* If the current frame is a special display frame,
2706 don't try to reuse its windows. */
2707 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
2708 {
2709 Lisp_Object frames;
2710
2711 frames = Qnil;
2712 if (FRAME_MINIBUF_ONLY_P (f))
2713 XSETFRAME (frames, last_nonminibuf_frame);
2714 /* Don't try to create a window if would get an error */
2715 if (split_height_threshold < window_min_height << 1)
2716 split_height_threshold = window_min_height << 1;
2717
2718 /* Note that both Fget_largest_window and Fget_lru_window
2719 ignore minibuffers and dedicated windows.
2720 This means they can return nil. */
2721
2722 /* If the frame we would try to split cannot be split,
2723 try other frames. */
2724 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
2725 {
2726 /* Try visible frames first. */
2727 window = Fget_largest_window (Qvisible);
2728 /* If that didn't work, try iconified frames. */
2729 if (NILP (window))
2730 window = Fget_largest_window (make_number (0));
2731 if (NILP (window))
2732 window = Fget_largest_window (Qt);
2733 }
2734 else
2735 window = Fget_largest_window (frames);
2736
2737 /* If we got a tall enough full-width window that can be split,
2738 split it. */
2739 if (!NILP (window)
2740 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2741 && window_height (window) >= split_height_threshold
2742 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
2743 window = Fsplit_window (window, Qnil, Qnil);
2744 else
2745 {
2746 Lisp_Object upper, lower, other;
2747
2748 window = Fget_lru_window (frames);
2749 /* If the LRU window is selected, and big enough,
2750 and can be split, split it. */
2751 if (!NILP (window)
2752 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2753 && (EQ (window, selected_window)
2754 || EQ (XWINDOW (window)->parent, Qnil))
2755 && window_height (window) >= window_min_height << 1)
2756 window = Fsplit_window (window, Qnil, Qnil);
2757 /* If Fget_lru_window returned nil, try other approaches. */
2758
2759 /* Try visible frames first. */
2760 if (NILP (window))
2761 window = Fget_buffer_window (buffer, Qvisible);
2762 if (NILP (window))
2763 window = Fget_largest_window (Qvisible);
2764 /* If that didn't work, try iconified frames. */
2765 if (NILP (window))
2766 window = Fget_buffer_window (buffer, make_number (0));
2767 if (NILP (window))
2768 window = Fget_largest_window (make_number (0));
2769 /* Try invisible frames. */
2770 if (NILP (window))
2771 window = Fget_buffer_window (buffer, Qt);
2772 if (NILP (window))
2773 window = Fget_largest_window (Qt);
2774 /* As a last resort, make a new frame. */
2775 if (NILP (window))
2776 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2777 /* If window appears above or below another,
2778 even out their heights. */
2779 other = upper = lower = Qnil;
2780 if (!NILP (XWINDOW (window)->prev))
2781 other = upper = XWINDOW (window)->prev, lower = window;
2782 if (!NILP (XWINDOW (window)->next))
2783 other = lower = XWINDOW (window)->next, upper = window;
2784 if (!NILP (other)
2785 /* Check that OTHER and WINDOW are vertically arrayed. */
2786 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2787 && (XFASTINT (XWINDOW (other)->height)
2788 > XFASTINT (XWINDOW (window)->height)))
2789 {
2790 int total = (XFASTINT (XWINDOW (other)->height)
2791 + XFASTINT (XWINDOW (window)->height));
2792 enlarge_window (upper,
2793 total / 2 - XFASTINT (XWINDOW (upper)->height),
2794 0);
2795 }
2796 }
2797 }
2798 else
2799 window = Fget_lru_window (Qnil);
2800
2801 Fset_window_buffer (window, buffer);
2802 return display_buffer_1 (window);
2803 }
2804
2805 void
2806 temp_output_buffer_show (buf)
2807 register Lisp_Object buf;
2808 {
2809 register struct buffer *old = current_buffer;
2810 register Lisp_Object window;
2811 register struct window *w;
2812
2813 XBUFFER (buf)->directory = current_buffer->directory;
2814
2815 Fset_buffer (buf);
2816 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
2817 BEGV = BEG;
2818 ZV = Z;
2819 SET_PT (BEG);
2820 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
2821 set_buffer_internal (old);
2822
2823 if (!EQ (Vtemp_buffer_show_function, Qnil))
2824 call1 (Vtemp_buffer_show_function, buf);
2825 else
2826 {
2827 window = Fdisplay_buffer (buf, Qnil, Qnil);
2828
2829 if (!EQ (XWINDOW (window)->frame, selected_frame))
2830 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2831 Vminibuf_scroll_window = window;
2832 w = XWINDOW (window);
2833 XSETFASTINT (w->hscroll, 0);
2834 set_marker_restricted_both (w->start, buf, 1, 1);
2835 set_marker_restricted_both (w->pointm, buf, 1, 1);
2836
2837 /* Run temp-buffer-show-hook, with the chosen window selected
2838 and it sbuffer current. */
2839 if (!NILP (Vrun_hooks))
2840 {
2841 Lisp_Object tem;
2842 tem = Fboundp (Qtemp_buffer_show_hook);
2843 if (!NILP (tem))
2844 {
2845 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2846 if (!NILP (tem))
2847 {
2848 int count = specpdl_ptr - specpdl;
2849 Lisp_Object prev_window;
2850 prev_window = selected_window;
2851
2852 /* Select the window that was chosen, for running the hook. */
2853 record_unwind_protect (Fselect_window, prev_window);
2854 select_window_1 (window, 0);
2855 Fset_buffer (w->buffer);
2856 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2857 select_window_1 (prev_window, 0);
2858 unbind_to (count, Qnil);
2859 }
2860 }
2861 }
2862 }
2863 }
2864 \f
2865 static void
2866 make_dummy_parent (window)
2867 Lisp_Object window;
2868 {
2869 Lisp_Object new;
2870 register struct window *o, *p;
2871 register struct Lisp_Vector *vec;
2872 int i;
2873
2874 o = XWINDOW (window);
2875 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2876 for (i = 0; i < VECSIZE (struct window); ++i)
2877 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2878 vec->size = VECSIZE (struct window);
2879 p = (struct window *)vec;
2880 XSETWINDOW (new, p);
2881
2882 XSETFASTINT (p->sequence_number, ++sequence_number);
2883
2884 /* Put new into window structure in place of window */
2885 replace_window (window, new);
2886
2887 o->next = Qnil;
2888 o->prev = Qnil;
2889 o->vchild = Qnil;
2890 o->hchild = Qnil;
2891 o->parent = new;
2892
2893 p->start = Qnil;
2894 p->pointm = Qnil;
2895 p->buffer = Qnil;
2896 }
2897
2898 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2899 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2900 WINDOW defaults to selected one and SIZE to half its size.\n\
2901 If optional third arg HORFLAG is non-nil, split side by side\n\
2902 and put SIZE columns in the first of the pair. In that case,\n\
2903 SIZE includes that window's scroll bar, or the divider column to its right.")
2904 (window, size, horflag)
2905 Lisp_Object window, size, horflag;
2906 {
2907 register Lisp_Object new;
2908 register struct window *o, *p;
2909 FRAME_PTR fo;
2910 register int size_int;
2911
2912 if (NILP (window))
2913 window = selected_window;
2914 else
2915 CHECK_LIVE_WINDOW (window, 0);
2916
2917 o = XWINDOW (window);
2918 fo = XFRAME (WINDOW_FRAME (o));
2919
2920 if (NILP (size))
2921 {
2922 if (!NILP (horflag))
2923 /* Calculate the size of the left-hand window, by dividing
2924 the usable space in columns by two.
2925 We round up, since the left-hand window may include
2926 a dividing line, while the right-hand may not. */
2927 size_int = (XFASTINT (o->width) + 1) >> 1;
2928 else
2929 size_int = XFASTINT (o->height) >> 1;
2930 }
2931 else
2932 {
2933 CHECK_NUMBER (size, 1);
2934 size_int = XINT (size);
2935 }
2936
2937 if (MINI_WINDOW_P (o))
2938 error ("Attempt to split minibuffer window");
2939 else if (window_fixed_size_p (o, !NILP (horflag), 0))
2940 error ("Attempt to split fixed-size window");
2941
2942 check_min_window_sizes ();
2943
2944 if (NILP (horflag))
2945 {
2946 if (size_int < window_min_height)
2947 error ("Window height %d too small (after splitting)", size_int);
2948 if (size_int + window_min_height > XFASTINT (o->height))
2949 error ("Window height %d too small (after splitting)",
2950 XFASTINT (o->height) - size_int);
2951 if (NILP (o->parent)
2952 || NILP (XWINDOW (o->parent)->vchild))
2953 {
2954 make_dummy_parent (window);
2955 new = o->parent;
2956 XWINDOW (new)->vchild = window;
2957 }
2958 }
2959 else
2960 {
2961 if (size_int < window_min_width)
2962 error ("Window width %d too small (after splitting)", size_int);
2963
2964 if (size_int + window_min_width > XFASTINT (o->width))
2965 error ("Window width %d too small (after splitting)",
2966 XFASTINT (o->width) - size_int);
2967 if (NILP (o->parent)
2968 || NILP (XWINDOW (o->parent)->hchild))
2969 {
2970 make_dummy_parent (window);
2971 new = o->parent;
2972 XWINDOW (new)->hchild = window;
2973 }
2974 }
2975
2976 /* Now we know that window's parent is a vertical combination
2977 if we are dividing vertically, or a horizontal combination
2978 if we are making side-by-side windows */
2979
2980 windows_or_buffers_changed++;
2981 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
2982 new = make_window ();
2983 p = XWINDOW (new);
2984
2985 p->frame = o->frame;
2986 p->next = o->next;
2987 if (!NILP (p->next))
2988 XWINDOW (p->next)->prev = new;
2989 p->prev = window;
2990 o->next = new;
2991 p->parent = o->parent;
2992 p->buffer = Qt;
2993 p->window_end_valid = Qnil;
2994 bzero (&p->last_cursor, sizeof p->last_cursor);
2995
2996 /* Apportion the available frame space among the two new windows */
2997
2998 if (!NILP (horflag))
2999 {
3000 p->height = o->height;
3001 p->top = o->top;
3002 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
3003 XSETFASTINT (o->width, size_int);
3004 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
3005 }
3006 else
3007 {
3008 p->left = o->left;
3009 p->width = o->width;
3010 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3011 XSETFASTINT (o->height, size_int);
3012 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
3013 }
3014
3015 /* Adjust glyph matrices. */
3016 adjust_glyphs (fo);
3017 Fset_window_buffer (new, o->buffer);
3018 return new;
3019 }
3020 \f
3021 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3022 "Make current window ARG lines bigger.\n\
3023 From program, optional second arg non-nil means grow sideways ARG columns.")
3024 (arg, side)
3025 register Lisp_Object arg, side;
3026 {
3027 CHECK_NUMBER (arg, 0);
3028 enlarge_window (selected_window, XINT (arg), !NILP (side));
3029
3030 if (! NILP (Vwindow_configuration_change_hook))
3031 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3032
3033 return Qnil;
3034 }
3035
3036 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3037 "Make current window ARG lines smaller.\n\
3038 From program, optional second arg non-nil means shrink sideways arg columns.")
3039 (arg, side)
3040 register Lisp_Object arg, side;
3041 {
3042 CHECK_NUMBER (arg, 0);
3043 enlarge_window (selected_window, -XINT (arg), !NILP (side));
3044
3045 if (! NILP (Vwindow_configuration_change_hook))
3046 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3047
3048 return Qnil;
3049 }
3050
3051 int
3052 window_height (window)
3053 Lisp_Object window;
3054 {
3055 register struct window *p = XWINDOW (window);
3056 return XFASTINT (p->height);
3057 }
3058
3059 int
3060 window_width (window)
3061 Lisp_Object window;
3062 {
3063 register struct window *p = XWINDOW (window);
3064 return XFASTINT (p->width);
3065 }
3066
3067
3068 #define CURBEG(w) \
3069 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
3070
3071 #define CURSIZE(w) \
3072 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
3073
3074
3075 /* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3076 increase its width. Siblings of the selected window are resized to
3077 fullfil the size request. If they become too small in the process,
3078 they will be deleted. */
3079
3080 static void
3081 enlarge_window (window, delta, widthflag)
3082 Lisp_Object window;
3083 int delta, widthflag;
3084 {
3085 Lisp_Object parent, next, prev;
3086 struct window *p;
3087 int *sizep, maximum;
3088 int (*sizefun) P_ ((Lisp_Object))
3089 = widthflag ? window_width : window_height;
3090 void (*setsizefun) P_ ((Lisp_Object, int, int))
3091 = (widthflag ? set_window_width : set_window_height);
3092
3093 /* Check values of window_min_width and window_min_height for
3094 validity. */
3095 check_min_window_sizes ();
3096
3097 /* Give up if this window cannot be resized. */
3098 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3099 error ("Window is not resizable");
3100
3101 /* Find the parent of the selected window. */
3102 while (1)
3103 {
3104 p = XWINDOW (window);
3105 parent = p->parent;
3106
3107 if (NILP (parent))
3108 {
3109 if (widthflag)
3110 error ("No other window to side of this one");
3111 break;
3112 }
3113
3114 if (widthflag
3115 ? !NILP (XWINDOW (parent)->hchild)
3116 : !NILP (XWINDOW (parent)->vchild))
3117 break;
3118
3119 window = parent;
3120 }
3121
3122 sizep = &CURSIZE (window);
3123
3124 {
3125 register int maxdelta;
3126
3127 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
3128 : !NILP (p->next) ? ((*sizefun) (p->next)
3129 - window_min_size (XWINDOW (p->next),
3130 widthflag, 0, 0))
3131 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3132 - window_min_size (XWINDOW (p->prev),
3133 widthflag, 0, 0))
3134 /* This is a frame with only one window, a minibuffer-only
3135 or a minibufferless frame. */
3136 : (delta = 0));
3137
3138 if (delta > maxdelta)
3139 /* This case traps trying to make the minibuffer
3140 the full frame, or make the only window aside from the
3141 minibuffer the full frame. */
3142 delta = maxdelta;
3143 }
3144
3145 if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3146 {
3147 delete_window (window);
3148 return;
3149 }
3150
3151 if (delta == 0)
3152 return;
3153
3154 /* Find the total we can get from other siblings. */
3155 maximum = 0;
3156 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3157 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3158 widthflag, 0, 0);
3159 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3160 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3161 widthflag, 0, 0);
3162
3163 /* If we can get it all from them, do so. */
3164 if (delta <= maximum)
3165 {
3166 Lisp_Object first_unaffected;
3167 Lisp_Object first_affected;
3168 int fixed_p;
3169
3170 next = p->next;
3171 prev = p->prev;
3172 first_affected = window;
3173 /* Look at one sibling at a time,
3174 moving away from this window in both directions alternately,
3175 and take as much as we can get without deleting that sibling. */
3176 while (delta != 0 && (!NILP (next) || !NILP (prev)))
3177 {
3178 if (! NILP (next))
3179 {
3180 int this_one = ((*sizefun) (next)
3181 - window_min_size (XWINDOW (next),
3182 widthflag, 0, &fixed_p));
3183 if (!fixed_p)
3184 {
3185 if (this_one > delta)
3186 this_one = delta;
3187
3188 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3189 (*setsizefun) (window, *sizep + this_one, 0);
3190
3191 delta -= this_one;
3192 }
3193
3194 next = XWINDOW (next)->next;
3195 }
3196
3197 if (delta == 0)
3198 break;
3199
3200 if (! NILP (prev))
3201 {
3202 int this_one = ((*sizefun) (prev)
3203 - window_min_size (XWINDOW (prev),
3204 widthflag, 0, &fixed_p));
3205 if (!fixed_p)
3206 {
3207 if (this_one > delta)
3208 this_one = delta;
3209
3210 first_affected = prev;
3211
3212 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3213 (*setsizefun) (window, *sizep + this_one, 0);
3214
3215 delta -= this_one;
3216 }
3217
3218 prev = XWINDOW (prev)->prev;
3219 }
3220 }
3221
3222 xassert (delta == 0);
3223
3224 /* Now recalculate the edge positions of all the windows affected,
3225 based on the new sizes. */
3226 first_unaffected = next;
3227 prev = first_affected;
3228 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3229 prev = next, next = XWINDOW (next)->next)
3230 {
3231 CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
3232 /* This does not change size of NEXT,
3233 but it propagates the new top edge to its children */
3234 (*setsizefun) (next, (*sizefun) (next), 0);
3235 }
3236 }
3237 else
3238 {
3239 register int delta1;
3240 register int opht = (*sizefun) (parent);
3241
3242 /* If trying to grow this window to or beyond size of the parent,
3243 make delta1 so big that, on shrinking back down,
3244 all the siblings end up with less than one line and are deleted. */
3245 if (opht <= *sizep + delta)
3246 delta1 = opht * opht * 2;
3247 else
3248 {
3249 /* Otherwise, make delta1 just right so that if we add
3250 delta1 lines to this window and to the parent, and then
3251 shrink the parent back to its original size, the new
3252 proportional size of this window will increase by delta.
3253
3254 The function size_window will compute the new height h'
3255 of the window from delta1 as:
3256
3257 e = delta1/n
3258 x = delta1 - delta1/n * n for the 1st resizable child
3259 h' = h + e + x
3260
3261 where n is the number of children that can be resized.
3262 We can ignore x by choosing a delta1 that is a multiple of
3263 n. We want the height of this window to come out as
3264
3265 h' = h + delta
3266
3267 So, delta1 must be
3268
3269 h + e = h + delta
3270 delta1/n = delta
3271 delta1 = n * delta.
3272
3273 The number of children n rquals the number of resizable
3274 children of this window + 1 because we know window itself
3275 is resizable (otherwise we would have signalled an error. */
3276
3277 struct window *w = XWINDOW (window);
3278 Lisp_Object s;
3279 int n = 1;
3280
3281 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3282 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3283 ++n;
3284 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3285 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3286 ++n;
3287
3288 delta1 = n * delta;
3289 }
3290
3291 /* Add delta1 lines or columns to this window, and to the parent,
3292 keeping things consistent while not affecting siblings. */
3293 CURSIZE (parent) = opht + delta1;
3294 (*setsizefun) (window, *sizep + delta1, 0);
3295
3296 /* Squeeze out delta1 lines or columns from our parent,
3297 shriking this window and siblings proportionately.
3298 This brings parent back to correct size.
3299 Delta1 was calculated so this makes this window the desired size,
3300 taking it all out of the siblings. */
3301 (*setsizefun) (parent, opht, 0);
3302 }
3303
3304 XSETFASTINT (p->last_modified, 0);
3305 XSETFASTINT (p->last_overlay_modified, 0);
3306
3307 /* Adjust glyph matrices. */
3308 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3309 }
3310
3311 #undef CURBEG
3312 #undef CURSIZE
3313
3314
3315 \f
3316 /***********************************************************************
3317 Resizing Mini-Windows
3318 ***********************************************************************/
3319
3320 static void shrink_window_lowest_first P_ ((struct window *, int));
3321 static void save_restore_orig_size P_ ((struct window *, int));
3322
3323
3324 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3325 from lowest windows first. */
3326
3327 static void
3328 shrink_window_lowest_first (w, height)
3329 struct window *w;
3330 int height;
3331 {
3332 struct window *c;
3333 Lisp_Object child;
3334 int old_height;
3335
3336 xassert (!MINI_WINDOW_P (w));
3337
3338 /* Set redisplay hints. */
3339 XSETFASTINT (w->last_modified, 0);
3340 XSETFASTINT (w->last_overlay_modified, 0);
3341 windows_or_buffers_changed++;
3342 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3343
3344 old_height = XFASTINT (w->height);
3345 XSETFASTINT (w->height, height);
3346
3347 if (!NILP (w->hchild))
3348 {
3349 for (child = w->hchild; !NILP (child); child = c->next)
3350 {
3351 c = XWINDOW (child);
3352 c->top = w->top;
3353 shrink_window_lowest_first (c, height);
3354 }
3355 }
3356 else if (!NILP (w->vchild))
3357 {
3358 Lisp_Object last_child;
3359 int delta = old_height - height;
3360 int last_top;
3361
3362 /* Find the last child. We are taking space from lowest windows
3363 first, so we iterate over children from the last child
3364 backwards. */
3365 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3366 last_child = child;
3367
3368 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3369 for (child = last_child; delta && !NILP (child); child = c->prev)
3370 {
3371 int this_one;
3372
3373 c = XWINDOW (child);
3374 this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
3375
3376 if (this_one > delta)
3377 this_one = delta;
3378
3379 shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
3380 delta -= this_one;
3381 }
3382
3383 /* Compute new positions. */
3384 last_top = w->top;
3385 for (child = w->vchild; !NILP (child); child = c->next)
3386 {
3387 c = XWINDOW (child);
3388 c->top = make_number (last_top);
3389 shrink_window_lowest_first (c, XFASTINT (c->height));
3390 last_top += XFASTINT (c->height);
3391 }
3392 }
3393 }
3394
3395
3396 /* Save or restore positions and sizes in the window tree rooted at W.
3397 SAVE_P non-zero means save top position and height in orig_top and
3398 orig_height members of the window structure. Otherwise, restore top
3399 and height from orig_top and orig_height. */
3400
3401 static void
3402 save_restore_orig_size (w, save_p)
3403 struct window *w;
3404 int save_p;
3405 {
3406 while (w)
3407 {
3408 if (!NILP (w->hchild))
3409 save_restore_orig_size (XWINDOW (w->hchild), save_p);
3410 else if (!NILP (w->vchild))
3411 save_restore_orig_size (XWINDOW (w->vchild), save_p);
3412
3413 if (save_p)
3414 {
3415 w->orig_top = w->top;
3416 w->orig_height = w->height;
3417 }
3418 else
3419 {
3420 xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
3421 w->top = w->orig_top;
3422 w->height = w->orig_height;
3423 w->orig_height = w->orig_top = Qnil;
3424 }
3425
3426 XSETFASTINT (w->last_modified, 0);
3427 XSETFASTINT (w->last_overlay_modified, 0);
3428 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3429 }
3430 }
3431
3432
3433 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3434 without deleting other windows. */
3435
3436 void
3437 grow_mini_window (w, delta)
3438 struct window *w;
3439 int delta;
3440 {
3441 struct frame *f = XFRAME (w->frame);
3442 struct window *root;
3443
3444 xassert (MINI_WINDOW_P (w));
3445 xassert (delta >= 0);
3446
3447 /* Check values of window_min_width and window_min_height for
3448 validity. */
3449 check_min_window_sizes ();
3450
3451 /* Compute how much we can enlarge the mini-window without deleting
3452 other windows. */
3453 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3454 if (delta)
3455 {
3456 int min_height = window_min_size (root, 0, 0, 0);
3457 if (XFASTINT (root->height) - delta < min_height)
3458 delta = XFASTINT (root->height) - min_height;
3459 }
3460
3461 if (delta)
3462 {
3463 /* Save original window sizes and positions, if not already done. */
3464 if (NILP (root->orig_top))
3465 save_restore_orig_size (root, 1);
3466
3467 /* Shrink other windows. */
3468 shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
3469
3470 /* Grow the mini-window. */
3471 w->top = make_number (XFASTINT (root->top) + XFASTINT (root)->height);
3472 w->height = make_number (XFASTINT (w->height) + delta);
3473 XSETFASTINT (w->last_modified, 0);
3474 XSETFASTINT (w->last_overlay_modified, 0);
3475
3476 adjust_glyphs (f);
3477 }
3478 }
3479
3480
3481 /* Shrink mini-window W. If there is recorded info about window sizes
3482 before a call to grow_mini_window, restore recorded window sizes.
3483 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3484 line. */
3485
3486 void
3487 shrink_mini_window (w)
3488 struct window *w;
3489 {
3490 struct frame *f = XFRAME (w->frame);
3491 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
3492
3493 if (!NILP (root->orig_height))
3494 {
3495 save_restore_orig_size (root, 0);
3496 adjust_glyphs (f);
3497 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3498 windows_or_buffers_changed = 1;
3499 }
3500 else if (XFASTINT (w->height) > 1)
3501 {
3502 Lisp_Object window;
3503 XSETWINDOW (window, w);
3504 enlarge_window (window, 1 - XFASTINT (w->height), 0);
3505 }
3506 }
3507
3508
3509 \f
3510 /* Mark window cursors off for all windows in the window tree rooted
3511 at W by setting their phys_cursor_on_p flag to zero. Called from
3512 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3513 the frame are cleared. */
3514
3515 void
3516 mark_window_cursors_off (w)
3517 struct window *w;
3518 {
3519 while (w)
3520 {
3521 if (!NILP (w->hchild))
3522 mark_window_cursors_off (XWINDOW (w->hchild));
3523 else if (!NILP (w->vchild))
3524 mark_window_cursors_off (XWINDOW (w->vchild));
3525 else
3526 w->phys_cursor_on_p = 0;
3527
3528 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3529 }
3530 }
3531
3532
3533 /* Return number of lines of text (not counting mode line) in W. */
3534
3535 int
3536 window_internal_height (w)
3537 struct window *w;
3538 {
3539 int ht = XFASTINT (w->height);
3540
3541 if (MINI_WINDOW_P (w))
3542 return ht;
3543
3544 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
3545 || !NILP (w->next) || !NILP (w->prev)
3546 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
3547 return ht - 1;
3548
3549 return ht;
3550 }
3551
3552
3553 /* Return the number of columns in W.
3554 Don't count columns occupied by scroll bars or the vertical bar
3555 separating W from the sibling to its right. */
3556
3557 int
3558 window_internal_width (w)
3559 struct window *w;
3560 {
3561 struct frame *f = XFRAME (WINDOW_FRAME (w));
3562 int width = XINT (w->width);
3563
3564 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3565 /* Scroll bars occupy a few columns. */
3566 width -= FRAME_SCROLL_BAR_COLS (f);
3567 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3568 /* The column of `|' characters separating side-by-side windows
3569 occupies one column only. */
3570 width -= 1;
3571
3572 /* On window-systems, areas to the left and right of the window
3573 are used to display bitmaps there. */
3574 if (FRAME_WINDOW_P (f))
3575 width -= FRAME_FLAGS_AREA_COLS (f);
3576
3577 return width;
3578 }
3579
3580 \f
3581 /************************************************************************
3582 Window Scrolling
3583 ***********************************************************************/
3584
3585 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3586 one screen-full, which is defined as the height of the window minus
3587 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3588 instead. Negative values of N mean scroll down. NOERROR non-zero
3589 means don't signal an error if we try to move over BEGV or ZV,
3590 respectively. */
3591
3592 static void
3593 window_scroll (window, n, whole, noerror)
3594 Lisp_Object window;
3595 int n;
3596 int whole;
3597 int noerror;
3598 {
3599 /* If we must, use the pixel-based version which is much slower than
3600 the line-based one but can handle varying line heights. */
3601 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
3602 window_scroll_pixel_based (window, n, whole, noerror);
3603 else
3604 window_scroll_line_based (window, n, whole, noerror);
3605 }
3606
3607
3608 /* Implementation of window_scroll that works based on pixel line
3609 heights. See the comment of window_scroll for parameter
3610 descriptions. */
3611
3612 static void
3613 window_scroll_pixel_based (window, n, whole, noerror)
3614 Lisp_Object window;
3615 int n;
3616 int whole;
3617 int noerror;
3618 {
3619 struct it it;
3620 struct window *w = XWINDOW (window);
3621 struct text_pos start;
3622 Lisp_Object tem;
3623 int this_scroll_margin;
3624 int preserve_y;
3625
3626 SET_TEXT_POS_FROM_MARKER (start, w->start);
3627
3628 /* If PT is not visible in WINDOW, move back one half of
3629 the screen. */
3630 XSETFASTINT (tem, PT);
3631 tem = Fpos_visible_in_window_p (tem, window);
3632 if (NILP (tem))
3633 {
3634 /* Move backward half the height of the window. Performance note:
3635 vmotion used here is about 10% faster, but would give wrong
3636 results for variable height lines. */
3637 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3638 it.current_y = it.last_visible_y;
3639 move_it_vertically (&it, -it.last_visible_y / 2);
3640
3641 /* The function move_iterator_vertically may move over more than
3642 the specified y-distance. If it->w is small, e.g. a
3643 mini-buffer window, we may end up in front of the window's
3644 display area. This is the case when Start displaying at the
3645 start of the line containing PT in this case. */
3646 if (it.current_y <= 0)
3647 {
3648 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3649 move_it_vertically (&it, 0);
3650 it.current_y = 0;
3651 }
3652
3653 start = it.current.pos;
3654 }
3655
3656 /* If scroll_preserve_screen_position is non-zero, we try to set
3657 point in the same window line as it is now, so get that line. */
3658 if (!NILP (Vscroll_preserve_screen_position))
3659 {
3660 start_display (&it, w, start);
3661 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3662 preserve_y = it.current_y;
3663 }
3664 else
3665 preserve_y = -1;
3666
3667 /* Move iterator it from start the specified distance forward or
3668 backward. The result is the new window start. */
3669 start_display (&it, w, start);
3670 if (whole)
3671 {
3672 int screen_full = (it.last_visible_y
3673 - next_screen_context_lines * CANON_Y_UNIT (it.f));
3674 int direction = n < 0 ? -1 : 1;
3675 move_it_vertically (&it, direction * screen_full);
3676 }
3677 else
3678 move_it_by_lines (&it, n, 1);
3679
3680 /* End if we end up at ZV or BEGV. */
3681 if ((n > 0 && IT_CHARPOS (it) == ZV)
3682 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
3683 {
3684 if (noerror)
3685 return;
3686 else if (IT_CHARPOS (it) == ZV)
3687 Fsignal (Qend_of_buffer, Qnil);
3688 else
3689 Fsignal (Qbeginning_of_buffer, Qnil);
3690 }
3691
3692 /* Set the window start, and set up the window for redisplay. */
3693 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)), w->buffer);
3694 w->start_at_line_beg = Fbolp ();
3695 w->update_mode_line = Qt;
3696 XSETFASTINT (w->last_modified, 0);
3697 XSETFASTINT (w->last_overlay_modified, 0);
3698 /* Set force_start so that redisplay_window will run the
3699 window-scroll-functions. */
3700 w->force_start = Qt;
3701
3702 it.current_y = it.vpos = 0;
3703
3704 /* Preserve the screen position if we must. */
3705 if (preserve_y >= 0)
3706 {
3707 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
3708 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3709 }
3710 else
3711 {
3712 /* Move PT out of scroll margins. */
3713 this_scroll_margin = max (0, scroll_margin);
3714 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
3715 this_scroll_margin *= CANON_Y_UNIT (it.f);
3716
3717 if (n > 0)
3718 {
3719 /* We moved the window start towards ZV, so PT may be now
3720 in the scroll margin at the top. */
3721 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3722 while (it.current_y < this_scroll_margin)
3723 move_it_by_lines (&it, 1, 1);
3724 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3725 }
3726 else if (n < 0)
3727 {
3728 /* We moved the window start towards BEGV, so PT may be now
3729 in the scroll margin at the bottom. */
3730 move_it_to (&it, PT, -1,
3731 it.last_visible_y - this_scroll_margin - 1, -1,
3732 MOVE_TO_POS | MOVE_TO_Y);
3733
3734 /* Don't put point on a partially visible line at the end. */
3735 if (it.current_y + it.max_ascent + it.max_descent
3736 > it.last_visible_y)
3737 move_it_by_lines (&it, -1, 0);
3738
3739 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3740 }
3741 }
3742 }
3743
3744
3745 /* Implementation of window_scroll that works based on screen lines.
3746 See the comment of window_scroll for parameter descriptions. */
3747
3748 static void
3749 window_scroll_line_based (window, n, whole, noerror)
3750 Lisp_Object window;
3751 int n;
3752 int whole;
3753 int noerror;
3754 {
3755 register struct window *w = XWINDOW (window);
3756 register int opoint = PT, opoint_byte = PT_BYTE;
3757 register int pos, pos_byte;
3758 register int ht = window_internal_height (w);
3759 register Lisp_Object tem;
3760 int lose;
3761 Lisp_Object bolp;
3762 int startpos;
3763 struct position posit;
3764 int original_vpos;
3765
3766 startpos = marker_position (w->start);
3767
3768 posit = *compute_motion (startpos, 0, 0, 0,
3769 PT, ht, 0,
3770 window_internal_width (w), XINT (w->hscroll),
3771 0, w);
3772 original_vpos = posit.vpos;
3773
3774 XSETFASTINT (tem, PT);
3775 tem = Fpos_visible_in_window_p (tem, window);
3776
3777 if (NILP (tem))
3778 {
3779 Fvertical_motion (make_number (- (ht / 2)), window);
3780 startpos = PT;
3781 }
3782
3783 SET_PT (startpos);
3784 lose = n < 0 && PT == BEGV;
3785 Fvertical_motion (make_number (n), window);
3786 pos = PT;
3787 pos_byte = PT_BYTE;
3788 bolp = Fbolp ();
3789 SET_PT_BOTH (opoint, opoint_byte);
3790
3791 if (lose)
3792 {
3793 if (noerror)
3794 return;
3795 else
3796 Fsignal (Qbeginning_of_buffer, Qnil);
3797 }
3798
3799 if (pos < ZV)
3800 {
3801 int this_scroll_margin = scroll_margin;
3802
3803 /* Don't use a scroll margin that is negative or too large. */
3804 if (this_scroll_margin < 0)
3805 this_scroll_margin = 0;
3806
3807 if (XINT (w->height) < 4 * scroll_margin)
3808 this_scroll_margin = XINT (w->height) / 4;
3809
3810 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
3811 w->start_at_line_beg = bolp;
3812 w->update_mode_line = Qt;
3813 XSETFASTINT (w->last_modified, 0);
3814 XSETFASTINT (w->last_overlay_modified, 0);
3815 /* Set force_start so that redisplay_window will run
3816 the window-scroll-functions. */
3817 w->force_start = Qt;
3818
3819 if (whole && !NILP (Vscroll_preserve_screen_position))
3820 {
3821 SET_PT_BOTH (pos, pos_byte);
3822 Fvertical_motion (make_number (original_vpos), window);
3823 }
3824 /* If we scrolled forward, put point enough lines down
3825 that it is outside the scroll margin. */
3826 else if (n > 0)
3827 {
3828 int top_margin;
3829
3830 if (this_scroll_margin > 0)
3831 {
3832 SET_PT_BOTH (pos, pos_byte);
3833 Fvertical_motion (make_number (this_scroll_margin), window);
3834 top_margin = PT;
3835 }
3836 else
3837 top_margin = pos;
3838
3839 if (top_margin <= opoint)
3840 SET_PT_BOTH (opoint, opoint_byte);
3841 else if (!NILP (Vscroll_preserve_screen_position))
3842 {
3843 SET_PT_BOTH (pos, pos_byte);
3844 Fvertical_motion (make_number (original_vpos), window);
3845 }
3846 else
3847 SET_PT (top_margin);
3848 }
3849 else if (n < 0)
3850 {
3851 int bottom_margin;
3852
3853 /* If we scrolled backward, put point near the end of the window
3854 but not within the scroll margin. */
3855 SET_PT_BOTH (pos, pos_byte);
3856 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
3857 if (XFASTINT (tem) == ht - this_scroll_margin)
3858 bottom_margin = PT;
3859 else
3860 bottom_margin = PT + 1;
3861
3862 if (bottom_margin > opoint)
3863 SET_PT_BOTH (opoint, opoint_byte);
3864 else
3865 {
3866 if (!NILP (Vscroll_preserve_screen_position))
3867 {
3868 SET_PT_BOTH (pos, pos_byte);
3869 Fvertical_motion (make_number (original_vpos), window);
3870 }
3871 else
3872 Fvertical_motion (make_number (-1), window);
3873 }
3874 }
3875 }
3876 else
3877 {
3878 if (noerror)
3879 return;
3880 else
3881 Fsignal (Qend_of_buffer, Qnil);
3882 }
3883 }
3884
3885
3886 /* Scroll selected_window up or down. If N is nil, scroll a
3887 screen-full which is defined as the height of the window minus
3888 next_screen_context_lines. If N is the symbol `-', scroll.
3889 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
3890 up. This is the guts of Fscroll_up and Fscroll_down. */
3891
3892 static void
3893 scroll_command (n, direction)
3894 Lisp_Object n;
3895 int direction;
3896 {
3897 register int defalt;
3898 int count = specpdl_ptr - specpdl;
3899
3900 xassert (abs (direction) == 1);
3901
3902 /* If selected window's buffer isn't current, make it current for
3903 the moment. But don't screw up if window_scroll gets an error. */
3904 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
3905 {
3906 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3907 Fset_buffer (XWINDOW (selected_window)->buffer);
3908
3909 /* Make redisplay consider other windows than just selected_window. */
3910 ++windows_or_buffers_changed;
3911 }
3912
3913 defalt = (window_internal_height (XWINDOW (selected_window))
3914 - next_screen_context_lines);
3915 defalt = direction * (defalt < 1 ? 1 : defalt);
3916
3917 if (NILP (n))
3918 window_scroll (selected_window, defalt, 1, 0);
3919 else if (EQ (n, Qminus))
3920 window_scroll (selected_window, - defalt, 1, 0);
3921 else
3922 {
3923 n = Fprefix_numeric_value (n);
3924 window_scroll (selected_window, XINT (n) * direction, 0, 0);
3925 }
3926
3927 unbind_to (count, Qnil);
3928 }
3929
3930 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
3931 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
3932 A near full screen is `next-screen-context-lines' less than a full screen.\n\
3933 Negative ARG means scroll downward.\n\
3934 If ARG is the atom `-', scroll downward by nearly full screen.\n\
3935 When calling from a program, supply as argument a number, nil, or `-'.")
3936 (arg)
3937 Lisp_Object arg;
3938 {
3939 scroll_command (arg, 1);
3940 return Qnil;
3941 }
3942
3943 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
3944 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
3945 A near full screen is `next-screen-context-lines' less than a full screen.\n\
3946 Negative ARG means scroll upward.\n\
3947 If ARG is the atom `-', scroll upward by nearly full screen.\n\
3948 When calling from a program, supply as argument a number, nil, or `-'.")
3949 (arg)
3950 Lisp_Object arg;
3951 {
3952 scroll_command (arg, -1);
3953 return Qnil;
3954 }
3955 \f
3956 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
3957 "Return the other window for \"other window scroll\" commands.\n\
3958 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
3959 specifies the window.\n\
3960 If `other-window-scroll-buffer' is non-nil, a window\n\
3961 showing that buffer is used.")
3962 ()
3963 {
3964 Lisp_Object window;
3965
3966 if (MINI_WINDOW_P (XWINDOW (selected_window))
3967 && !NILP (Vminibuf_scroll_window))
3968 window = Vminibuf_scroll_window;
3969 /* If buffer is specified, scroll that buffer. */
3970 else if (!NILP (Vother_window_scroll_buffer))
3971 {
3972 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
3973 if (NILP (window))
3974 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
3975 }
3976 else
3977 {
3978 /* Nothing specified; look for a neighboring window on the same
3979 frame. */
3980 window = Fnext_window (selected_window, Qnil, Qnil);
3981
3982 if (EQ (window, selected_window))
3983 /* That didn't get us anywhere; look for a window on another
3984 visible frame. */
3985 do
3986 window = Fnext_window (window, Qnil, Qt);
3987 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
3988 && ! EQ (window, selected_window));
3989 }
3990
3991 CHECK_LIVE_WINDOW (window, 0);
3992
3993 if (EQ (window, selected_window))
3994 error ("There is no other window");
3995
3996 return window;
3997 }
3998
3999 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4000 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
4001 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4002 The next window is the one below the current one; or the one at the top\n\
4003 if the current one is at the bottom. Negative ARG means scroll downward.\n\
4004 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4005 When calling from a program, supply as argument a number, nil, or `-'.\n\
4006 \n\
4007 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4008 specifies the window to scroll.\n\
4009 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
4010 showing that buffer, popping the buffer up if necessary.")
4011 (arg)
4012 register Lisp_Object arg;
4013 {
4014 register Lisp_Object window;
4015 register int defalt;
4016 register struct window *w;
4017 register int count = specpdl_ptr - specpdl;
4018
4019 window = Fother_window_for_scrolling ();
4020
4021 w = XWINDOW (window);
4022 defalt = window_internal_height (w) - next_screen_context_lines;
4023 if (defalt < 1) defalt = 1;
4024
4025 /* Don't screw up if window_scroll gets an error. */
4026 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4027 ++windows_or_buffers_changed;
4028
4029 Fset_buffer (w->buffer);
4030 SET_PT (marker_position (w->pointm));
4031
4032 if (NILP (arg))
4033 window_scroll (window, defalt, 1, 1);
4034 else if (EQ (arg, Qminus))
4035 window_scroll (window, -defalt, 1, 1);
4036 else
4037 {
4038 if (CONSP (arg))
4039 arg = Fcar (arg);
4040 CHECK_NUMBER (arg, 0);
4041 window_scroll (window, XINT (arg), 0, 1);
4042 }
4043
4044 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4045 unbind_to (count, Qnil);
4046
4047 return Qnil;
4048 }
4049 \f
4050 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4051 "Scroll selected window display ARG columns left.\n\
4052 Default for ARG is window width minus 2.")
4053 (arg)
4054 register Lisp_Object arg;
4055 {
4056
4057 if (NILP (arg))
4058 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4059 else
4060 arg = Fprefix_numeric_value (arg);
4061
4062 return
4063 Fset_window_hscroll (selected_window,
4064 make_number (XINT (XWINDOW (selected_window)->hscroll)
4065 + XINT (arg)));
4066 }
4067
4068 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4069 "Scroll selected window display ARG columns right.\n\
4070 Default for ARG is window width minus 2.")
4071 (arg)
4072 register Lisp_Object arg;
4073 {
4074 if (NILP (arg))
4075 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4076 else
4077 arg = Fprefix_numeric_value (arg);
4078
4079 return
4080 Fset_window_hscroll (selected_window,
4081 make_number (XINT (XWINDOW (selected_window)->hscroll)
4082 - XINT (arg)));
4083 }
4084
4085 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4086 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
4087 The desired position of point is always relative to the current window.\n\
4088 Just C-u as prefix means put point in the center of the window.\n\
4089 If ARG is omitted or nil, erases the entire frame and then\n\
4090 redraws with point in the center of the current window.")
4091 (arg)
4092 register Lisp_Object arg;
4093 {
4094 register struct window *w = XWINDOW (selected_window);
4095 register int ht = window_internal_height (w);
4096 struct position pos;
4097 struct buffer *buf = XBUFFER (w->buffer);
4098 struct buffer *obuf = current_buffer;
4099
4100 if (NILP (arg))
4101 {
4102 extern int frame_garbaged;
4103
4104 Fredraw_frame (w->frame);
4105 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4106 XSETFASTINT (arg, ht / 2);
4107 }
4108 else if (CONSP (arg)) /* Just C-u. */
4109 {
4110 XSETFASTINT (arg, ht / 2);
4111 }
4112 else
4113 {
4114 arg = Fprefix_numeric_value (arg);
4115 CHECK_NUMBER (arg, 0);
4116 }
4117
4118 if (XINT (arg) < 0)
4119 XSETINT (arg, XINT (arg) + ht);
4120
4121 set_buffer_internal (buf);
4122 pos = *vmotion (PT, - XINT (arg), w);
4123
4124 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
4125 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
4126 || FETCH_BYTE (pos.bytepos - 1) == '\n')
4127 ? Qt : Qnil);
4128 w->force_start = Qt;
4129 set_buffer_internal (obuf);
4130
4131 return Qnil;
4132 }
4133 \f
4134 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4135 1, 1, "P",
4136 "Position point relative to window.\n\
4137 With no argument, position point at center of window.\n\
4138 An argument specifies vertical position within the window;\n\
4139 zero means top of window, negative means relative to bottom of window.")
4140 (arg)
4141 register Lisp_Object arg;
4142 {
4143 register struct window *w = XWINDOW (selected_window);
4144 register int height = window_internal_height (w);
4145 register int start;
4146 Lisp_Object window;
4147
4148 if (NILP (arg))
4149 XSETFASTINT (arg, height / 2);
4150 else
4151 {
4152 arg = Fprefix_numeric_value (arg);
4153 if (XINT (arg) < 0)
4154 XSETINT (arg, XINT (arg) + height);
4155 }
4156
4157 start = marker_position (w->start);
4158 XSETWINDOW (window, w);
4159 if (start < BEGV || start > ZV)
4160 {
4161 Fvertical_motion (make_number (- (height / 2)), window);
4162 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4163 w->start_at_line_beg = Fbolp ();
4164 w->force_start = Qt;
4165 }
4166 else
4167 Fgoto_char (w->start);
4168
4169 return Fvertical_motion (arg, window);
4170 }
4171
4172
4173 \f
4174 /***********************************************************************
4175 Window Configuration
4176 ***********************************************************************/
4177
4178 struct save_window_data
4179 {
4180 EMACS_INT size_from_Lisp_Vector_struct;
4181 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4182 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4183 Lisp_Object frame_tool_bar_lines;
4184 Lisp_Object selected_frame;
4185 Lisp_Object current_window;
4186 Lisp_Object current_buffer;
4187 Lisp_Object minibuf_scroll_window;
4188 Lisp_Object root_window;
4189 Lisp_Object focus_frame;
4190 /* Record the values of window-min-width and window-min-height
4191 so that window sizes remain consistent with them. */
4192 Lisp_Object min_width, min_height;
4193 /* A vector, each of whose elements is a struct saved_window
4194 for one window. */
4195 Lisp_Object saved_windows;
4196 };
4197
4198 /* This is saved as a Lisp_Vector */
4199 struct saved_window
4200 {
4201 /* these first two must agree with struct Lisp_Vector in lisp.h */
4202 EMACS_INT size_from_Lisp_Vector_struct;
4203 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4204
4205 Lisp_Object window;
4206 Lisp_Object buffer, start, pointm, mark;
4207 Lisp_Object left, top, width, height, hscroll;
4208 Lisp_Object parent, prev;
4209 Lisp_Object start_at_line_beg;
4210 Lisp_Object display_table;
4211 };
4212 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
4213
4214 #define SAVED_WINDOW_N(swv,n) \
4215 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4216
4217 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4218 "Return t if OBJECT is a window-configuration object.")
4219 (object)
4220 Lisp_Object object;
4221 {
4222 if (WINDOW_CONFIGURATIONP (object))
4223 return Qt;
4224 return Qnil;
4225 }
4226
4227 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4228 "Return the frame that CONFIG, a window-configuration object, is about.")
4229 (config)
4230 Lisp_Object config;
4231 {
4232 register struct save_window_data *data;
4233 struct Lisp_Vector *saved_windows;
4234
4235 if (! WINDOW_CONFIGURATIONP (config))
4236 wrong_type_argument (Qwindow_configuration_p, config);
4237
4238 data = (struct save_window_data *) XVECTOR (config);
4239 saved_windows = XVECTOR (data->saved_windows);
4240 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4241 }
4242
4243 DEFUN ("set-window-configuration", Fset_window_configuration,
4244 Sset_window_configuration, 1, 1, 0,
4245 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4246 CONFIGURATION must be a value previously returned\n\
4247 by `current-window-configuration' (which see).\n\
4248 If CONFIGURATION was made from a frame that is now deleted,\n\
4249 only frame-independent values can be restored. In this case,\n\
4250 the return value is nil. Otherwise the value is t.")
4251 (configuration)
4252 Lisp_Object configuration;
4253 {
4254 register struct save_window_data *data;
4255 struct Lisp_Vector *saved_windows;
4256 Lisp_Object new_current_buffer;
4257 Lisp_Object frame;
4258 FRAME_PTR f;
4259 int old_point = -1;
4260
4261 while (!WINDOW_CONFIGURATIONP (configuration))
4262 wrong_type_argument (Qwindow_configuration_p, configuration);
4263
4264 data = (struct save_window_data *) XVECTOR (configuration);
4265 saved_windows = XVECTOR (data->saved_windows);
4266
4267 new_current_buffer = data->current_buffer;
4268 if (NILP (XBUFFER (new_current_buffer)->name))
4269 new_current_buffer = Qnil;
4270 else
4271 {
4272 if (XBUFFER (new_current_buffer) == current_buffer)
4273 old_point = PT;
4274
4275 }
4276
4277 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4278 f = XFRAME (frame);
4279
4280 /* If f is a dead frame, don't bother rebuilding its window tree.
4281 However, there is other stuff we should still try to do below. */
4282 if (FRAME_LIVE_P (f))
4283 {
4284 register struct window *w;
4285 register struct saved_window *p;
4286 struct window *root_window;
4287 struct window **leaf_windows;
4288 int n_leaf_windows;
4289 int k, i;
4290
4291 /* If the frame has been resized since this window configuration was
4292 made, we change the frame to the size specified in the
4293 configuration, restore the configuration, and then resize it
4294 back. We keep track of the prevailing height in these variables. */
4295 int previous_frame_height = FRAME_HEIGHT (f);
4296 int previous_frame_width = FRAME_WIDTH (f);
4297 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
4298 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
4299
4300 /* The mouse highlighting code could get screwed up
4301 if it runs during this. */
4302 BLOCK_INPUT;
4303
4304 if (XFASTINT (data->frame_height) != previous_frame_height
4305 || XFASTINT (data->frame_width) != previous_frame_width)
4306 change_frame_size (f, XFASTINT (data->frame_height),
4307 XFASTINT (data->frame_width), 0, 0, 0);
4308 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4309 if (XFASTINT (data->frame_menu_bar_lines)
4310 != previous_frame_menu_bar_lines)
4311 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4312 #ifdef HAVE_WINDOW_SYSTEM
4313 if (XFASTINT (data->frame_tool_bar_lines)
4314 != previous_frame_tool_bar_lines)
4315 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4316 #endif
4317 #endif
4318
4319 if (! NILP (XWINDOW (selected_window)->buffer))
4320 {
4321 w = XWINDOW (selected_window);
4322 set_marker_both (w->pointm,
4323 w->buffer,
4324 BUF_PT (XBUFFER (w->buffer)),
4325 BUF_PT_BYTE (XBUFFER (w->buffer)));
4326 }
4327
4328 windows_or_buffers_changed++;
4329 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4330
4331 /* Problem: Freeing all matrices and later allocating them again
4332 is a serious redisplay flickering problem. What we would
4333 really like to do is to free only those matrices not reused
4334 below. */
4335 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4336 leaf_windows
4337 = (struct window **) alloca (count_windows (root_window)
4338 * sizeof (struct window *));
4339 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4340
4341 /* Temporarily avoid any problems with windows that are smaller
4342 than they are supposed to be. */
4343 window_min_height = 1;
4344 window_min_width = 1;
4345
4346 /* Kludge Alert!
4347 Mark all windows now on frame as "deleted".
4348 Restoring the new configuration "undeletes" any that are in it.
4349
4350 Save their current buffers in their height fields, since we may
4351 need it later, if a buffer saved in the configuration is now
4352 dead. */
4353 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4354
4355 for (k = 0; k < saved_windows->size; k++)
4356 {
4357 p = SAVED_WINDOW_N (saved_windows, k);
4358 w = XWINDOW (p->window);
4359 w->next = Qnil;
4360
4361 if (!NILP (p->parent))
4362 w->parent = SAVED_WINDOW_N (saved_windows,
4363 XFASTINT (p->parent))->window;
4364 else
4365 w->parent = Qnil;
4366
4367 if (!NILP (p->prev))
4368 {
4369 w->prev = SAVED_WINDOW_N (saved_windows,
4370 XFASTINT (p->prev))->window;
4371 XWINDOW (w->prev)->next = p->window;
4372 }
4373 else
4374 {
4375 w->prev = Qnil;
4376 if (!NILP (w->parent))
4377 {
4378 if (EQ (p->width, XWINDOW (w->parent)->width))
4379 {
4380 XWINDOW (w->parent)->vchild = p->window;
4381 XWINDOW (w->parent)->hchild = Qnil;
4382 }
4383 else
4384 {
4385 XWINDOW (w->parent)->hchild = p->window;
4386 XWINDOW (w->parent)->vchild = Qnil;
4387 }
4388 }
4389 }
4390
4391 /* If we squirreled away the buffer in the window's height,
4392 restore it now. */
4393 if (BUFFERP (w->height))
4394 w->buffer = w->height;
4395 w->left = p->left;
4396 w->top = p->top;
4397 w->width = p->width;
4398 w->height = p->height;
4399 w->hscroll = p->hscroll;
4400 w->display_table = p->display_table;
4401 XSETFASTINT (w->last_modified, 0);
4402 XSETFASTINT (w->last_overlay_modified, 0);
4403
4404 /* Reinstall the saved buffer and pointers into it. */
4405 if (NILP (p->buffer))
4406 w->buffer = p->buffer;
4407 else
4408 {
4409 if (!NILP (XBUFFER (p->buffer)->name))
4410 /* If saved buffer is alive, install it. */
4411 {
4412 w->buffer = p->buffer;
4413 w->start_at_line_beg = p->start_at_line_beg;
4414 set_marker_restricted (w->start, p->start, w->buffer);
4415 set_marker_restricted (w->pointm, p->pointm, w->buffer);
4416 Fset_marker (XBUFFER (w->buffer)->mark,
4417 p->mark, w->buffer);
4418
4419 /* As documented in Fcurrent_window_configuration, don't
4420 save the location of point in the buffer which was current
4421 when the window configuration was recorded. */
4422 if (!EQ (p->buffer, new_current_buffer)
4423 && XBUFFER (p->buffer) == current_buffer)
4424 Fgoto_char (w->pointm);
4425 }
4426 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4427 /* Else unless window has a live buffer, get one. */
4428 {
4429 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4430 /* This will set the markers to beginning of visible
4431 range. */
4432 set_marker_restricted (w->start, make_number (0), w->buffer);
4433 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4434 w->start_at_line_beg = Qt;
4435 }
4436 else
4437 /* Keeping window's old buffer; make sure the markers
4438 are real. */
4439 {
4440 /* Set window markers at start of visible range. */
4441 if (XMARKER (w->start)->buffer == 0)
4442 set_marker_restricted (w->start, make_number (0),
4443 w->buffer);
4444 if (XMARKER (w->pointm)->buffer == 0)
4445 set_marker_restricted_both (w->pointm, w->buffer,
4446 BUF_PT (XBUFFER (w->buffer)),
4447 BUF_PT_BYTE (XBUFFER (w->buffer)));
4448 w->start_at_line_beg = Qt;
4449 }
4450 }
4451 }
4452
4453 FRAME_ROOT_WINDOW (f) = data->root_window;
4454 Fselect_window (data->current_window);
4455 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4456 = selected_window;
4457
4458 if (NILP (data->focus_frame)
4459 || (FRAMEP (data->focus_frame)
4460 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4461 Fredirect_frame_focus (frame, data->focus_frame);
4462
4463 #if 0 /* I don't understand why this is needed, and it causes problems
4464 when the frame's old selected window has been deleted. */
4465 if (f != selected_frame && FRAME_WINDOW_P (f))
4466 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4467 Qnil, 0);
4468 #endif
4469
4470 /* Set the screen height to the value it had before this function. */
4471 if (previous_frame_height != FRAME_HEIGHT (f)
4472 || previous_frame_width != FRAME_WIDTH (f))
4473 change_frame_size (f, previous_frame_height, previous_frame_width,
4474 0, 0, 0);
4475 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4476 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
4477 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4478 make_number (0));
4479 #ifdef HAVE_WINDOW_SYSTEM
4480 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4481 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4482 make_number (0));
4483 #endif
4484 #endif
4485
4486 /* Now, free glyph matrices in windows that were not reused. */
4487 for (i = 0; i < n_leaf_windows; ++i)
4488 if (NILP (leaf_windows[i]->buffer))
4489 {
4490 /* Assert it's not reused as a combination. */
4491 xassert (NILP (leaf_windows[i]->hchild)
4492 && NILP (leaf_windows[i]->vchild));
4493 free_window_matrices (leaf_windows[i]);
4494 SET_FRAME_GARBAGED (f);
4495 }
4496
4497 adjust_glyphs (f);
4498
4499 UNBLOCK_INPUT;
4500
4501 /* Fselect_window will have made f the selected frame, so we
4502 reselect the proper frame here. Fhandle_switch_frame will change the
4503 selected window too, but that doesn't make the call to
4504 Fselect_window above totally superfluous; it still sets f's
4505 selected window. */
4506 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
4507 do_switch_frame (data->selected_frame, Qnil, 0);
4508
4509 if (! NILP (Vwindow_configuration_change_hook)
4510 && ! NILP (Vrun_hooks))
4511 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4512 }
4513
4514 if (!NILP (new_current_buffer))
4515 {
4516 Fset_buffer (new_current_buffer);
4517
4518 /* If the buffer that is current now is the same
4519 that was current before setting the window configuration,
4520 don't alter its PT. */
4521 if (old_point >= 0)
4522 SET_PT (old_point);
4523 }
4524
4525 /* Restore the minimum heights recorded in the configuration. */
4526 window_min_height = XINT (data->min_height);
4527 window_min_width = XINT (data->min_width);
4528
4529 Vminibuf_scroll_window = data->minibuf_scroll_window;
4530
4531 return (FRAME_LIVE_P (f) ? Qt : Qnil);
4532 }
4533
4534 /* Mark all windows now on frame as deleted
4535 by setting their buffers to nil. */
4536
4537 void
4538 delete_all_subwindows (w)
4539 register struct window *w;
4540 {
4541 if (!NILP (w->next))
4542 delete_all_subwindows (XWINDOW (w->next));
4543 if (!NILP (w->vchild))
4544 delete_all_subwindows (XWINDOW (w->vchild));
4545 if (!NILP (w->hchild))
4546 delete_all_subwindows (XWINDOW (w->hchild));
4547
4548 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
4549
4550 if (!NILP (w->buffer))
4551 unshow_buffer (w);
4552
4553 /* We set all three of these fields to nil, to make sure that we can
4554 distinguish this dead window from any live window. Live leaf
4555 windows will have buffer set, and combination windows will have
4556 vchild or hchild set. */
4557 w->buffer = Qnil;
4558 w->vchild = Qnil;
4559 w->hchild = Qnil;
4560 }
4561 \f
4562 static int
4563 count_windows (window)
4564 register struct window *window;
4565 {
4566 register int count = 1;
4567 if (!NILP (window->next))
4568 count += count_windows (XWINDOW (window->next));
4569 if (!NILP (window->vchild))
4570 count += count_windows (XWINDOW (window->vchild));
4571 if (!NILP (window->hchild))
4572 count += count_windows (XWINDOW (window->hchild));
4573 return count;
4574 }
4575
4576
4577 /* Fill vector FLAT with leaf windows under W, starting at index I.
4578 Value is last index + 1. */
4579
4580 static int
4581 get_leaf_windows (w, flat, i)
4582 struct window *w;
4583 struct window **flat;
4584 int i;
4585 {
4586 while (w)
4587 {
4588 if (!NILP (w->hchild))
4589 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
4590 else if (!NILP (w->vchild))
4591 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
4592 else
4593 flat[i++] = w;
4594
4595 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4596 }
4597
4598 return i;
4599 }
4600
4601
4602 /* Return a pointer to the glyph W's physical cursor is on. Value is
4603 null if W's current matrix is invalid, so that no meaningfull glyph
4604 can be returned. */
4605
4606 struct glyph *
4607 get_phys_cursor_glyph (w)
4608 struct window *w;
4609 {
4610 struct glyph_row *row;
4611 struct glyph *glyph;
4612
4613 if (w->phys_cursor.vpos >= 0
4614 && w->phys_cursor.vpos < w->current_matrix->nrows
4615 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
4616 row->enabled_p)
4617 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
4618 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
4619 else
4620 glyph = NULL;
4621
4622 return glyph;
4623 }
4624
4625
4626 static int
4627 save_window_save (window, vector, i)
4628 Lisp_Object window;
4629 struct Lisp_Vector *vector;
4630 int i;
4631 {
4632 register struct saved_window *p;
4633 register struct window *w;
4634 register Lisp_Object tem;
4635
4636 for (;!NILP (window); window = w->next)
4637 {
4638 p = SAVED_WINDOW_N (vector, i);
4639 w = XWINDOW (window);
4640
4641 XSETFASTINT (w->temslot, i++);
4642 p->window = window;
4643 p->buffer = w->buffer;
4644 p->left = w->left;
4645 p->top = w->top;
4646 p->width = w->width;
4647 p->height = w->height;
4648 p->hscroll = w->hscroll;
4649 p->display_table = w->display_table;
4650 if (!NILP (w->buffer))
4651 {
4652 /* Save w's value of point in the window configuration.
4653 If w is the selected window, then get the value of point
4654 from the buffer; pointm is garbage in the selected window. */
4655 if (EQ (window, selected_window))
4656 {
4657 p->pointm = Fmake_marker ();
4658 set_marker_both (p->pointm, w->buffer,
4659 BUF_PT (XBUFFER (w->buffer)),
4660 BUF_PT_BYTE (XBUFFER (w->buffer)));
4661 }
4662 else
4663 p->pointm = Fcopy_marker (w->pointm, Qnil);
4664
4665 p->start = Fcopy_marker (w->start, Qnil);
4666 p->start_at_line_beg = w->start_at_line_beg;
4667
4668 tem = XBUFFER (w->buffer)->mark;
4669 p->mark = Fcopy_marker (tem, Qnil);
4670 }
4671 else
4672 {
4673 p->pointm = Qnil;
4674 p->start = Qnil;
4675 p->mark = Qnil;
4676 p->start_at_line_beg = Qnil;
4677 }
4678
4679 if (NILP (w->parent))
4680 p->parent = Qnil;
4681 else
4682 p->parent = XWINDOW (w->parent)->temslot;
4683
4684 if (NILP (w->prev))
4685 p->prev = Qnil;
4686 else
4687 p->prev = XWINDOW (w->prev)->temslot;
4688
4689 if (!NILP (w->vchild))
4690 i = save_window_save (w->vchild, vector, i);
4691 if (!NILP (w->hchild))
4692 i = save_window_save (w->hchild, vector, i);
4693 }
4694
4695 return i;
4696 }
4697
4698 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
4699 Scurrent_window_configuration, 0, 1, 0,
4700 "Return an object representing the current window configuration of FRAME.\n\
4701 If FRAME is nil or omitted, use the selected frame.\n\
4702 This describes the number of windows, their sizes and current buffers,\n\
4703 and for each displayed buffer, where display starts, and the positions of\n\
4704 point and mark. An exception is made for point in the current buffer:\n\
4705 its value is -not- saved.\n\
4706 This also records the currently selected frame, and FRAME's focus\n\
4707 redirection (see `redirect-frame-focus').")
4708 (frame)
4709 Lisp_Object frame;
4710 {
4711 register Lisp_Object tem;
4712 register int n_windows;
4713 register struct save_window_data *data;
4714 register struct Lisp_Vector *vec;
4715 register int i;
4716 FRAME_PTR f;
4717
4718 if (NILP (frame))
4719 frame = selected_frame;
4720 CHECK_LIVE_FRAME (frame, 0);
4721 f = XFRAME (frame);
4722
4723 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4724 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
4725 for (i = 0; i < VECSIZE (struct save_window_data); i++)
4726 vec->contents[i] = Qnil;
4727 vec->size = VECSIZE (struct save_window_data);
4728 data = (struct save_window_data *)vec;
4729
4730 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
4731 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
4732 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
4733 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
4734 data->selected_frame = selected_frame;
4735 data->current_window = FRAME_SELECTED_WINDOW (f);
4736 XSETBUFFER (data->current_buffer, current_buffer);
4737 data->minibuf_scroll_window = Vminibuf_scroll_window;
4738 data->root_window = FRAME_ROOT_WINDOW (f);
4739 data->focus_frame = FRAME_FOCUS_FRAME (f);
4740 XSETINT (data->min_height, window_min_height);
4741 XSETINT (data->min_width, window_min_width);
4742 tem = Fmake_vector (make_number (n_windows), Qnil);
4743 data->saved_windows = tem;
4744 for (i = 0; i < n_windows; i++)
4745 XVECTOR (tem)->contents[i]
4746 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
4747 save_window_save (FRAME_ROOT_WINDOW (f),
4748 XVECTOR (tem), 0);
4749 XSETWINDOW_CONFIGURATION (tem, data);
4750 return (tem);
4751 }
4752
4753 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
4754 0, UNEVALLED, 0,
4755 "Execute body, preserving window sizes and contents.\n\
4756 Restore which buffer appears in which window, where display starts,\n\
4757 and the value of point and mark for each window.\n\
4758 Also restore which buffer is current.\n\
4759 But do not preserve point in the current buffer.\n\
4760 Does not restore the value of point in current buffer.")
4761 (args)
4762 Lisp_Object args;
4763 {
4764 register Lisp_Object val;
4765 register int count = specpdl_ptr - specpdl;
4766
4767 record_unwind_protect (Fset_window_configuration,
4768 Fcurrent_window_configuration (Qnil));
4769 val = Fprogn (args);
4770 return unbind_to (count, val);
4771 }
4772
4773 \f
4774 /***********************************************************************
4775 Marginal Areas
4776 ***********************************************************************/
4777
4778 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
4779 2, 3, "",
4780 "Set width of marginal areas of window WINDOW.\n\
4781 If window is nil or omitted, set margins of the currently selected window.\n\
4782 First parameter LEFT-WIDTH specifies the number of character\n\
4783 cells to reserve for the left marginal area. Second parameter\n\
4784 RIGHT-WIDTH does the same for the right marginal area.\n\
4785 A nil width parameter means no margin.")
4786 (window, left, right)
4787 Lisp_Object window, left, right;
4788 {
4789 struct window *w = decode_window (window);
4790
4791 if (!NILP (left))
4792 CHECK_NUMBER_OR_FLOAT (left, 1);
4793 if (!NILP (right))
4794 CHECK_NUMBER_OR_FLOAT (right, 2);
4795
4796 /* Check widths < 0 and translate a zero width to nil.
4797 Margins that are too wide have to be checked elsewhere. */
4798 if ((INTEGERP (left) && XINT (left) < 0)
4799 || (FLOATP (left) && XFLOAT (left)->data <= 0))
4800 XSETFASTINT (left, 0);
4801 if (INTEGERP (left) && XFASTINT (left) == 0)
4802 left = Qnil;
4803
4804 if ((INTEGERP (right) && XINT (right) < 0)
4805 || (FLOATP (right) && XFLOAT (right)->data <= 0))
4806 XSETFASTINT (right, 0);
4807 if (INTEGERP (right) && XFASTINT (right) == 0)
4808 right = Qnil;
4809
4810 w->left_margin_width = left;
4811 w->right_margin_width = right;
4812
4813 ++windows_or_buffers_changed;
4814 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
4815 return Qnil;
4816 }
4817
4818
4819 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
4820 0, 1, 0,
4821 "Get width of marginal areas of window WINDOW.\n\
4822 If WINDOW is omitted or nil, use the currently selected window.\n\
4823 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
4824 If a marginal area does not exist, its width will be returned\n\
4825 as nil.")
4826 (window)
4827 Lisp_Object window;
4828 {
4829 struct window *w = decode_window (window);
4830 return Fcons (w->left_margin_width, w->right_margin_width);
4831 }
4832
4833
4834 \f
4835 /***********************************************************************
4836 Smooth scrolling
4837 ***********************************************************************/
4838
4839 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
4840 "Return the amount by which WINDOW is scrolled vertically.\n\
4841 Use the selected window if WINDOW is nil or omitted.\n\
4842 Value is a multiple of the canonical character height of WINDOW.")
4843 (window)
4844 Lisp_Object window;
4845 {
4846 Lisp_Object result;
4847 struct frame *f;
4848 struct window *w;
4849
4850 if (NILP (window))
4851 window = selected_window;
4852 else
4853 CHECK_WINDOW (window, 0);
4854 w = XWINDOW (window);
4855 f = XFRAME (w->frame);
4856
4857 if (FRAME_WINDOW_P (f))
4858 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
4859 else
4860 result = make_number (0);
4861 return result;
4862 }
4863
4864
4865 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
4866 2, 2, 0,
4867 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
4868 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
4869 non-negative multiple of the canonical character height of WINDOW.")
4870 (window, vscroll)
4871 Lisp_Object window, vscroll;
4872 {
4873 struct window *w;
4874 struct frame *f;
4875
4876 if (NILP (window))
4877 window = selected_window;
4878 else
4879 CHECK_WINDOW (window, 0);
4880 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
4881
4882 w = XWINDOW (window);
4883 f = XFRAME (w->frame);
4884
4885 if (FRAME_WINDOW_P (f))
4886 {
4887 int old_dy = w->vscroll;
4888
4889 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
4890 w->vscroll = min (w->vscroll, 0);
4891
4892 /* Adjust glyph matrix of the frame if the virtual display
4893 area becomes larger than before. */
4894 if (w->vscroll < 0 && w->vscroll < old_dy)
4895 adjust_glyphs (f);
4896
4897 /* Prevent redisplay shortcuts. */
4898 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4899 }
4900
4901 return Fwindow_vscroll (window);
4902 }
4903
4904 \f
4905 /* Call FN for all leaf windows on frame F. FN is called with the
4906 first argument being a pointer to the leaf window, and with
4907 additional arguments A1..A4. */
4908
4909 void
4910 foreach_window (f, fn, a1, a2, a3, a4)
4911 struct frame *f;
4912 void (* fn) ();
4913 int a1, a2, a3, a4;
4914 {
4915 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, a1, a2, a3, a4);
4916 }
4917
4918
4919 /* Helper function for foreach_window. Call FN for all leaf windows
4920 reachable from W. FN is called with the first argument being a
4921 pointer to the leaf window, and with additional arguments A1..A4. */
4922
4923 static void
4924 foreach_window_1 (w, fn, a1, a2, a3, a4)
4925 struct window *w;
4926 void (* fn) ();
4927 int a1, a2, a3, a4;
4928 {
4929 while (w)
4930 {
4931 if (!NILP (w->hchild))
4932 foreach_window_1 (XWINDOW (w->hchild), fn, a1, a2, a3, a4);
4933 else if (!NILP (w->vchild))
4934 foreach_window_1 (XWINDOW (w->vchild), fn, a1, a2, a3, a4);
4935 else
4936 fn (w, a1, a2, a3, a4);
4937
4938 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4939 }
4940 }
4941
4942
4943 /* Freeze or unfreeze the window start of W if unless it is a
4944 mini-window or the selected window. FREEZE_P non-zero means freeze
4945 the window start. */
4946
4947 static void
4948 freeze_window_start (w, freeze_p)
4949 struct window *w;
4950 int freeze_p;
4951 {
4952 if (w == XWINDOW (selected_window)
4953 || MINI_WINDOW_P (w)
4954 || (MINI_WINDOW_P (XWINDOW (selected_window))
4955 && w == XWINDOW (Vminibuf_scroll_window)))
4956 freeze_p = 0;
4957
4958 w->frozen_window_start_p = freeze_p;
4959 }
4960
4961
4962 /* Freeze or unfreeze the window starts of all leaf windows on frame
4963 F, except the selected window and a mini-window. FREEZE_P non-zero
4964 means freeze the window start. */
4965
4966 void
4967 freeze_window_starts (f, freeze_p)
4968 struct frame *f;
4969 int freeze_p;
4970 {
4971 foreach_window (f, freeze_window_start, freeze_p);
4972 }
4973
4974 \f
4975 /***********************************************************************
4976 Initialization
4977 ***********************************************************************/
4978
4979 /* Return 1 if window configurations C1 and C2
4980 describe the same state of affairs. This is used by Fequal. */
4981
4982 int
4983 compare_window_configurations (c1, c2, ignore_positions)
4984 Lisp_Object c1, c2;
4985 int ignore_positions;
4986 {
4987 register struct save_window_data *d1, *d2;
4988 struct Lisp_Vector *sw1, *sw2;
4989 int i;
4990
4991 d1 = (struct save_window_data *) XVECTOR (c1);
4992 d2 = (struct save_window_data *) XVECTOR (c2);
4993 sw1 = XVECTOR (d1->saved_windows);
4994 sw2 = XVECTOR (d2->saved_windows);
4995
4996 if (! EQ (d1->frame_width, d2->frame_width))
4997 return 0;
4998 if (! EQ (d1->frame_height, d2->frame_height))
4999 return 0;
5000 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5001 return 0;
5002 if (! EQ (d1->selected_frame, d2->selected_frame))
5003 return 0;
5004 /* Don't compare the current_window field directly.
5005 Instead see w1_is_current and w2_is_current, below. */
5006 if (! EQ (d1->current_buffer, d2->current_buffer))
5007 return 0;
5008 if (! ignore_positions)
5009 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5010 return 0;
5011 /* Don't compare the root_window field.
5012 We don't require the two configurations
5013 to use the same window object,
5014 and the two root windows must be equivalent
5015 if everything else compares equal. */
5016 if (! EQ (d1->focus_frame, d2->focus_frame))
5017 return 0;
5018 if (! EQ (d1->min_width, d2->min_width))
5019 return 0;
5020 if (! EQ (d1->min_height, d2->min_height))
5021 return 0;
5022
5023 /* Verify that the two confis have the same number of windows. */
5024 if (sw1->size != sw2->size)
5025 return 0;
5026
5027 for (i = 0; i < sw1->size; i++)
5028 {
5029 struct saved_window *p1, *p2;
5030 int w1_is_current, w2_is_current;
5031
5032 p1 = SAVED_WINDOW_N (sw1, i);
5033 p2 = SAVED_WINDOW_N (sw2, i);
5034
5035 /* Verify that the current windows in the two
5036 configurations correspond to each other. */
5037 w1_is_current = EQ (d1->current_window, p1->window);
5038 w2_is_current = EQ (d2->current_window, p2->window);
5039
5040 if (w1_is_current != w2_is_current)
5041 return 0;
5042
5043 /* Verify that the corresponding windows do match. */
5044 if (! EQ (p1->buffer, p2->buffer))
5045 return 0;
5046 if (! EQ (p1->left, p2->left))
5047 return 0;
5048 if (! EQ (p1->top, p2->top))
5049 return 0;
5050 if (! EQ (p1->width, p2->width))
5051 return 0;
5052 if (! EQ (p1->height, p2->height))
5053 return 0;
5054 if (! EQ (p1->display_table, p2->display_table))
5055 return 0;
5056 if (! EQ (p1->parent, p2->parent))
5057 return 0;
5058 if (! EQ (p1->prev, p2->prev))
5059 return 0;
5060 if (! ignore_positions)
5061 {
5062 if (! EQ (p1->hscroll, p2->hscroll))
5063 return 0;
5064 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5065 return 0;
5066 if (NILP (Fequal (p1->start, p2->start)))
5067 return 0;
5068 if (NILP (Fequal (p1->pointm, p2->pointm)))
5069 return 0;
5070 if (NILP (Fequal (p1->mark, p2->mark)))
5071 return 0;
5072 }
5073 }
5074
5075 return 1;
5076 }
5077
5078 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5079 Scompare_window_configurations, 2, 2, 0,
5080 "Compare two window configurations as regards the structure of windows.\n\
5081 This function ignores details such as the values of point and mark\n\
5082 and scrolling positions.")
5083 (x, y)
5084 Lisp_Object x, y;
5085 {
5086 if (compare_window_configurations (x, y, 1))
5087 return Qt;
5088 return Qnil;
5089 }
5090 \f
5091 void
5092 init_window_once ()
5093 {
5094 struct frame *f = make_terminal_frame ();
5095 XSETFRAME (selected_frame, f);
5096 Vterminal_frame = selected_frame;
5097 minibuf_window = f->minibuffer_window;
5098 selected_window = f->selected_window;
5099 last_nonminibuf_frame = f;
5100
5101 window_initialized = 1;
5102 }
5103
5104 void
5105 syms_of_window ()
5106 {
5107 Qleft_bitmap_area = intern ("left-bitmap-area");
5108 staticpro (&Qleft_bitmap_area);
5109 Qright_bitmap_area = intern ("right-bitmap-area");
5110 staticpro (&Qright_bitmap_area);
5111
5112 Qwindow_size_fixed = intern ("window-size-fixed");
5113 staticpro (&Qwindow_size_fixed);
5114
5115 staticpro (&Qwindow_configuration_change_hook);
5116 Qwindow_configuration_change_hook
5117 = intern ("window-configuration-change-hook");
5118
5119 Qwindowp = intern ("windowp");
5120 staticpro (&Qwindowp);
5121
5122 Qwindow_configuration_p = intern ("window-configuration-p");
5123 staticpro (&Qwindow_configuration_p);
5124
5125 Qwindow_live_p = intern ("window-live-p");
5126 staticpro (&Qwindow_live_p);
5127
5128 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5129 staticpro (&Qtemp_buffer_show_hook);
5130
5131 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5132 "Non-nil means call as function to display a help buffer.\n\
5133 The function is called with one argument, the buffer to be displayed.\n\
5134 Used by `with-output-to-temp-buffer'.\n\
5135 If this function is used, then it must do the entire job of showing\n\
5136 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5137 Vtemp_buffer_show_function = Qnil;
5138
5139 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5140 "If non-nil, function to call to handle `display-buffer'.\n\
5141 It will receive two args, the buffer and a flag which if non-nil means\n\
5142 that the currently selected window is not acceptable.\n\
5143 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5144 work using this function.");
5145 Vdisplay_buffer_function = Qnil;
5146
5147 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5148 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5149 Vminibuf_scroll_window = Qnil;
5150
5151 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5152 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5153 Vother_window_scroll_buffer = Qnil;
5154
5155 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5156 "*Non-nil means `display-buffer' should make a separate frame.");
5157 pop_up_frames = 0;
5158
5159 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5160 "Function to call to handle automatic new frame creation.\n\
5161 It is called with no arguments and should return a newly created frame.\n\
5162 \n\
5163 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5164 where `pop-up-frame-alist' would hold the default frame parameters.");
5165 Vpop_up_frame_function = Qnil;
5166
5167 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5168 "*List of buffer names that should have their own special frames.\n\
5169 Displaying a buffer whose name is in this list makes a special frame for it\n\
5170 using `special-display-function'. See also `special-display-regexps'.\n\
5171 \n\
5172 An element of the list can be a list instead of just a string.\n\
5173 There are two ways to use a list as an element:\n\
5174 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5175 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5176 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5177 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5178 All this is done by the function found in `special-display-function'.\n\
5179 \n\
5180 If this variable appears \"not to work\", because you add a name to it\n\
5181 but that buffer still appears in the selected window, look at the\n\
5182 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5183 Those variables take precedence over this one.");
5184 Vspecial_display_buffer_names = Qnil;
5185
5186 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5187 "*List of regexps saying which buffers should have their own special frames.\n\
5188 If a buffer name matches one of these regexps, it gets its own frame.\n\
5189 Displaying a buffer whose name is in this list makes a special frame for it\n\
5190 using `special-display-function'.\n\
5191 \n\
5192 An element of the list can be a list instead of just a string.\n\
5193 There are two ways to use a list as an element:\n\
5194 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5195 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5196 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5197 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5198 All this is done by the function found in `special-display-function'.\n\
5199 \n\
5200 If this variable appears \"not to work\", because you add a regexp to it\n\
5201 but the matching buffers still appear in the selected window, look at the\n\
5202 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5203 Those variables take precedence over this one.");
5204 Vspecial_display_regexps = Qnil;
5205
5206 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5207 "Function to call to make a new frame for a special buffer.\n\
5208 It is called with two arguments, the buffer and optional buffer specific\n\
5209 data, and should return a window displaying that buffer.\n\
5210 The default value makes a separate frame for the buffer,\n\
5211 using `special-display-frame-alist' to specify the frame parameters.\n\
5212 \n\
5213 A buffer is special if its is listed in `special-display-buffer-names'\n\
5214 or matches a regexp in `special-display-regexps'.");
5215 Vspecial_display_function = Qnil;
5216
5217 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5218 "*List of buffer names that should appear in the selected window.\n\
5219 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5220 switches to it in the selected window, rather than making it appear\n\
5221 in some other window.\n\
5222 \n\
5223 An element of the list can be a cons cell instead of just a string.\n\
5224 Then the car must be a string, which specifies the buffer name.\n\
5225 This is for compatibility with `special-display-buffer-names';\n\
5226 the cdr of the cons cell is ignored.\n\
5227 \n\
5228 See also `same-window-regexps'.");
5229 Vsame_window_buffer_names = Qnil;
5230
5231 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5232 "*List of regexps saying which buffers should appear in the selected window.\n\
5233 If a buffer name matches one of these regexps, then displaying it\n\
5234 using `display-buffer' or `pop-to-buffer' switches to it\n\
5235 in the selected window, rather than making it appear in some other window.\n\
5236 \n\
5237 An element of the list can be a cons cell instead of just a string.\n\
5238 Then the car must be a string, which specifies the buffer name.\n\
5239 This is for compatibility with `special-display-buffer-names';\n\
5240 the cdr of the cons cell is ignored.\n\
5241 \n\
5242 See also `same-window-buffer-names'.");
5243 Vsame_window_regexps = Qnil;
5244
5245 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5246 "*Non-nil means display-buffer should make new windows.");
5247 pop_up_windows = 1;
5248
5249 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5250 "*Number of lines of continuity when scrolling by screenfuls.");
5251 next_screen_context_lines = 2;
5252
5253 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5254 "*display-buffer would prefer to split the largest window if this large.\n\
5255 If there is only one window, it is split regardless of this value.");
5256 split_height_threshold = 500;
5257
5258 DEFVAR_INT ("window-min-height", &window_min_height,
5259 "*Delete any window less than this tall (including its mode line).");
5260 window_min_height = 4;
5261
5262 DEFVAR_INT ("window-min-width", &window_min_width,
5263 "*Delete any window less than this wide.");
5264 window_min_width = 10;
5265
5266 DEFVAR_LISP ("scroll-preserve-screen-position",
5267 &Vscroll_preserve_screen_position,
5268 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
5269 Vscroll_preserve_screen_position = Qnil;
5270
5271 DEFVAR_LISP ("window-configuration-change-hook",
5272 &Vwindow_configuration_change_hook,
5273 "Functions to call when window configuration changes.\n\
5274 The selected frame is the one whose configuration has changed.");
5275 Vwindow_configuration_change_hook = Qnil;
5276
5277 defsubr (&Sselected_window);
5278 defsubr (&Sminibuffer_window);
5279 defsubr (&Swindow_minibuffer_p);
5280 defsubr (&Swindowp);
5281 defsubr (&Swindow_live_p);
5282 defsubr (&Spos_visible_in_window_p);
5283 defsubr (&Swindow_buffer);
5284 defsubr (&Swindow_height);
5285 defsubr (&Swindow_width);
5286 defsubr (&Swindow_hscroll);
5287 defsubr (&Sset_window_hscroll);
5288 defsubr (&Swindow_redisplay_end_trigger);
5289 defsubr (&Sset_window_redisplay_end_trigger);
5290 defsubr (&Swindow_edges);
5291 defsubr (&Scoordinates_in_window_p);
5292 defsubr (&Swindow_at);
5293 defsubr (&Swindow_point);
5294 defsubr (&Swindow_start);
5295 defsubr (&Swindow_end);
5296 defsubr (&Sset_window_point);
5297 defsubr (&Sset_window_start);
5298 defsubr (&Swindow_dedicated_p);
5299 defsubr (&Sset_window_dedicated_p);
5300 defsubr (&Swindow_display_table);
5301 defsubr (&Sset_window_display_table);
5302 defsubr (&Snext_window);
5303 defsubr (&Sprevious_window);
5304 defsubr (&Sother_window);
5305 defsubr (&Sget_lru_window);
5306 defsubr (&Sget_largest_window);
5307 defsubr (&Sget_buffer_window);
5308 defsubr (&Sdelete_other_windows);
5309 defsubr (&Sdelete_windows_on);
5310 defsubr (&Sreplace_buffer_in_windows);
5311 defsubr (&Sdelete_window);
5312 defsubr (&Sset_window_buffer);
5313 defsubr (&Sselect_window);
5314 defsubr (&Sspecial_display_p);
5315 defsubr (&Ssame_window_p);
5316 defsubr (&Sdisplay_buffer);
5317 defsubr (&Ssplit_window);
5318 defsubr (&Senlarge_window);
5319 defsubr (&Sshrink_window);
5320 defsubr (&Sscroll_up);
5321 defsubr (&Sscroll_down);
5322 defsubr (&Sscroll_left);
5323 defsubr (&Sscroll_right);
5324 defsubr (&Sother_window_for_scrolling);
5325 defsubr (&Sscroll_other_window);
5326 defsubr (&Srecenter);
5327 defsubr (&Smove_to_window_line);
5328 defsubr (&Swindow_configuration_p);
5329 defsubr (&Swindow_configuration_frame);
5330 defsubr (&Sset_window_configuration);
5331 defsubr (&Scurrent_window_configuration);
5332 defsubr (&Ssave_window_excursion);
5333 defsubr (&Sset_window_margins);
5334 defsubr (&Swindow_margins);
5335 defsubr (&Swindow_vscroll);
5336 defsubr (&Sset_window_vscroll);
5337 defsubr (&Scompare_window_configurations);
5338 }
5339
5340 void
5341 keys_of_window ()
5342 {
5343 initial_define_key (control_x_map, '1', "delete-other-windows");
5344 initial_define_key (control_x_map, '2', "split-window");
5345 initial_define_key (control_x_map, '0', "delete-window");
5346 initial_define_key (control_x_map, 'o', "other-window");
5347 initial_define_key (control_x_map, '^', "enlarge-window");
5348 initial_define_key (control_x_map, '<', "scroll-left");
5349 initial_define_key (control_x_map, '>', "scroll-right");
5350
5351 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5352 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5353 initial_define_key (meta_map, 'v', "scroll-down");
5354
5355 initial_define_key (global_map, Ctl('L'), "recenter");
5356 initial_define_key (meta_map, 'r', "move-to-window-line");
5357 }