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