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