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