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