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