(coordinates_in_window): Increase width of area
[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 XSETFASTINT (w->hscroll, 0);
2630 XSETFASTINT (w->min_hscroll, 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
4499 if (old_buffer)
4500 set_buffer_internal (old_buffer);
4501
4502 bottom_y = it.current_y + it.max_ascent + it.max_descent;
4503
4504 if (bottom_y > it.current_y && bottom_y <= it.last_visible_y)
4505 /* Hit a line without a terminating newline. */
4506 it.vpos++;
4507
4508 /* Add in empty lines at the bottom of the window. */
4509 if (bottom_y < height)
4510 {
4511 struct frame *f = XFRAME (w->frame);
4512 int rest = height - bottom_y;
4513 int lines = rest / CANON_Y_UNIT (f);
4514 it.vpos += lines;
4515 }
4516
4517 return it.vpos;
4518 }
4519
4520
4521 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4522 "Center point in window and redisplay frame.\n\
4523 With prefix argument ARG, recenter putting point on screen line ARG\n\
4524 relative to the current window. If ARG is negative, it counts up from the\n\
4525 bottom of the window. (ARG should be less than the height of the window.)\n\
4526 \n\
4527 If ARG is omitted or nil, erase the entire frame and then\n\
4528 redraw with point in the center of the current window.\n\
4529 Just C-u as prefix means put point in the center of the window\n\
4530 and redisplay normally--don't erase and redraw the frame.")
4531 (arg)
4532 register Lisp_Object arg;
4533 {
4534 struct window *w = XWINDOW (selected_window);
4535 struct buffer *buf = XBUFFER (w->buffer);
4536 struct buffer *obuf = current_buffer;
4537 int center_p = 0;
4538 int charpos, bytepos;
4539
4540 if (NILP (arg))
4541 {
4542 int i;
4543
4544 /* Invalidate pixel data calculated for all compositions. */
4545 for (i = 0; i < n_compositions; i++)
4546 composition_table[i]->font = NULL;
4547
4548 Fredraw_frame (w->frame);
4549 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4550 center_p = 1;
4551 }
4552 else if (CONSP (arg)) /* Just C-u. */
4553 center_p = 1;
4554 else
4555 {
4556 arg = Fprefix_numeric_value (arg);
4557 CHECK_NUMBER (arg, 0);
4558 }
4559
4560 set_buffer_internal (buf);
4561
4562 /* Handle centering on a gfaphical frame specially. Such frames can
4563 have variable-height lines and centering point on the basis of
4564 line counts would lead to strange effects. */
4565 if (center_p && FRAME_WINDOW_P (XFRAME (w->frame)))
4566 {
4567 struct it it;
4568 struct text_pos pt;
4569
4570 SET_TEXT_POS (pt, PT, PT_BYTE);
4571 start_display (&it, w, pt);
4572 move_it_vertically (&it, - it.last_visible_y / 2);
4573 charpos = IT_CHARPOS (it);
4574 bytepos = IT_BYTEPOS (it);
4575 }
4576 else
4577 {
4578 struct position pos;
4579
4580 if (center_p)
4581 {
4582 int ht = displayed_window_lines (w);
4583 arg = make_number (ht / 2);
4584 }
4585 else if (XINT (arg) < 0)
4586 {
4587 int ht = displayed_window_lines (w);
4588 XSETINT (arg, XINT (arg) + ht);
4589 }
4590
4591 pos = *vmotion (PT, - XINT (arg), w);
4592 charpos = pos.bufpos;
4593 bytepos = pos.bytepos;
4594 }
4595
4596 /* Set the new window start. */
4597 set_marker_both (w->start, w->buffer, charpos, bytepos);
4598 w->window_end_valid = Qnil;
4599 w->force_start = Qt;
4600 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
4601 w->start_at_line_beg = Qt;
4602 else
4603 w->start_at_line_beg = Qnil;
4604
4605 set_buffer_internal (obuf);
4606 return Qnil;
4607 }
4608
4609
4610 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
4611 0, 1, 0,
4612 "Return the height in lines of the text display area of WINDOW.\n\
4613 This doesn't include the mode-line (or header-line if any) or any\n\
4614 partial-height lines in the text display area.")
4615 (window)
4616 Lisp_Object window;
4617 {
4618 struct window *w = decode_window (window);
4619 int pixel_height = window_box_height (w);
4620 int line_height = pixel_height / CANON_Y_UNIT (XFRAME (w->frame));
4621 return make_number (line_height);
4622 }
4623
4624
4625 \f
4626 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4627 1, 1, "P",
4628 "Position point relative to window.\n\
4629 With no argument, position point at center of window.\n\
4630 An argument specifies vertical position within the window;\n\
4631 zero means top of window, negative means relative to bottom of window.")
4632 (arg)
4633 Lisp_Object arg;
4634 {
4635 struct window *w = XWINDOW (selected_window);
4636 int lines, start;
4637 Lisp_Object window;
4638
4639 window = selected_window;
4640 start = marker_position (w->start);
4641 if (start < BEGV || start > ZV)
4642 {
4643 int height = window_internal_height (w);
4644 Fvertical_motion (make_number (- (height / 2)), window);
4645 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4646 w->start_at_line_beg = Fbolp ();
4647 w->force_start = Qt;
4648 }
4649 else
4650 Fgoto_char (w->start);
4651
4652 lines = displayed_window_lines (w);
4653 if (NILP (arg))
4654 XSETFASTINT (arg, lines / 2);
4655 else
4656 {
4657 arg = Fprefix_numeric_value (arg);
4658 if (XINT (arg) < 0)
4659 XSETINT (arg, XINT (arg) + lines);
4660 }
4661
4662 #if 0 /* I don't understand why this is done. Among other things,
4663 it means that C-u 0 M-r moves to line 1, and C-u -1 M-r
4664 moves to the line below the window end. 2000-02-05, gerd */
4665 if (w->vscroll)
4666 /* Skip past a partially visible first line. */
4667 XSETINT (arg, XINT (arg) + 1);
4668 #endif
4669
4670 return Fvertical_motion (arg, window);
4671 }
4672
4673
4674 \f
4675 /***********************************************************************
4676 Window Configuration
4677 ***********************************************************************/
4678
4679 struct save_window_data
4680 {
4681 EMACS_INT size_from_Lisp_Vector_struct;
4682 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4683 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4684 Lisp_Object frame_tool_bar_lines;
4685 Lisp_Object selected_frame;
4686 Lisp_Object current_window;
4687 Lisp_Object current_buffer;
4688 Lisp_Object minibuf_scroll_window;
4689 Lisp_Object root_window;
4690 Lisp_Object focus_frame;
4691 /* Record the values of window-min-width and window-min-height
4692 so that window sizes remain consistent with them. */
4693 Lisp_Object min_width, min_height;
4694 /* A vector, each of whose elements is a struct saved_window
4695 for one window. */
4696 Lisp_Object saved_windows;
4697 };
4698
4699 /* This is saved as a Lisp_Vector */
4700 struct saved_window
4701 {
4702 /* these first two must agree with struct Lisp_Vector in lisp.h */
4703 EMACS_INT size_from_Lisp_Vector_struct;
4704 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4705
4706 Lisp_Object window;
4707 Lisp_Object buffer, start, pointm, mark;
4708 Lisp_Object left, top, width, height, hscroll, min_hscroll;
4709 Lisp_Object parent, prev;
4710 Lisp_Object start_at_line_beg;
4711 Lisp_Object display_table;
4712 Lisp_Object orig_top, orig_height;
4713 };
4714
4715 #define SAVED_WINDOW_VECTOR_SIZE 17 /* Arg to Fmake_vector */
4716
4717 #define SAVED_WINDOW_N(swv,n) \
4718 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4719
4720 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4721 "Return t if OBJECT is a window-configuration object.")
4722 (object)
4723 Lisp_Object object;
4724 {
4725 if (WINDOW_CONFIGURATIONP (object))
4726 return Qt;
4727 return Qnil;
4728 }
4729
4730 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4731 "Return the frame that CONFIG, a window-configuration object, is about.")
4732 (config)
4733 Lisp_Object config;
4734 {
4735 register struct save_window_data *data;
4736 struct Lisp_Vector *saved_windows;
4737
4738 if (! WINDOW_CONFIGURATIONP (config))
4739 wrong_type_argument (Qwindow_configuration_p, config);
4740
4741 data = (struct save_window_data *) XVECTOR (config);
4742 saved_windows = XVECTOR (data->saved_windows);
4743 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4744 }
4745
4746 DEFUN ("set-window-configuration", Fset_window_configuration,
4747 Sset_window_configuration, 1, 1, 0,
4748 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4749 CONFIGURATION must be a value previously returned\n\
4750 by `current-window-configuration' (which see).\n\
4751 If CONFIGURATION was made from a frame that is now deleted,\n\
4752 only frame-independent values can be restored. In this case,\n\
4753 the return value is nil. Otherwise the value is t.")
4754 (configuration)
4755 Lisp_Object configuration;
4756 {
4757 register struct save_window_data *data;
4758 struct Lisp_Vector *saved_windows;
4759 Lisp_Object new_current_buffer;
4760 Lisp_Object frame;
4761 FRAME_PTR f;
4762 int old_point = -1;
4763
4764 while (!WINDOW_CONFIGURATIONP (configuration))
4765 wrong_type_argument (Qwindow_configuration_p, configuration);
4766
4767 data = (struct save_window_data *) XVECTOR (configuration);
4768 saved_windows = XVECTOR (data->saved_windows);
4769
4770 new_current_buffer = data->current_buffer;
4771 if (NILP (XBUFFER (new_current_buffer)->name))
4772 new_current_buffer = Qnil;
4773 else
4774 {
4775 if (XBUFFER (new_current_buffer) == current_buffer)
4776 old_point = PT;
4777 }
4778
4779 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4780 f = XFRAME (frame);
4781
4782 /* If f is a dead frame, don't bother rebuilding its window tree.
4783 However, there is other stuff we should still try to do below. */
4784 if (FRAME_LIVE_P (f))
4785 {
4786 register struct window *w;
4787 register struct saved_window *p;
4788 struct window *root_window;
4789 struct window **leaf_windows;
4790 int n_leaf_windows;
4791 int k, i, n;
4792
4793 /* If the frame has been resized since this window configuration was
4794 made, we change the frame to the size specified in the
4795 configuration, restore the configuration, and then resize it
4796 back. We keep track of the prevailing height in these variables. */
4797 int previous_frame_height = FRAME_HEIGHT (f);
4798 int previous_frame_width = FRAME_WIDTH (f);
4799 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
4800 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
4801
4802 /* The mouse highlighting code could get screwed up
4803 if it runs during this. */
4804 BLOCK_INPUT;
4805
4806 if (XFASTINT (data->frame_height) != previous_frame_height
4807 || XFASTINT (data->frame_width) != previous_frame_width)
4808 change_frame_size (f, XFASTINT (data->frame_height),
4809 XFASTINT (data->frame_width), 0, 0, 0);
4810 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4811 if (XFASTINT (data->frame_menu_bar_lines)
4812 != previous_frame_menu_bar_lines)
4813 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4814 #ifdef HAVE_WINDOW_SYSTEM
4815 if (XFASTINT (data->frame_tool_bar_lines)
4816 != previous_frame_tool_bar_lines)
4817 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4818 #endif
4819 #endif
4820
4821 /* "Swap out" point from the selected window
4822 into its buffer. We do this now, before
4823 restoring the window contents, and prevent it from
4824 being done later on when we select a new window. */
4825 if (! NILP (XWINDOW (selected_window)->buffer))
4826 {
4827 w = XWINDOW (selected_window);
4828 set_marker_both (w->pointm,
4829 w->buffer,
4830 BUF_PT (XBUFFER (w->buffer)),
4831 BUF_PT_BYTE (XBUFFER (w->buffer)));
4832 }
4833
4834 windows_or_buffers_changed++;
4835 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4836
4837 /* Problem: Freeing all matrices and later allocating them again
4838 is a serious redisplay flickering problem. What we would
4839 really like to do is to free only those matrices not reused
4840 below. */
4841 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4842 leaf_windows
4843 = (struct window **) alloca (count_windows (root_window)
4844 * sizeof (struct window *));
4845 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4846
4847 /* Temporarily avoid any problems with windows that are smaller
4848 than they are supposed to be. */
4849 window_min_height = 1;
4850 window_min_width = 1;
4851
4852 /* Kludge Alert!
4853 Mark all windows now on frame as "deleted".
4854 Restoring the new configuration "undeletes" any that are in it.
4855
4856 Save their current buffers in their height fields, since we may
4857 need it later, if a buffer saved in the configuration is now
4858 dead. */
4859 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4860
4861 for (k = 0; k < saved_windows->size; k++)
4862 {
4863 p = SAVED_WINDOW_N (saved_windows, k);
4864 w = XWINDOW (p->window);
4865 w->next = Qnil;
4866
4867 if (!NILP (p->parent))
4868 w->parent = SAVED_WINDOW_N (saved_windows,
4869 XFASTINT (p->parent))->window;
4870 else
4871 w->parent = Qnil;
4872
4873 if (!NILP (p->prev))
4874 {
4875 w->prev = SAVED_WINDOW_N (saved_windows,
4876 XFASTINT (p->prev))->window;
4877 XWINDOW (w->prev)->next = p->window;
4878 }
4879 else
4880 {
4881 w->prev = Qnil;
4882 if (!NILP (w->parent))
4883 {
4884 if (EQ (p->width, XWINDOW (w->parent)->width))
4885 {
4886 XWINDOW (w->parent)->vchild = p->window;
4887 XWINDOW (w->parent)->hchild = Qnil;
4888 }
4889 else
4890 {
4891 XWINDOW (w->parent)->hchild = p->window;
4892 XWINDOW (w->parent)->vchild = Qnil;
4893 }
4894 }
4895 }
4896
4897 /* If we squirreled away the buffer in the window's height,
4898 restore it now. */
4899 if (BUFFERP (w->height))
4900 w->buffer = w->height;
4901 w->left = p->left;
4902 w->top = p->top;
4903 w->width = p->width;
4904 w->height = p->height;
4905 w->hscroll = p->hscroll;
4906 w->min_hscroll = p->min_hscroll;
4907 w->display_table = p->display_table;
4908 w->orig_top = p->orig_top;
4909 w->orig_height = p->orig_height;
4910 XSETFASTINT (w->last_modified, 0);
4911 XSETFASTINT (w->last_overlay_modified, 0);
4912
4913 /* Reinstall the saved buffer and pointers into it. */
4914 if (NILP (p->buffer))
4915 w->buffer = p->buffer;
4916 else
4917 {
4918 if (!NILP (XBUFFER (p->buffer)->name))
4919 /* If saved buffer is alive, install it. */
4920 {
4921 w->buffer = p->buffer;
4922 w->start_at_line_beg = p->start_at_line_beg;
4923 set_marker_restricted (w->start, p->start, w->buffer);
4924 set_marker_restricted (w->pointm, p->pointm, w->buffer);
4925 Fset_marker (XBUFFER (w->buffer)->mark,
4926 p->mark, w->buffer);
4927
4928 /* As documented in Fcurrent_window_configuration, don't
4929 save the location of point in the buffer which was current
4930 when the window configuration was recorded. */
4931 if (!EQ (p->buffer, new_current_buffer)
4932 && XBUFFER (p->buffer) == current_buffer)
4933 Fgoto_char (w->pointm);
4934 }
4935 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4936 /* Else unless window has a live buffer, get one. */
4937 {
4938 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4939 /* This will set the markers to beginning of visible
4940 range. */
4941 set_marker_restricted (w->start, make_number (0), w->buffer);
4942 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4943 w->start_at_line_beg = Qt;
4944 }
4945 else
4946 /* Keeping window's old buffer; make sure the markers
4947 are real. */
4948 {
4949 /* Set window markers at start of visible range. */
4950 if (XMARKER (w->start)->buffer == 0)
4951 set_marker_restricted (w->start, make_number (0),
4952 w->buffer);
4953 if (XMARKER (w->pointm)->buffer == 0)
4954 set_marker_restricted_both (w->pointm, w->buffer,
4955 BUF_PT (XBUFFER (w->buffer)),
4956 BUF_PT_BYTE (XBUFFER (w->buffer)));
4957 w->start_at_line_beg = Qt;
4958 }
4959 }
4960 }
4961
4962 FRAME_ROOT_WINDOW (f) = data->root_window;
4963 /* Prevent "swapping out point" in the old selected window
4964 using the buffer that has been restored into it.
4965 That swapping out has already been done,
4966 near the beginning of this function. */
4967 selected_window = Qnil;
4968 Fselect_window (data->current_window);
4969 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4970 = selected_window;
4971
4972 if (NILP (data->focus_frame)
4973 || (FRAMEP (data->focus_frame)
4974 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4975 Fredirect_frame_focus (frame, data->focus_frame);
4976
4977 #if 0 /* I don't understand why this is needed, and it causes problems
4978 when the frame's old selected window has been deleted. */
4979 if (f != selected_frame && FRAME_WINDOW_P (f))
4980 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4981 Qnil, 0);
4982 #endif
4983
4984 /* Set the screen height to the value it had before this function. */
4985 if (previous_frame_height != FRAME_HEIGHT (f)
4986 || previous_frame_width != FRAME_WIDTH (f))
4987 change_frame_size (f, previous_frame_height, previous_frame_width,
4988 0, 0, 0);
4989 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4990 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
4991 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4992 make_number (0));
4993 #ifdef HAVE_WINDOW_SYSTEM
4994 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4995 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4996 make_number (0));
4997 #endif
4998 #endif
4999
5000 /* Now, free glyph matrices in windows that were not reused. */
5001 for (i = n = 0; i < n_leaf_windows; ++i)
5002 {
5003 if (NILP (leaf_windows[i]->buffer))
5004 {
5005 /* Assert it's not reused as a combination. */
5006 xassert (NILP (leaf_windows[i]->hchild)
5007 && NILP (leaf_windows[i]->vchild));
5008 free_window_matrices (leaf_windows[i]);
5009 }
5010 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5011 ++n;
5012 }
5013
5014 /* If more than one window shows the new and old current buffer,
5015 don't try to preserve point in that buffer. */
5016 if (old_point > 0 && n > 1)
5017 old_point = -1;
5018
5019 adjust_glyphs (f);
5020
5021 UNBLOCK_INPUT;
5022
5023 /* Fselect_window will have made f the selected frame, so we
5024 reselect the proper frame here. Fhandle_switch_frame will change the
5025 selected window too, but that doesn't make the call to
5026 Fselect_window above totally superfluous; it still sets f's
5027 selected window. */
5028 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5029 do_switch_frame (data->selected_frame, Qnil, 0);
5030
5031 if (! NILP (Vwindow_configuration_change_hook)
5032 && ! NILP (Vrun_hooks))
5033 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5034 }
5035
5036 if (!NILP (new_current_buffer))
5037 {
5038 Fset_buffer (new_current_buffer);
5039
5040 /* If the buffer that is current now is the same
5041 that was current before setting the window configuration,
5042 don't alter its PT. */
5043 if (old_point >= 0)
5044 SET_PT (old_point);
5045 }
5046
5047 /* Restore the minimum heights recorded in the configuration. */
5048 window_min_height = XINT (data->min_height);
5049 window_min_width = XINT (data->min_width);
5050
5051 Vminibuf_scroll_window = data->minibuf_scroll_window;
5052
5053 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5054 }
5055
5056 /* Mark all windows now on frame as deleted
5057 by setting their buffers to nil. */
5058
5059 void
5060 delete_all_subwindows (w)
5061 register struct window *w;
5062 {
5063 if (!NILP (w->next))
5064 delete_all_subwindows (XWINDOW (w->next));
5065 if (!NILP (w->vchild))
5066 delete_all_subwindows (XWINDOW (w->vchild));
5067 if (!NILP (w->hchild))
5068 delete_all_subwindows (XWINDOW (w->hchild));
5069
5070 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
5071
5072 if (!NILP (w->buffer))
5073 unshow_buffer (w);
5074
5075 /* We set all three of these fields to nil, to make sure that we can
5076 distinguish this dead window from any live window. Live leaf
5077 windows will have buffer set, and combination windows will have
5078 vchild or hchild set. */
5079 w->buffer = Qnil;
5080 w->vchild = Qnil;
5081 w->hchild = Qnil;
5082
5083 Vwindow_list = Qnil;
5084 }
5085 \f
5086 static int
5087 count_windows (window)
5088 register struct window *window;
5089 {
5090 register int count = 1;
5091 if (!NILP (window->next))
5092 count += count_windows (XWINDOW (window->next));
5093 if (!NILP (window->vchild))
5094 count += count_windows (XWINDOW (window->vchild));
5095 if (!NILP (window->hchild))
5096 count += count_windows (XWINDOW (window->hchild));
5097 return count;
5098 }
5099
5100
5101 /* Fill vector FLAT with leaf windows under W, starting at index I.
5102 Value is last index + 1. */
5103
5104 static int
5105 get_leaf_windows (w, flat, i)
5106 struct window *w;
5107 struct window **flat;
5108 int i;
5109 {
5110 while (w)
5111 {
5112 if (!NILP (w->hchild))
5113 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5114 else if (!NILP (w->vchild))
5115 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5116 else
5117 flat[i++] = w;
5118
5119 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5120 }
5121
5122 return i;
5123 }
5124
5125
5126 /* Return a pointer to the glyph W's physical cursor is on. Value is
5127 null if W's current matrix is invalid, so that no meaningfull glyph
5128 can be returned. */
5129
5130 struct glyph *
5131 get_phys_cursor_glyph (w)
5132 struct window *w;
5133 {
5134 struct glyph_row *row;
5135 struct glyph *glyph;
5136
5137 if (w->phys_cursor.vpos >= 0
5138 && w->phys_cursor.vpos < w->current_matrix->nrows
5139 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5140 row->enabled_p)
5141 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5142 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5143 else
5144 glyph = NULL;
5145
5146 return glyph;
5147 }
5148
5149
5150 static int
5151 save_window_save (window, vector, i)
5152 Lisp_Object window;
5153 struct Lisp_Vector *vector;
5154 int i;
5155 {
5156 register struct saved_window *p;
5157 register struct window *w;
5158 register Lisp_Object tem;
5159
5160 for (;!NILP (window); window = w->next)
5161 {
5162 p = SAVED_WINDOW_N (vector, i);
5163 w = XWINDOW (window);
5164
5165 XSETFASTINT (w->temslot, i++);
5166 p->window = window;
5167 p->buffer = w->buffer;
5168 p->left = w->left;
5169 p->top = w->top;
5170 p->width = w->width;
5171 p->height = w->height;
5172 p->hscroll = w->hscroll;
5173 p->min_hscroll = w->min_hscroll;
5174 p->display_table = w->display_table;
5175 p->orig_top = w->orig_top;
5176 p->orig_height = w->orig_height;
5177 if (!NILP (w->buffer))
5178 {
5179 /* Save w's value of point in the window configuration.
5180 If w is the selected window, then get the value of point
5181 from the buffer; pointm is garbage in the selected window. */
5182 if (EQ (window, selected_window))
5183 {
5184 p->pointm = Fmake_marker ();
5185 set_marker_both (p->pointm, w->buffer,
5186 BUF_PT (XBUFFER (w->buffer)),
5187 BUF_PT_BYTE (XBUFFER (w->buffer)));
5188 }
5189 else
5190 p->pointm = Fcopy_marker (w->pointm, Qnil);
5191
5192 p->start = Fcopy_marker (w->start, Qnil);
5193 p->start_at_line_beg = w->start_at_line_beg;
5194
5195 tem = XBUFFER (w->buffer)->mark;
5196 p->mark = Fcopy_marker (tem, Qnil);
5197 }
5198 else
5199 {
5200 p->pointm = Qnil;
5201 p->start = Qnil;
5202 p->mark = Qnil;
5203 p->start_at_line_beg = Qnil;
5204 }
5205
5206 if (NILP (w->parent))
5207 p->parent = Qnil;
5208 else
5209 p->parent = XWINDOW (w->parent)->temslot;
5210
5211 if (NILP (w->prev))
5212 p->prev = Qnil;
5213 else
5214 p->prev = XWINDOW (w->prev)->temslot;
5215
5216 if (!NILP (w->vchild))
5217 i = save_window_save (w->vchild, vector, i);
5218 if (!NILP (w->hchild))
5219 i = save_window_save (w->hchild, vector, i);
5220 }
5221
5222 return i;
5223 }
5224
5225 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5226 Scurrent_window_configuration, 0, 1, 0,
5227 "Return an object representing the current window configuration of FRAME.\n\
5228 If FRAME is nil or omitted, use the selected frame.\n\
5229 This describes the number of windows, their sizes and current buffers,\n\
5230 and for each displayed buffer, where display starts, and the positions of\n\
5231 point and mark. An exception is made for point in the current buffer:\n\
5232 its value is -not- saved.\n\
5233 This also records the currently selected frame, and FRAME's focus\n\
5234 redirection (see `redirect-frame-focus').")
5235 (frame)
5236 Lisp_Object frame;
5237 {
5238 register Lisp_Object tem;
5239 register int n_windows;
5240 register struct save_window_data *data;
5241 register struct Lisp_Vector *vec;
5242 register int i;
5243 FRAME_PTR f;
5244
5245 if (NILP (frame))
5246 frame = selected_frame;
5247 CHECK_LIVE_FRAME (frame, 0);
5248 f = XFRAME (frame);
5249
5250 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5251 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
5252 for (i = 0; i < VECSIZE (struct save_window_data); i++)
5253 vec->contents[i] = Qnil;
5254 vec->size = VECSIZE (struct save_window_data);
5255 data = (struct save_window_data *)vec;
5256
5257 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
5258 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
5259 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5260 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5261 data->selected_frame = selected_frame;
5262 data->current_window = FRAME_SELECTED_WINDOW (f);
5263 XSETBUFFER (data->current_buffer, current_buffer);
5264 data->minibuf_scroll_window = Vminibuf_scroll_window;
5265 data->root_window = FRAME_ROOT_WINDOW (f);
5266 data->focus_frame = FRAME_FOCUS_FRAME (f);
5267 XSETINT (data->min_height, window_min_height);
5268 XSETINT (data->min_width, window_min_width);
5269 tem = Fmake_vector (make_number (n_windows), Qnil);
5270 data->saved_windows = tem;
5271 for (i = 0; i < n_windows; i++)
5272 XVECTOR (tem)->contents[i]
5273 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5274 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5275 XSETWINDOW_CONFIGURATION (tem, data);
5276 return (tem);
5277 }
5278
5279 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5280 0, UNEVALLED, 0,
5281 "Execute body, preserving window sizes and contents.\n\
5282 Restore which buffer appears in which window, where display starts,\n\
5283 and the value of point and mark for each window.\n\
5284 Also restore the choice of selected window.\n\
5285 Also restore which buffer is current.\n\
5286 Does not restore the value of point in current buffer.")
5287 (args)
5288 Lisp_Object args;
5289 {
5290 register Lisp_Object val;
5291 register int count = specpdl_ptr - specpdl;
5292
5293 record_unwind_protect (Fset_window_configuration,
5294 Fcurrent_window_configuration (Qnil));
5295 val = Fprogn (args);
5296 return unbind_to (count, val);
5297 }
5298
5299 \f
5300 /***********************************************************************
5301 Marginal Areas
5302 ***********************************************************************/
5303
5304 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5305 2, 3, 0,
5306 "Set width of marginal areas of window WINDOW.\n\
5307 If window is nil, set margins of the currently selected window.\n\
5308 First parameter LEFT-WIDTH specifies the number of character\n\
5309 cells to reserve for the left marginal area. Second parameter\n\
5310 RIGHT-WIDTH does the same for the right marginal area.\n\
5311 A nil width parameter means no margin.")
5312 (window, left, right)
5313 Lisp_Object window, left, right;
5314 {
5315 struct window *w = decode_window (window);
5316
5317 if (!NILP (left))
5318 CHECK_NUMBER_OR_FLOAT (left, 1);
5319 if (!NILP (right))
5320 CHECK_NUMBER_OR_FLOAT (right, 2);
5321
5322 /* Check widths < 0 and translate a zero width to nil.
5323 Margins that are too wide have to be checked elsewhere. */
5324 if ((INTEGERP (left) && XINT (left) < 0)
5325 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
5326 XSETFASTINT (left, 0);
5327 if (INTEGERP (left) && XFASTINT (left) == 0)
5328 left = Qnil;
5329
5330 if ((INTEGERP (right) && XINT (right) < 0)
5331 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5332 XSETFASTINT (right, 0);
5333 if (INTEGERP (right) && XFASTINT (right) == 0)
5334 right = Qnil;
5335
5336 w->left_margin_width = left;
5337 w->right_margin_width = right;
5338
5339 ++windows_or_buffers_changed;
5340 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5341 return Qnil;
5342 }
5343
5344
5345 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5346 0, 1, 0,
5347 "Get width of marginal areas of window WINDOW.\n\
5348 If WINDOW is omitted or nil, use the currently selected window.\n\
5349 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
5350 If a marginal area does not exist, its width will be returned\n\
5351 as nil.")
5352 (window)
5353 Lisp_Object window;
5354 {
5355 struct window *w = decode_window (window);
5356 return Fcons (w->left_margin_width, w->right_margin_width);
5357 }
5358
5359
5360 \f
5361 /***********************************************************************
5362 Smooth scrolling
5363 ***********************************************************************/
5364
5365 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
5366 "Return the amount by which WINDOW is scrolled vertically.\n\
5367 Use the selected window if WINDOW is nil or omitted.\n\
5368 Value is a multiple of the canonical character height of WINDOW.")
5369 (window)
5370 Lisp_Object window;
5371 {
5372 Lisp_Object result;
5373 struct frame *f;
5374 struct window *w;
5375
5376 if (NILP (window))
5377 window = selected_window;
5378 else
5379 CHECK_WINDOW (window, 0);
5380 w = XWINDOW (window);
5381 f = XFRAME (w->frame);
5382
5383 if (FRAME_WINDOW_P (f))
5384 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5385 else
5386 result = make_number (0);
5387 return result;
5388 }
5389
5390
5391 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
5392 2, 2, 0,
5393 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5394 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
5395 non-negative multiple of the canonical character height of WINDOW.")
5396 (window, vscroll)
5397 Lisp_Object window, vscroll;
5398 {
5399 struct window *w;
5400 struct frame *f;
5401
5402 if (NILP (window))
5403 window = selected_window;
5404 else
5405 CHECK_WINDOW (window, 0);
5406 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
5407
5408 w = XWINDOW (window);
5409 f = XFRAME (w->frame);
5410
5411 if (FRAME_WINDOW_P (f))
5412 {
5413 int old_dy = w->vscroll;
5414
5415 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
5416 w->vscroll = min (w->vscroll, 0);
5417
5418 /* Adjust glyph matrix of the frame if the virtual display
5419 area becomes larger than before. */
5420 if (w->vscroll < 0 && w->vscroll < old_dy)
5421 adjust_glyphs (f);
5422
5423 /* Prevent redisplay shortcuts. */
5424 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5425 }
5426
5427 return Fwindow_vscroll (window);
5428 }
5429
5430 \f
5431 /* Call FN for all leaf windows on frame F. FN is called with the
5432 first argument being a pointer to the leaf window, and with
5433 additional argument USER_DATA. Stops when FN returns 0. */
5434
5435 void
5436 foreach_window (f, fn, user_data)
5437 struct frame *f;
5438 int (* fn) P_ ((struct window *, void *));
5439 void *user_data;
5440 {
5441 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
5442 }
5443
5444
5445 /* Helper function for foreach_window. Call FN for all leaf windows
5446 reachable from W. FN is called with the first argument being a
5447 pointer to the leaf window, and with additional argument USER_DATA.
5448 Stop when FN returns 0. Value is 0 if stopped by FN. */
5449
5450 static int
5451 foreach_window_1 (w, fn, user_data)
5452 struct window *w;
5453 int (* fn) P_ ((struct window *, void *));
5454 void *user_data;
5455 {
5456 int cont;
5457
5458 for (cont = 1; w && cont;)
5459 {
5460 if (!NILP (w->hchild))
5461 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
5462 else if (!NILP (w->vchild))
5463 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
5464 else
5465 cont = fn (w, user_data);
5466
5467 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5468 }
5469
5470 return cont;
5471 }
5472
5473
5474 /* Freeze or unfreeze the window start of W if unless it is a
5475 mini-window or the selected window. FREEZE_P non-null means freeze
5476 the window start. */
5477
5478 static int
5479 freeze_window_start (w, freeze_p)
5480 struct window *w;
5481 void *freeze_p;
5482 {
5483 if (w == XWINDOW (selected_window)
5484 || MINI_WINDOW_P (w)
5485 || (MINI_WINDOW_P (XWINDOW (selected_window))
5486 && ! NILP (Vminibuf_scroll_window)
5487 && w == XWINDOW (Vminibuf_scroll_window)))
5488 freeze_p = NULL;
5489
5490 w->frozen_window_start_p = freeze_p != NULL;
5491 return 1;
5492 }
5493
5494
5495 /* Freeze or unfreeze the window starts of all leaf windows on frame
5496 F, except the selected window and a mini-window. FREEZE_P non-zero
5497 means freeze the window start. */
5498
5499 void
5500 freeze_window_starts (f, freeze_p)
5501 struct frame *f;
5502 int freeze_p;
5503 {
5504 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
5505 }
5506
5507 \f
5508 /***********************************************************************
5509 Initialization
5510 ***********************************************************************/
5511
5512 /* Return 1 if window configurations C1 and C2
5513 describe the same state of affairs. This is used by Fequal. */
5514
5515 int
5516 compare_window_configurations (c1, c2, ignore_positions)
5517 Lisp_Object c1, c2;
5518 int ignore_positions;
5519 {
5520 register struct save_window_data *d1, *d2;
5521 struct Lisp_Vector *sw1, *sw2;
5522 int i;
5523
5524 if (!WINDOW_CONFIGURATIONP (c1))
5525 wrong_type_argument (Qwindow_configuration_p, c1);
5526 if (!WINDOW_CONFIGURATIONP (c2))
5527 wrong_type_argument (Qwindow_configuration_p, c2);
5528
5529 d1 = (struct save_window_data *) XVECTOR (c1);
5530 d2 = (struct save_window_data *) XVECTOR (c2);
5531 sw1 = XVECTOR (d1->saved_windows);
5532 sw2 = XVECTOR (d2->saved_windows);
5533
5534 if (! EQ (d1->frame_width, d2->frame_width))
5535 return 0;
5536 if (! EQ (d1->frame_height, d2->frame_height))
5537 return 0;
5538 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5539 return 0;
5540 if (! EQ (d1->selected_frame, d2->selected_frame))
5541 return 0;
5542 /* Don't compare the current_window field directly.
5543 Instead see w1_is_current and w2_is_current, below. */
5544 if (! EQ (d1->current_buffer, d2->current_buffer))
5545 return 0;
5546 if (! ignore_positions)
5547 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5548 return 0;
5549 /* Don't compare the root_window field.
5550 We don't require the two configurations
5551 to use the same window object,
5552 and the two root windows must be equivalent
5553 if everything else compares equal. */
5554 if (! EQ (d1->focus_frame, d2->focus_frame))
5555 return 0;
5556 if (! EQ (d1->min_width, d2->min_width))
5557 return 0;
5558 if (! EQ (d1->min_height, d2->min_height))
5559 return 0;
5560
5561 /* Verify that the two confis have the same number of windows. */
5562 if (sw1->size != sw2->size)
5563 return 0;
5564
5565 for (i = 0; i < sw1->size; i++)
5566 {
5567 struct saved_window *p1, *p2;
5568 int w1_is_current, w2_is_current;
5569
5570 p1 = SAVED_WINDOW_N (sw1, i);
5571 p2 = SAVED_WINDOW_N (sw2, i);
5572
5573 /* Verify that the current windows in the two
5574 configurations correspond to each other. */
5575 w1_is_current = EQ (d1->current_window, p1->window);
5576 w2_is_current = EQ (d2->current_window, p2->window);
5577
5578 if (w1_is_current != w2_is_current)
5579 return 0;
5580
5581 /* Verify that the corresponding windows do match. */
5582 if (! EQ (p1->buffer, p2->buffer))
5583 return 0;
5584 if (! EQ (p1->left, p2->left))
5585 return 0;
5586 if (! EQ (p1->top, p2->top))
5587 return 0;
5588 if (! EQ (p1->width, p2->width))
5589 return 0;
5590 if (! EQ (p1->height, p2->height))
5591 return 0;
5592 if (! EQ (p1->display_table, p2->display_table))
5593 return 0;
5594 if (! EQ (p1->parent, p2->parent))
5595 return 0;
5596 if (! EQ (p1->prev, p2->prev))
5597 return 0;
5598 if (! ignore_positions)
5599 {
5600 if (! EQ (p1->hscroll, p2->hscroll))
5601 return 0;
5602 if (!EQ (p1->min_hscroll, p2->min_hscroll))
5603 return 0;
5604 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5605 return 0;
5606 if (NILP (Fequal (p1->start, p2->start)))
5607 return 0;
5608 if (NILP (Fequal (p1->pointm, p2->pointm)))
5609 return 0;
5610 if (NILP (Fequal (p1->mark, p2->mark)))
5611 return 0;
5612 }
5613 }
5614
5615 return 1;
5616 }
5617
5618 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5619 Scompare_window_configurations, 2, 2, 0,
5620 "Compare two window configurations as regards the structure of windows.\n\
5621 This function ignores details such as the values of point and mark\n\
5622 and scrolling positions.")
5623 (x, y)
5624 Lisp_Object x, y;
5625 {
5626 if (compare_window_configurations (x, y, 1))
5627 return Qt;
5628 return Qnil;
5629 }
5630 \f
5631 void
5632 init_window_once ()
5633 {
5634 struct frame *f = make_terminal_frame ();
5635 XSETFRAME (selected_frame, f);
5636 Vterminal_frame = selected_frame;
5637 minibuf_window = f->minibuffer_window;
5638 selected_window = f->selected_window;
5639 last_nonminibuf_frame = f;
5640
5641 window_initialized = 1;
5642 }
5643
5644 void
5645 init_window ()
5646 {
5647 Vwindow_list = Qnil;
5648 }
5649
5650 void
5651 syms_of_window ()
5652 {
5653 Qleft_fringe = intern ("left-fringe");
5654 staticpro (&Qleft_fringe);
5655 Qright_fringe = intern ("right-fringe");
5656 staticpro (&Qright_fringe);
5657
5658 Qwindow_size_fixed = intern ("window-size-fixed");
5659 staticpro (&Qwindow_size_fixed);
5660
5661 staticpro (&Qwindow_configuration_change_hook);
5662 Qwindow_configuration_change_hook
5663 = intern ("window-configuration-change-hook");
5664
5665 Qwindowp = intern ("windowp");
5666 staticpro (&Qwindowp);
5667
5668 Qwindow_configuration_p = intern ("window-configuration-p");
5669 staticpro (&Qwindow_configuration_p);
5670
5671 Qwindow_live_p = intern ("window-live-p");
5672 staticpro (&Qwindow_live_p);
5673
5674 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5675 staticpro (&Qtemp_buffer_show_hook);
5676
5677 staticpro (&Vwindow_list);
5678
5679 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5680 "Non-nil means call as function to display a help buffer.\n\
5681 The function is called with one argument, the buffer to be displayed.\n\
5682 Used by `with-output-to-temp-buffer'.\n\
5683 If this function is used, then it must do the entire job of showing\n\
5684 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5685 Vtemp_buffer_show_function = Qnil;
5686
5687 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5688 "If non-nil, function to call to handle `display-buffer'.\n\
5689 It will receive two args, the buffer and a flag which if non-nil means\n\
5690 that the currently selected window is not acceptable.\n\
5691 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5692 work using this function.");
5693 Vdisplay_buffer_function = Qnil;
5694
5695 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
5696 "*If non-nil, `display-buffer' should even the window heights.\n\
5697 If nil, `display-buffer' will leave the window configuration alone.");
5698 Veven_window_heights = Qt;
5699
5700 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5701 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5702 Vminibuf_scroll_window = Qnil;
5703
5704 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5705 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5706 Vother_window_scroll_buffer = Qnil;
5707
5708 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5709 "*Non-nil means `display-buffer' should make a separate frame.");
5710 pop_up_frames = 0;
5711
5712 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
5713 "*Non-nil means `display-buffer' should reuse frames.\n\
5714 If the buffer in question is already displayed in a frame, raise that frame.");
5715 display_buffer_reuse_frames = 0;
5716
5717 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5718 "Function to call to handle automatic new frame creation.\n\
5719 It is called with no arguments and should return a newly created frame.\n\
5720 \n\
5721 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5722 where `pop-up-frame-alist' would hold the default frame parameters.");
5723 Vpop_up_frame_function = Qnil;
5724
5725 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5726 "*List of buffer names that should have their own special frames.\n\
5727 Displaying a buffer whose name is in this list makes a special frame for it\n\
5728 using `special-display-function'. See also `special-display-regexps'.\n\
5729 \n\
5730 An element of the list can be a list instead of just a string.\n\
5731 There are two ways to use a list as an element:\n\
5732 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5733 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5734 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5735 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5736 All this is done by the function found in `special-display-function'.\n\
5737 \n\
5738 If this variable appears \"not to work\", because you add a name to it\n\
5739 but that buffer still appears in the selected window, look at the\n\
5740 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5741 Those variables take precedence over this one.");
5742 Vspecial_display_buffer_names = Qnil;
5743
5744 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5745 "*List of regexps saying which buffers should have their own special frames.\n\
5746 If a buffer name matches one of these regexps, it gets its own frame.\n\
5747 Displaying a buffer whose name is in this list makes a special frame for it\n\
5748 using `special-display-function'.\n\
5749 \n\
5750 An element of the list can be a list instead of just a string.\n\
5751 There are two ways to use a list as an element:\n\
5752 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5753 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5754 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5755 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5756 All this is done by the function found in `special-display-function'.\n\
5757 \n\
5758 If this variable appears \"not to work\", because you add a regexp to it\n\
5759 but the matching buffers still appear in the selected window, look at the\n\
5760 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5761 Those variables take precedence over this one.");
5762 Vspecial_display_regexps = Qnil;
5763
5764 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5765 "Function to call to make a new frame for a special buffer.\n\
5766 It is called with two arguments, the buffer and optional buffer specific\n\
5767 data, and should return a window displaying that buffer.\n\
5768 The default value makes a separate frame for the buffer,\n\
5769 using `special-display-frame-alist' to specify the frame parameters.\n\
5770 \n\
5771 A buffer is special if its is listed in `special-display-buffer-names'\n\
5772 or matches a regexp in `special-display-regexps'.");
5773 Vspecial_display_function = Qnil;
5774
5775 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5776 "*List of buffer names that should appear in the selected window.\n\
5777 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5778 switches to it in the selected window, rather than making it appear\n\
5779 in some other window.\n\
5780 \n\
5781 An element of the list can be a cons cell instead of just a string.\n\
5782 Then the car must be a string, which specifies the buffer name.\n\
5783 This is for compatibility with `special-display-buffer-names';\n\
5784 the cdr of the cons cell is ignored.\n\
5785 \n\
5786 See also `same-window-regexps'.");
5787 Vsame_window_buffer_names = Qnil;
5788
5789 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5790 "*List of regexps saying which buffers should appear in the selected window.\n\
5791 If a buffer name matches one of these regexps, then displaying it\n\
5792 using `display-buffer' or `pop-to-buffer' switches to it\n\
5793 in the selected window, rather than making it appear in some other window.\n\
5794 \n\
5795 An element of the list can be a cons cell instead of just a string.\n\
5796 Then the car must be a string, which specifies the buffer name.\n\
5797 This is for compatibility with `special-display-buffer-names';\n\
5798 the cdr of the cons cell is ignored.\n\
5799 \n\
5800 See also `same-window-buffer-names'.");
5801 Vsame_window_regexps = Qnil;
5802
5803 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5804 "*Non-nil means display-buffer should make new windows.");
5805 pop_up_windows = 1;
5806
5807 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5808 "*Number of lines of continuity when scrolling by screenfuls.");
5809 next_screen_context_lines = 2;
5810
5811 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5812 "*display-buffer would prefer to split the largest window if this large.\n\
5813 If there is only one window, it is split regardless of this value.");
5814 split_height_threshold = 500;
5815
5816 DEFVAR_INT ("window-min-height", &window_min_height,
5817 "*Delete any window less than this tall (including its mode line).");
5818 window_min_height = 4;
5819
5820 DEFVAR_INT ("window-min-width", &window_min_width,
5821 "*Delete any window less than this wide.");
5822 window_min_width = 10;
5823
5824 DEFVAR_LISP ("scroll-preserve-screen-position",
5825 &Vscroll_preserve_screen_position,
5826 "*Non-nil means scroll commands move point to keep its screen line unchanged.");
5827 Vscroll_preserve_screen_position = Qnil;
5828
5829 DEFVAR_LISP ("window-configuration-change-hook",
5830 &Vwindow_configuration_change_hook,
5831 "Functions to call when window configuration changes.\n\
5832 The selected frame is the one whose configuration has changed.");
5833 Vwindow_configuration_change_hook = Qnil;
5834
5835 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
5836 "Non-nil in a buffer means windows displaying the buffer are fixed-size.\n\
5837 Emacs won't change the size of any window displaying that buffer,\n\
5838 unless you explicitly change the size, or Emacs has no other choice.\n\
5839 This variable automatically becomes buffer-local when set.");
5840 Fmake_variable_buffer_local (Qwindow_size_fixed);
5841 window_size_fixed = 0;
5842
5843 defsubr (&Sselected_window);
5844 defsubr (&Sminibuffer_window);
5845 defsubr (&Swindow_minibuffer_p);
5846 defsubr (&Swindowp);
5847 defsubr (&Swindow_live_p);
5848 defsubr (&Spos_visible_in_window_p);
5849 defsubr (&Swindow_buffer);
5850 defsubr (&Swindow_height);
5851 defsubr (&Swindow_width);
5852 defsubr (&Swindow_hscroll);
5853 defsubr (&Sset_window_hscroll);
5854 defsubr (&Swindow_redisplay_end_trigger);
5855 defsubr (&Sset_window_redisplay_end_trigger);
5856 defsubr (&Swindow_edges);
5857 defsubr (&Scoordinates_in_window_p);
5858 defsubr (&Swindow_at);
5859 defsubr (&Swindow_point);
5860 defsubr (&Swindow_start);
5861 defsubr (&Swindow_end);
5862 defsubr (&Sset_window_point);
5863 defsubr (&Sset_window_start);
5864 defsubr (&Swindow_dedicated_p);
5865 defsubr (&Sset_window_dedicated_p);
5866 defsubr (&Swindow_display_table);
5867 defsubr (&Sset_window_display_table);
5868 defsubr (&Snext_window);
5869 defsubr (&Sprevious_window);
5870 defsubr (&Sother_window);
5871 defsubr (&Sget_lru_window);
5872 defsubr (&Sget_largest_window);
5873 defsubr (&Sget_buffer_window);
5874 defsubr (&Sdelete_other_windows);
5875 defsubr (&Sdelete_windows_on);
5876 defsubr (&Sreplace_buffer_in_windows);
5877 defsubr (&Sdelete_window);
5878 defsubr (&Sset_window_buffer);
5879 defsubr (&Sselect_window);
5880 defsubr (&Sspecial_display_p);
5881 defsubr (&Ssame_window_p);
5882 defsubr (&Sdisplay_buffer);
5883 defsubr (&Ssplit_window);
5884 defsubr (&Senlarge_window);
5885 defsubr (&Sshrink_window);
5886 defsubr (&Sscroll_up);
5887 defsubr (&Sscroll_down);
5888 defsubr (&Sscroll_left);
5889 defsubr (&Sscroll_right);
5890 defsubr (&Sother_window_for_scrolling);
5891 defsubr (&Sscroll_other_window);
5892 defsubr (&Srecenter);
5893 defsubr (&Swindow_text_height);
5894 defsubr (&Smove_to_window_line);
5895 defsubr (&Swindow_configuration_p);
5896 defsubr (&Swindow_configuration_frame);
5897 defsubr (&Sset_window_configuration);
5898 defsubr (&Scurrent_window_configuration);
5899 defsubr (&Ssave_window_excursion);
5900 defsubr (&Sset_window_margins);
5901 defsubr (&Swindow_margins);
5902 defsubr (&Swindow_vscroll);
5903 defsubr (&Sset_window_vscroll);
5904 defsubr (&Scompare_window_configurations);
5905 defsubr (&Swindow_list);
5906 }
5907
5908 void
5909 keys_of_window ()
5910 {
5911 initial_define_key (control_x_map, '1', "delete-other-windows");
5912 initial_define_key (control_x_map, '2', "split-window");
5913 initial_define_key (control_x_map, '0', "delete-window");
5914 initial_define_key (control_x_map, 'o', "other-window");
5915 initial_define_key (control_x_map, '^', "enlarge-window");
5916 initial_define_key (control_x_map, '<', "scroll-left");
5917 initial_define_key (control_x_map, '>', "scroll-right");
5918
5919 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5920 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5921 initial_define_key (meta_map, 'v', "scroll-down");
5922
5923 initial_define_key (global_map, Ctl('L'), "recenter");
5924 initial_define_key (meta_map, 'r', "move-to-window-line");
5925 }