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