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