]> code.delx.au - gnu-emacs/blob - src/window.c
* window.c (window_scroll_pixel_based_preserve_x)
[gnu-emacs] / src / window.c
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
4 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 Free Software Foundation, Inc.
6
7 This file is part of GNU Emacs.
8
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include <config.h>
23 #include <stdio.h>
24
25 #include "lisp.h"
26 #include "buffer.h"
27 #include "keyboard.h"
28 #include "keymap.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "commands.h"
32 #include "indent.h"
33 #include "termchar.h"
34 #include "disptab.h"
35 #include "dispextern.h"
36 #include "blockinput.h"
37 #include "intervals.h"
38 #include "termhooks.h" /* For FRAME_TERMINAL. */
39
40 #ifdef HAVE_X_WINDOWS
41 #include "xterm.h"
42 #endif /* HAVE_X_WINDOWS */
43 #ifdef WINDOWSNT
44 #include "w32term.h"
45 #endif
46 #ifdef MSDOS
47 #include "msdos.h"
48 #endif
49 #ifdef MAC_OS
50 #include "macterm.h"
51 #endif
52
53
54 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
55 Lisp_Object Qscroll_up, Qscroll_down;
56 Lisp_Object Qwindow_size_fixed;
57 extern Lisp_Object Qleft_margin, Qright_margin;
58
59 static int displayed_window_lines P_ ((struct window *));
60 static struct window *decode_window P_ ((Lisp_Object));
61 static int count_windows P_ ((struct window *));
62 static int get_leaf_windows P_ ((struct window *, struct window **, int));
63 static void window_scroll P_ ((Lisp_Object, int, int, int));
64 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
65 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
66 static int window_min_size_1 P_ ((struct window *, int, int));
67 static int window_min_size_2 P_ ((struct window *, int, int));
68 static int window_min_size P_ ((struct window *, int, int, int, int *));
69 static void size_window P_ ((Lisp_Object, int, int, int, int, int));
70 static int freeze_window_start P_ ((struct window *, void *));
71 static int window_fixed_size_p P_ ((struct window *, int, int));
72 static void enlarge_window P_ ((Lisp_Object, int, int));
73 static Lisp_Object window_list P_ ((void));
74 static int add_window_to_list P_ ((struct window *, void *));
75 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
76 Lisp_Object));
77 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
78 Lisp_Object, int));
79 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
80 Lisp_Object *));
81 static int foreach_window_1 P_ ((struct window *,
82 int (* fn) (struct window *, void *),
83 void *));
84 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
85
86 /* This is the window in which the terminal's cursor should
87 be left when nothing is being done with it. This must
88 always be a leaf window, and its buffer is selected by
89 the top level editing loop at the end of each command.
90
91 This value is always the same as
92 FRAME_SELECTED_WINDOW (selected_frame). */
93
94 Lisp_Object selected_window;
95
96 /* A list of all windows for use by next_window and Fwindow_list.
97 Functions creating or deleting windows should invalidate this cache
98 by setting it to nil. */
99
100 Lisp_Object Vwindow_list;
101
102 /* The mini-buffer window of the selected frame.
103 Note that you cannot test for mini-bufferness of an arbitrary window
104 by comparing against this; but you can test for mini-bufferness of
105 the selected window. */
106
107 Lisp_Object minibuf_window;
108
109 /* Non-nil means it is the window whose mode line should be
110 shown as the selected window when the minibuffer is selected. */
111
112 Lisp_Object minibuf_selected_window;
113
114 /* Non-nil means it is the window for C-M-v to scroll
115 when the mini-buffer is selected. */
116
117 Lisp_Object Vminibuf_scroll_window;
118
119 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
120
121 Lisp_Object Vother_window_scroll_buffer;
122
123 /* Non-nil means it's function to call to display temp buffers. */
124
125 Lisp_Object Vtemp_buffer_show_function;
126
127 /* Non-zero means line and page scrolling on tall lines (with images)
128 does partial scrolling by modifying window-vscroll. */
129
130 int auto_window_vscroll_p;
131
132 /* Non-zero means to use mode-line-inactive face in all windows but the
133 selected-window and the minibuffer-scroll-window when the
134 minibuffer is active. */
135 int mode_line_in_non_selected_windows;
136
137 /* If a window gets smaller than either of these, it is removed. */
138
139 EMACS_INT window_min_height;
140 EMACS_INT window_min_width;
141
142 /* Nonzero implies Fdisplay_buffer should create windows. */
143
144 int pop_up_windows;
145
146 /* Nonzero implies make new frames for Fdisplay_buffer. */
147
148 int pop_up_frames;
149
150 /* Nonzero means reuse existing frames for displaying buffers. */
151
152 int display_buffer_reuse_frames;
153
154 /* Non-nil means use this function instead of default */
155
156 Lisp_Object Vpop_up_frame_function;
157
158 /* Function to call to handle Fdisplay_buffer. */
159
160 Lisp_Object Vdisplay_buffer_function;
161
162 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
163
164 Lisp_Object Veven_window_heights;
165
166 /* List of buffer *names* for buffers that should have their own frames. */
167
168 Lisp_Object Vspecial_display_buffer_names;
169
170 /* List of regexps for buffer names that should have their own frames. */
171
172 Lisp_Object Vspecial_display_regexps;
173
174 /* Function to pop up a special frame. */
175
176 Lisp_Object Vspecial_display_function;
177
178 /* List of buffer *names* for buffers to appear in selected window. */
179
180 Lisp_Object Vsame_window_buffer_names;
181
182 /* List of regexps for buffer names to appear in selected window. */
183
184 Lisp_Object Vsame_window_regexps;
185
186 /* Hook run at end of temp_output_buffer_show. */
187
188 Lisp_Object Qtemp_buffer_show_hook;
189
190 /* Fdisplay_buffer always splits the largest window
191 if that window is more than this high. */
192
193 EMACS_INT split_height_threshold;
194
195 /* How to split windows (horizontally/vertically/hybrid). */
196
197 Lisp_Object Vsplit_window_preferred_function;
198
199 /* Number of lines of continuity in scrolling by screenfuls. */
200
201 EMACS_INT next_screen_context_lines;
202
203 /* Incremented for each window created. */
204
205 static int sequence_number;
206
207 /* Nonzero after init_window_once has finished. */
208
209 static int window_initialized;
210
211 /* Hook to run when window config changes. */
212
213 static Lisp_Object Qwindow_configuration_change_hook;
214 static Lisp_Object Vwindow_configuration_change_hook;
215
216 /* Non-nil means scroll commands try to put point
217 at the same screen height as previously. */
218
219 Lisp_Object Vscroll_preserve_screen_position;
220
221 /* Incremented by 1 whenever a window is deleted. */
222
223 int window_deletion_count;
224
225 /* Used by the function window_scroll_pixel_based */
226
227 static int window_scroll_pixel_based_preserve_x;
228 static int window_scroll_pixel_based_preserve_y;
229
230 /* Same for window_scroll_line_based. */
231
232 static int window_scroll_preserve_hpos;
233 static int window_scroll_preserve_vpos;
234
235 #if 0 /* This isn't used anywhere. */
236 /* Nonzero means we can split a frame even if it is "unsplittable". */
237 static int inhibit_frame_unsplittable;
238 #endif /* 0 */
239
240 extern EMACS_INT scroll_margin;
241
242 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
243 \f
244 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
245 doc: /* Returns t if OBJECT is a window. */)
246 (object)
247 Lisp_Object object;
248 {
249 return WINDOWP (object) ? Qt : Qnil;
250 }
251
252 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
253 doc: /* Returns t if OBJECT is a window which is currently visible. */)
254 (object)
255 Lisp_Object object;
256 {
257 return WINDOW_LIVE_P (object) ? Qt : Qnil;
258 }
259
260 Lisp_Object
261 make_window ()
262 {
263 Lisp_Object val;
264 register struct window *p;
265
266 p = allocate_window ();
267 ++sequence_number;
268 XSETFASTINT (p->sequence_number, sequence_number);
269 XSETFASTINT (p->left_col, 0);
270 XSETFASTINT (p->top_line, 0);
271 XSETFASTINT (p->total_lines, 0);
272 XSETFASTINT (p->total_cols, 0);
273 XSETFASTINT (p->hscroll, 0);
274 XSETFASTINT (p->min_hscroll, 0);
275 p->orig_top_line = p->orig_total_lines = Qnil;
276 p->start = Fmake_marker ();
277 p->pointm = Fmake_marker ();
278 XSETFASTINT (p->use_time, 0);
279 p->frame = Qnil;
280 p->display_table = Qnil;
281 p->dedicated = Qnil;
282 p->window_parameters = Qnil;
283 p->pseudo_window_p = 0;
284 bzero (&p->cursor, sizeof (p->cursor));
285 bzero (&p->last_cursor, sizeof (p->last_cursor));
286 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
287 p->desired_matrix = p->current_matrix = 0;
288 p->nrows_scale_factor = p->ncols_scale_factor = 1;
289 p->phys_cursor_type = -1;
290 p->phys_cursor_width = -1;
291 p->must_be_updated_p = 0;
292 XSETFASTINT (p->window_end_vpos, 0);
293 XSETFASTINT (p->window_end_pos, 0);
294 p->window_end_valid = Qnil;
295 p->vscroll = 0;
296 XSETWINDOW (val, p);
297 XSETFASTINT (p->last_point, 0);
298 p->frozen_window_start_p = 0;
299 p->last_cursor_off_p = p->cursor_off_p = 0;
300 p->left_margin_cols = Qnil;
301 p->right_margin_cols = Qnil;
302 p->left_fringe_width = Qnil;
303 p->right_fringe_width = Qnil;
304 p->fringes_outside_margins = Qnil;
305 p->scroll_bar_width = Qnil;
306 p->vertical_scroll_bar_type = Qt;
307 p->resize_proportionally = Qnil;
308
309 Vwindow_list = Qnil;
310 return val;
311 }
312
313 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
314 doc: /* Return the window that the cursor now appears in and commands apply to. */)
315 ()
316 {
317 return selected_window;
318 }
319
320 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
321 doc: /* Return the window used now for minibuffers.
322 If the optional argument FRAME is specified, return the minibuffer window
323 used by that frame. */)
324 (frame)
325 Lisp_Object frame;
326 {
327 if (NILP (frame))
328 frame = selected_frame;
329 CHECK_LIVE_FRAME (frame);
330 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
331 }
332
333 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
334 doc: /* Returns non-nil if WINDOW is a minibuffer window.
335 WINDOW defaults to the selected window. */)
336 (window)
337 Lisp_Object window;
338 {
339 struct window *w = decode_window (window);
340 return MINI_WINDOW_P (w) ? Qt : Qnil;
341 }
342
343
344 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
345 Spos_visible_in_window_p, 0, 3, 0,
346 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
347 Return nil if that position is scrolled vertically out of view.
348 If a character is only partially visible, nil is returned, unless the
349 optional argument PARTIALLY is non-nil.
350 If POS is only out of view because of horizontal scrolling, return non-nil.
351 If POS is t, it specifies the position of the last visible glyph in WINDOW.
352 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
353
354 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
355 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
356 where X and Y are the pixel coordinates relative to the top left corner
357 of the window. The remaining elements are omitted if the character after
358 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
359 off-window at the top and bottom of the row, ROWH is the height of the
360 display row, and VPOS is the row number (0-based) containing POS. */)
361 (pos, window, partially)
362 Lisp_Object pos, window, partially;
363 {
364 register struct window *w;
365 register int posint;
366 register struct buffer *buf;
367 struct text_pos top;
368 Lisp_Object in_window = Qnil;
369 int rtop, rbot, rowh, vpos, fully_p = 1;
370 int x, y;
371
372 w = decode_window (window);
373 buf = XBUFFER (w->buffer);
374 SET_TEXT_POS_FROM_MARKER (top, w->start);
375
376 if (EQ (pos, Qt))
377 posint = -1;
378 else if (!NILP (pos))
379 {
380 CHECK_NUMBER_COERCE_MARKER (pos);
381 posint = XINT (pos);
382 }
383 else if (w == XWINDOW (selected_window))
384 posint = PT;
385 else
386 posint = XMARKER (w->pointm)->charpos;
387
388 /* If position is above window start or outside buffer boundaries,
389 or if window start is out of range, position is not visible. */
390 if ((EQ (pos, Qt)
391 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
392 && CHARPOS (top) >= BUF_BEGV (buf)
393 && CHARPOS (top) <= BUF_ZV (buf)
394 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
395 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
396 in_window = Qt;
397
398 if (!NILP (in_window) && !NILP (partially))
399 {
400 Lisp_Object part = Qnil;
401 if (!fully_p)
402 part = list4 (make_number (rtop), make_number (rbot),
403 make_number (rowh), make_number (vpos));
404 in_window = Fcons (make_number (x),
405 Fcons (make_number (y), part));
406 }
407
408 return in_window;
409 }
410
411 DEFUN ("window-line-height", Fwindow_line_height,
412 Swindow_line_height, 0, 2, 0,
413 doc: /* Return height in pixels of text line LINE in window WINDOW.
414 If WINDOW is nil or omitted, use selected window.
415
416 Return height of current line if LINE is omitted or nil. Return height of
417 header or mode line if LINE is `header-line' and `mode-line'.
418 Otherwise, LINE is a text line number starting from 0. A negative number
419 counts from the end of the window.
420
421 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
422 in pixels of the visible part of the line, VPOS and YPOS are the
423 vertical position in lines and pixels of the line, relative to the top
424 of the first text line, and OFFBOT is the number of off-window pixels at
425 the bottom of the text line. If there are off-window pixels at the top
426 of the (first) text line, YPOS is negative.
427
428 Return nil if window display is not up-to-date. In that case, use
429 `pos-visible-in-window-p' to obtain the information. */)
430 (line, window)
431 Lisp_Object line, window;
432 {
433 register struct window *w;
434 register struct buffer *b;
435 struct glyph_row *row, *end_row;
436 int max_y, crop, i, n;
437
438 w = decode_window (window);
439
440 if (noninteractive
441 || w->pseudo_window_p)
442 return Qnil;
443
444 CHECK_BUFFER (w->buffer);
445 b = XBUFFER (w->buffer);
446
447 /* Fail if current matrix is not up-to-date. */
448 if (NILP (w->window_end_valid)
449 || current_buffer->clip_changed
450 || current_buffer->prevent_redisplay_optimizations_p
451 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
452 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
453 return Qnil;
454
455 if (NILP (line))
456 {
457 i = w->cursor.vpos;
458 if (i < 0 || i >= w->current_matrix->nrows
459 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
460 return Qnil;
461 max_y = window_text_bottom_y (w);
462 goto found_row;
463 }
464
465 if (EQ (line, Qheader_line))
466 {
467 if (!WINDOW_WANTS_HEADER_LINE_P (w))
468 return Qnil;
469 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
470 if (!row->enabled_p)
471 return Qnil;
472 return list4 (make_number (row->height),
473 make_number (0), make_number (0),
474 make_number (0));
475 }
476
477 if (EQ (line, Qmode_line))
478 {
479 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
480 if (!row->enabled_p)
481 return Qnil;
482 return list4 (make_number (row->height),
483 make_number (0), /* not accurate */
484 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
485 + window_text_bottom_y (w)),
486 make_number (0));
487 }
488
489 CHECK_NUMBER (line);
490 n = XINT (line);
491
492 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
493 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
494 max_y = window_text_bottom_y (w);
495 i = 0;
496
497 while ((n < 0 || i < n)
498 && row <= end_row && row->enabled_p
499 && row->y + row->height < max_y)
500 row++, i++;
501
502 if (row > end_row || !row->enabled_p)
503 return Qnil;
504
505 if (++n < 0)
506 {
507 if (-n > i)
508 return Qnil;
509 row += n;
510 i += n;
511 }
512
513 found_row:
514 crop = max (0, (row->y + row->height) - max_y);
515 return list4 (make_number (row->height + min (0, row->y) - crop),
516 make_number (i),
517 make_number (row->y),
518 make_number (crop));
519 }
520
521
522 \f
523 static struct window *
524 decode_window (window)
525 register Lisp_Object window;
526 {
527 if (NILP (window))
528 return XWINDOW (selected_window);
529
530 CHECK_LIVE_WINDOW (window);
531 return XWINDOW (window);
532 }
533
534 static struct window *
535 decode_any_window (window)
536 register Lisp_Object window;
537 {
538 if (NILP (window))
539 return XWINDOW (selected_window);
540
541 CHECK_WINDOW (window);
542 return XWINDOW (window);
543 }
544
545 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
546 doc: /* Return the buffer that WINDOW is displaying.
547 WINDOW defaults to the selected window. */)
548 (window)
549 Lisp_Object window;
550 {
551 return decode_window (window)->buffer;
552 }
553
554 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
555 doc: /* Return the number of lines in WINDOW (including its mode line).
556 WINDOW defaults to the selected window. */)
557 (window)
558 Lisp_Object window;
559 {
560 return decode_any_window (window)->total_lines;
561 }
562
563 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
564 doc: /* Return the number of display columns in WINDOW.
565 This is the width that is usable columns available for text in WINDOW.
566 If you want to find out how many columns WINDOW takes up,
567 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
568 (window)
569 Lisp_Object window;
570 {
571 return make_number (window_box_text_cols (decode_any_window (window)));
572 }
573
574 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
575 doc: /* Return t if WINDOW is as wide as its frame.
576 WINDOW defaults to the selected window. */)
577 (window)
578 Lisp_Object window;
579 {
580 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
581 }
582
583 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
584 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
585 WINDOW defaults to the selected window. */)
586 (window)
587 Lisp_Object window;
588 {
589 return decode_window (window)->hscroll;
590 }
591
592 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
593 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
594 Return NCOL. NCOL should be zero or positive.
595
596 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
597 window so that the location of point moves off-window. */)
598 (window, ncol)
599 Lisp_Object window, ncol;
600 {
601 struct window *w = decode_window (window);
602 int hscroll;
603
604 CHECK_NUMBER (ncol);
605 hscroll = max (0, XINT (ncol));
606
607 /* Prevent redisplay shortcuts when changing the hscroll. */
608 if (XINT (w->hscroll) != hscroll)
609 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
610
611 w->hscroll = make_number (hscroll);
612 return ncol;
613 }
614
615 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
616 Swindow_redisplay_end_trigger, 0, 1, 0,
617 doc: /* Return WINDOW's redisplay end trigger value.
618 WINDOW defaults to the selected window.
619 See `set-window-redisplay-end-trigger' for more information. */)
620 (window)
621 Lisp_Object window;
622 {
623 return decode_window (window)->redisplay_end_trigger;
624 }
625
626 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
627 Sset_window_redisplay_end_trigger, 2, 2, 0,
628 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
629 VALUE should be a buffer position (typically a marker) or nil.
630 If it is a buffer position, then if redisplay in WINDOW reaches a position
631 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
632 with two arguments: WINDOW, and the end trigger value.
633 Afterwards the end-trigger value is reset to nil. */)
634 (window, value)
635 register Lisp_Object window, value;
636 {
637 register struct window *w;
638
639 w = decode_window (window);
640 w->redisplay_end_trigger = value;
641 return value;
642 }
643
644 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
645 doc: /* Return a list of the edge coordinates of WINDOW.
646 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
647 RIGHT is one more than the rightmost column occupied by WINDOW,
648 and BOTTOM is one more than the bottommost row occupied by WINDOW.
649 The edges include the space used by the window's scroll bar,
650 display margins, fringes, header line, and mode line, if it has them.
651 To get the edges of the actual text area, use `window-inside-edges'. */)
652 (window)
653 Lisp_Object window;
654 {
655 register struct window *w = decode_any_window (window);
656
657 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
658 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
659 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
660 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
661 Qnil))));
662 }
663
664 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
665 doc: /* Return a list of the edge pixel coordinates of WINDOW.
666 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
667 RIGHT is one more than the rightmost x position occupied by WINDOW,
668 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
669 The pixel edges include the space used by the window's scroll bar,
670 display margins, fringes, header line, and mode line, if it has them.
671 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
672 (window)
673 Lisp_Object window;
674 {
675 register struct window *w = decode_any_window (window);
676
677 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
678 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
679 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
680 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
681 Qnil))));
682 }
683
684 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
685 doc: /* Return a list of the edge coordinates of WINDOW.
686 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
687 RIGHT is one more than the rightmost column used by text in WINDOW,
688 and BOTTOM is one more than the bottommost row used by text in WINDOW.
689 The inside edges do not include the space used by the window's scroll bar,
690 display margins, fringes, header line, and/or mode line. */)
691 (window)
692 Lisp_Object window;
693 {
694 register struct window *w = decode_any_window (window);
695
696 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
697 + WINDOW_LEFT_MARGIN_COLS (w)
698 + WINDOW_LEFT_FRINGE_COLS (w)),
699 make_number (WINDOW_TOP_EDGE_LINE (w)
700 + WINDOW_HEADER_LINE_LINES (w)),
701 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
702 - WINDOW_RIGHT_MARGIN_COLS (w)
703 - WINDOW_RIGHT_FRINGE_COLS (w)),
704 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
705 - WINDOW_MODE_LINE_LINES (w)));
706 }
707
708 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
709 doc: /* Return a list of the edge pixel coordinates of WINDOW.
710 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
711 RIGHT is one more than the rightmost x position used by text in WINDOW,
712 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
713 The inside edges do not include the space used by the window's scroll bar,
714 display margins, fringes, header line, and/or mode line. */)
715 (window)
716 Lisp_Object window;
717 {
718 register struct window *w = decode_any_window (window);
719
720 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
721 + WINDOW_LEFT_MARGIN_WIDTH (w)
722 + WINDOW_LEFT_FRINGE_WIDTH (w)),
723 make_number (WINDOW_TOP_EDGE_Y (w)
724 + WINDOW_HEADER_LINE_HEIGHT (w)),
725 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
726 - WINDOW_RIGHT_MARGIN_WIDTH (w)
727 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
728 make_number (WINDOW_BOTTOM_EDGE_Y (w)
729 - WINDOW_MODE_LINE_HEIGHT (w)));
730 }
731
732 /* Test if the character at column *X, row *Y is within window W.
733 If it is not, return ON_NOTHING;
734 if it is in the window's text area,
735 set *x and *y to its location relative to the upper left corner
736 of the window, and
737 return ON_TEXT;
738 if it is on the window's modeline, return ON_MODE_LINE;
739 if it is on the border between the window and its right sibling,
740 return ON_VERTICAL_BORDER.
741 if it is on a scroll bar,
742 return ON_SCROLL_BAR.
743 if it is on the window's top line, return ON_HEADER_LINE;
744 if it is in left or right fringe of the window,
745 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
746 to window-relative coordinates;
747 if it is in the marginal area to the left/right of the window,
748 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
749 to window-relative coordinates.
750
751 X and Y are frame relative pixel coordinates. */
752
753 static enum window_part
754 coordinates_in_window (w, x, y)
755 register struct window *w;
756 register int *x, *y;
757 {
758 struct frame *f = XFRAME (WINDOW_FRAME (w));
759 int left_x, right_x, top_y, bottom_y;
760 enum window_part part;
761 int ux = FRAME_COLUMN_WIDTH (f);
762 int x0 = WINDOW_LEFT_EDGE_X (w);
763 int x1 = WINDOW_RIGHT_EDGE_X (w);
764 /* The width of the area where the vertical line can be dragged.
765 (Between mode lines for instance. */
766 int grabbable_width = ux;
767 int lmargin_width, rmargin_width, text_left, text_right;
768
769 /* In what's below, we subtract 1 when computing right_x because we
770 want the rightmost pixel, which is given by left_pixel+width-1. */
771 if (w->pseudo_window_p)
772 {
773 left_x = 0;
774 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
775 top_y = WINDOW_TOP_EDGE_Y (w);
776 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
777 }
778 else
779 {
780 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
781 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
782 top_y = WINDOW_TOP_EDGE_Y (w);
783 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
784 }
785
786 /* Outside any interesting row? */
787 if (*y < top_y || *y >= bottom_y)
788 return ON_NOTHING;
789
790 /* On the mode line or header line? If it's near the start of
791 the mode or header line of window that's has a horizontal
792 sibling, say it's on the vertical line. That's to be able
793 to resize windows horizontally in case we're using toolkit
794 scroll bars. */
795
796 if (WINDOW_WANTS_MODELINE_P (w)
797 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
798 {
799 part = ON_MODE_LINE;
800
801 header_vertical_border_check:
802 /* We're somewhere on the mode line. We consider the place
803 between mode lines of horizontally adjacent mode lines
804 as the vertical border. If scroll bars on the left,
805 return the right window. */
806 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
807 || WINDOW_RIGHTMOST_P (w))
808 {
809 if (!WINDOW_LEFTMOST_P (w) && eabs (*x - x0) < grabbable_width)
810 {
811 /* Convert X and Y to window relative coordinates.
812 Vertical border is at the left edge of window. */
813 *x = max (0, *x - x0);
814 *y -= top_y;
815 return ON_VERTICAL_BORDER;
816 }
817 }
818 else
819 {
820 if (eabs (*x - x1) < grabbable_width)
821 {
822 /* Convert X and Y to window relative coordinates.
823 Vertical border is at the right edge of window. */
824 *x = min (x1, *x) - x0;
825 *y -= top_y;
826 return ON_VERTICAL_BORDER;
827 }
828 }
829
830 if (*x < x0 || *x >= x1)
831 return ON_NOTHING;
832
833 /* Convert X and Y to window relative coordinates.
834 Mode line starts at left edge of window. */
835 *x -= x0;
836 *y -= top_y;
837 return part;
838 }
839
840 if (WINDOW_WANTS_HEADER_LINE_P (w)
841 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
842 {
843 part = ON_HEADER_LINE;
844 goto header_vertical_border_check;
845 }
846
847 if (*x < x0 || *x >= x1)
848 return ON_NOTHING;
849
850 /* Outside any interesting column? */
851 if (*x < left_x || *x > right_x)
852 {
853 *y -= top_y;
854 return ON_SCROLL_BAR;
855 }
856
857 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
858 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
859
860 text_left = window_box_left (w, TEXT_AREA);
861 text_right = text_left + window_box_width (w, TEXT_AREA);
862
863 if (FRAME_WINDOW_P (f))
864 {
865 if (!w->pseudo_window_p
866 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
867 && !WINDOW_RIGHTMOST_P (w)
868 && (eabs (*x - right_x) < grabbable_width))
869 {
870 /* Convert X and Y to window relative coordinates.
871 Vertical border is at the right edge of window. */
872 *x = min (right_x, *x) - left_x;
873 *y -= top_y;
874 return ON_VERTICAL_BORDER;
875 }
876 }
877 else
878 {
879 /* Need to say "*x > right_x" rather than >=, since on character
880 terminals, the vertical line's x coordinate is right_x. */
881 if (!w->pseudo_window_p
882 && !WINDOW_RIGHTMOST_P (w)
883 && *x > right_x - ux)
884 {
885 /* On the border on the right side of the window? Assume that
886 this area begins at RIGHT_X minus a canonical char width. */
887 *x = min (right_x, *x) - left_x;
888 *y -= top_y;
889 return ON_VERTICAL_BORDER;
890 }
891 }
892
893 if (*x < text_left)
894 {
895 if (lmargin_width > 0
896 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
897 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
898 : (*x < left_x + lmargin_width)))
899 {
900 *x -= left_x;
901 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
902 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
903 *y -= top_y;
904 return ON_LEFT_MARGIN;
905 }
906
907 /* Convert X and Y to window-relative pixel coordinates. */
908 *x -= left_x;
909 *y -= top_y;
910 return ON_LEFT_FRINGE;
911 }
912
913 if (*x >= text_right)
914 {
915 if (rmargin_width > 0
916 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
917 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
918 : (*x >= right_x - rmargin_width)))
919 {
920 *x -= right_x - rmargin_width;
921 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
922 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
923 *y -= top_y;
924 return ON_RIGHT_MARGIN;
925 }
926
927 /* Convert X and Y to window-relative pixel coordinates. */
928 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
929 *y -= top_y;
930 return ON_RIGHT_FRINGE;
931 }
932
933 /* Everything special ruled out - must be on text area */
934 *x -= text_left;
935 *y -= top_y;
936 return ON_TEXT;
937 }
938
939
940 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
941 Scoordinates_in_window_p, 2, 2, 0,
942 doc: /* Return non-nil if COORDINATES are in WINDOW.
943 COORDINATES is a cons of the form (X . Y), X and Y being distances
944 measured in characters from the upper-left corner of the frame.
945 \(0 . 0) denotes the character in the upper left corner of the
946 frame.
947 If COORDINATES are in the text portion of WINDOW,
948 the coordinates relative to the window are returned.
949 If they are in the mode line of WINDOW, `mode-line' is returned.
950 If they are in the top mode line of WINDOW, `header-line' is returned.
951 If they are in the left fringe of WINDOW, `left-fringe' is returned.
952 If they are in the right fringe of WINDOW, `right-fringe' is returned.
953 If they are on the border between WINDOW and its right sibling,
954 `vertical-line' is returned.
955 If they are in the windows's left or right marginal areas, `left-margin'\n\
956 or `right-margin' is returned. */)
957 (coordinates, window)
958 register Lisp_Object coordinates, window;
959 {
960 struct window *w;
961 struct frame *f;
962 int x, y;
963 Lisp_Object lx, ly;
964
965 CHECK_WINDOW (window);
966 w = XWINDOW (window);
967 f = XFRAME (w->frame);
968 CHECK_CONS (coordinates);
969 lx = Fcar (coordinates);
970 ly = Fcdr (coordinates);
971 CHECK_NUMBER_OR_FLOAT (lx);
972 CHECK_NUMBER_OR_FLOAT (ly);
973 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
974 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
975
976 switch (coordinates_in_window (w, &x, &y))
977 {
978 case ON_NOTHING:
979 return Qnil;
980
981 case ON_TEXT:
982 /* X and Y are now window relative pixel coordinates. Convert
983 them to canonical char units before returning them. */
984 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
985 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
986
987 case ON_MODE_LINE:
988 return Qmode_line;
989
990 case ON_VERTICAL_BORDER:
991 return Qvertical_line;
992
993 case ON_HEADER_LINE:
994 return Qheader_line;
995
996 case ON_LEFT_FRINGE:
997 return Qleft_fringe;
998
999 case ON_RIGHT_FRINGE:
1000 return Qright_fringe;
1001
1002 case ON_LEFT_MARGIN:
1003 return Qleft_margin;
1004
1005 case ON_RIGHT_MARGIN:
1006 return Qright_margin;
1007
1008 case ON_SCROLL_BAR:
1009 /* Historically we are supposed to return nil in this case. */
1010 return Qnil;
1011
1012 default:
1013 abort ();
1014 }
1015 }
1016
1017
1018 /* Callback for foreach_window, used in window_from_coordinates.
1019 Check if window W contains coordinates specified by USER_DATA which
1020 is actually a pointer to a struct check_window_data CW.
1021
1022 Check if window W contains coordinates *CW->x and *CW->y. If it
1023 does, return W in *CW->window, as Lisp_Object, and return in
1024 *CW->part the part of the window under coordinates *X,*Y. Return
1025 zero from this function to stop iterating over windows. */
1026
1027 struct check_window_data
1028 {
1029 Lisp_Object *window;
1030 int *x, *y;
1031 enum window_part *part;
1032 };
1033
1034 static int
1035 check_window_containing (w, user_data)
1036 struct window *w;
1037 void *user_data;
1038 {
1039 struct check_window_data *cw = (struct check_window_data *) user_data;
1040 enum window_part found;
1041 int continue_p = 1;
1042
1043 found = coordinates_in_window (w, cw->x, cw->y);
1044 if (found != ON_NOTHING)
1045 {
1046 *cw->part = found;
1047 XSETWINDOW (*cw->window, w);
1048 continue_p = 0;
1049 }
1050
1051 return continue_p;
1052 }
1053
1054
1055 /* Find the window containing frame-relative pixel position X/Y and
1056 return it as a Lisp_Object.
1057
1058 If X, Y is on one of the window's special `window_part' elements,
1059 set *PART to the id of that element, and return X and Y converted
1060 to window relative coordinates in WX and WY.
1061
1062 If there is no window under X, Y return nil and leave *PART
1063 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1064
1065 This function was previously implemented with a loop cycling over
1066 windows with Fnext_window, and starting with the frame's selected
1067 window. It turned out that this doesn't work with an
1068 implementation of next_window using Vwindow_list, because
1069 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1070 tree of F when this function is called asynchronously from
1071 note_mouse_highlight. The original loop didn't terminate in this
1072 case. */
1073
1074 Lisp_Object
1075 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1076 struct frame *f;
1077 int x, y;
1078 enum window_part *part;
1079 int *wx, *wy;
1080 int tool_bar_p;
1081 {
1082 Lisp_Object window;
1083 struct check_window_data cw;
1084 enum window_part dummy;
1085
1086 if (part == 0)
1087 part = &dummy;
1088
1089 window = Qnil;
1090 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1091 foreach_window (f, check_window_containing, &cw);
1092
1093 /* If not found above, see if it's in the tool bar window, if a tool
1094 bar exists. */
1095 if (NILP (window)
1096 && tool_bar_p
1097 && WINDOWP (f->tool_bar_window)
1098 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1099 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1100 != ON_NOTHING))
1101 {
1102 *part = ON_TEXT;
1103 window = f->tool_bar_window;
1104 }
1105
1106 if (wx) *wx = x;
1107 if (wy) *wy = y;
1108
1109 return window;
1110 }
1111
1112 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1113 doc: /* Return window containing coordinates X and Y on FRAME.
1114 If omitted, FRAME defaults to the currently selected frame.
1115 The top left corner of the frame is considered to be row 0,
1116 column 0. */)
1117 (x, y, frame)
1118 Lisp_Object x, y, frame;
1119 {
1120 struct frame *f;
1121
1122 if (NILP (frame))
1123 frame = selected_frame;
1124 CHECK_LIVE_FRAME (frame);
1125 f = XFRAME (frame);
1126
1127 /* Check that arguments are integers or floats. */
1128 CHECK_NUMBER_OR_FLOAT (x);
1129 CHECK_NUMBER_OR_FLOAT (y);
1130
1131 return window_from_coordinates (f,
1132 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1133 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1134 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1135 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1136 0, 0, 0, 0);
1137 }
1138
1139 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1140 doc: /* Return current value of point in WINDOW.
1141 WINDOW defaults to the selected window.
1142
1143 For a nonselected window, this is the value point would have
1144 if that window were selected.
1145
1146 Note that, when WINDOW is the selected window and its buffer
1147 is also currently selected, the value returned is the same as (point).
1148 It would be more strictly correct to return the `top-level' value
1149 of point, outside of any save-excursion forms.
1150 But that is hard to define. */)
1151 (window)
1152 Lisp_Object window;
1153 {
1154 register struct window *w = decode_window (window);
1155
1156 if (w == XWINDOW (selected_window)
1157 && current_buffer == XBUFFER (w->buffer))
1158 return Fpoint ();
1159 return Fmarker_position (w->pointm);
1160 }
1161
1162 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1163 doc: /* Return position at which display currently starts in WINDOW.
1164 WINDOW defaults to the selected window.
1165 This is updated by redisplay or by calling `set-window-start'. */)
1166 (window)
1167 Lisp_Object window;
1168 {
1169 return Fmarker_position (decode_window (window)->start);
1170 }
1171
1172 /* This is text temporarily removed from the doc string below.
1173
1174 This function returns nil if the position is not currently known.
1175 That happens when redisplay is preempted and doesn't finish.
1176 If in that case you want to compute where the end of the window would
1177 have been if redisplay had finished, do this:
1178 (save-excursion
1179 (goto-char (window-start window))
1180 (vertical-motion (1- (window-height window)) window)
1181 (point))") */
1182
1183 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1184 doc: /* Return position at which display currently ends in WINDOW.
1185 WINDOW defaults to the selected window.
1186 This is updated by redisplay, when it runs to completion.
1187 Simply changing the buffer text or setting `window-start'
1188 does not update this value.
1189 Return nil if there is no recorded value. \(This can happen if the
1190 last redisplay of WINDOW was preempted, and did not finish.)
1191 If UPDATE is non-nil, compute the up-to-date position
1192 if it isn't already recorded. */)
1193 (window, update)
1194 Lisp_Object window, update;
1195 {
1196 Lisp_Object value;
1197 struct window *w = decode_window (window);
1198 Lisp_Object buf;
1199 struct buffer *b;
1200
1201 buf = w->buffer;
1202 CHECK_BUFFER (buf);
1203 b = XBUFFER (buf);
1204
1205 #if 0 /* This change broke some things. We should make it later. */
1206 /* If we don't know the end position, return nil.
1207 The user can compute it with vertical-motion if he wants to.
1208 It would be nicer to do it automatically,
1209 but that's so slow that it would probably bother people. */
1210 if (NILP (w->window_end_valid))
1211 return Qnil;
1212 #endif
1213
1214 if (! NILP (update)
1215 && ! (! NILP (w->window_end_valid)
1216 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1217 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1218 && !noninteractive)
1219 {
1220 struct text_pos startp;
1221 struct it it;
1222 struct buffer *old_buffer = NULL;
1223
1224 /* Cannot use Fvertical_motion because that function doesn't
1225 cope with variable-height lines. */
1226 if (b != current_buffer)
1227 {
1228 old_buffer = current_buffer;
1229 set_buffer_internal (b);
1230 }
1231
1232 /* In case W->start is out of the range, use something
1233 reasonable. This situation occurred when loading a file with
1234 `-l' containing a call to `rmail' with subsequent other
1235 commands. At the end, W->start happened to be BEG, while
1236 rmail had already narrowed the buffer. */
1237 if (XMARKER (w->start)->charpos < BEGV)
1238 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1239 else if (XMARKER (w->start)->charpos > ZV)
1240 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1241 else
1242 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1243
1244 start_display (&it, w, startp);
1245 move_it_vertically (&it, window_box_height (w));
1246 if (it.current_y < it.last_visible_y)
1247 move_it_past_eol (&it);
1248 value = make_number (IT_CHARPOS (it));
1249
1250 if (old_buffer)
1251 set_buffer_internal (old_buffer);
1252 }
1253 else
1254 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1255
1256 return value;
1257 }
1258
1259 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1260 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1261 Return POS. */)
1262 (window, pos)
1263 Lisp_Object window, pos;
1264 {
1265 register struct window *w = decode_window (window);
1266
1267 CHECK_NUMBER_COERCE_MARKER (pos);
1268 if (w == XWINDOW (selected_window)
1269 && XBUFFER (w->buffer) == current_buffer)
1270 Fgoto_char (pos);
1271 else
1272 set_marker_restricted (w->pointm, pos, w->buffer);
1273
1274 /* We have to make sure that redisplay updates the window to show
1275 the new value of point. */
1276 if (!EQ (window, selected_window))
1277 ++windows_or_buffers_changed;
1278
1279 return pos;
1280 }
1281
1282 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1283 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1284 Return POS.
1285 Optional third arg NOFORCE non-nil inhibits next redisplay
1286 from overriding motion of point in order to display at this exact start. */)
1287 (window, pos, noforce)
1288 Lisp_Object window, pos, noforce;
1289 {
1290 register struct window *w = decode_window (window);
1291
1292 CHECK_NUMBER_COERCE_MARKER (pos);
1293 set_marker_restricted (w->start, pos, w->buffer);
1294 /* this is not right, but much easier than doing what is right. */
1295 w->start_at_line_beg = Qnil;
1296 if (NILP (noforce))
1297 w->force_start = Qt;
1298 w->update_mode_line = Qt;
1299 XSETFASTINT (w->last_modified, 0);
1300 XSETFASTINT (w->last_overlay_modified, 0);
1301 if (!EQ (window, selected_window))
1302 windows_or_buffers_changed++;
1303
1304 return pos;
1305 }
1306
1307 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1308 1, 1, 0,
1309 doc: /* Return WINDOW's dedicated object, usually t or nil.
1310 See also `set-window-dedicated-p'. */)
1311 (window)
1312 Lisp_Object window;
1313 {
1314 return decode_window (window)->dedicated;
1315 }
1316
1317 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1318 Sset_window_dedicated_p, 2, 2, 0,
1319 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1320 If it is dedicated, Emacs will not automatically change
1321 which buffer appears in it.
1322 The second argument is the new value for the dedication flag;
1323 non-nil means yes. */)
1324 (window, arg)
1325 Lisp_Object window, arg;
1326 {
1327 register struct window *w = decode_window (window);
1328
1329 w->dedicated = arg;
1330
1331 return w->dedicated;
1332 }
1333
1334 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1335 0, 1, 0,
1336 doc: /* Return the parameters-alist of window WINDOW.
1337 It is a list of elements of the form (PARAMETER . VALUE).
1338 If WINDOW is omitted, return information on the currently selected window. */)
1339 (window)
1340 Lisp_Object window;
1341 {
1342 return Fcopy_alist (decode_window (window)->window_parameters);
1343 }
1344
1345 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1346 2, 2, 0,
1347 doc: /* Return WINDOW's value for parameter PARAMETER.
1348 If WINDOW is nil, describe the currently selected window. */)
1349 (window, parameter)
1350 Lisp_Object window, parameter;
1351 {
1352 Lisp_Object result;
1353
1354 result = Fassq (parameter, decode_window (window)->window_parameters);
1355 return CDR_SAFE (result);
1356 }
1357
1358
1359 DEFUN ("set-window-parameter", Fset_window_parameter,
1360 Sset_window_parameter, 3, 3, 0,
1361 doc: /* Set window parameter PARAMETER to VALUE on WINDOW.
1362 If WINDOW is nil, use the currently selected window.
1363 Return VALUE. */)
1364 (window, parameter, value)
1365 Lisp_Object window, parameter, value;
1366 {
1367 register struct window *w = decode_window (window);
1368 Lisp_Object old_alist_elt;
1369
1370 old_alist_elt = Fassq (parameter, w->window_parameters);
1371 if (EQ (old_alist_elt, Qnil))
1372 w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
1373 else
1374 Fsetcdr (old_alist_elt, value);
1375 return value;
1376 }
1377
1378
1379 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1380 0, 1, 0,
1381 doc: /* Return the display-table that WINDOW is using.
1382 WINDOW defaults to the selected window. */)
1383 (window)
1384 Lisp_Object window;
1385 {
1386 return decode_window (window)->display_table;
1387 }
1388
1389 /* Get the display table for use on window W. This is either W's
1390 display table or W's buffer's display table. Ignore the specified
1391 tables if they are not valid; if no valid table is specified,
1392 return 0. */
1393
1394 struct Lisp_Char_Table *
1395 window_display_table (w)
1396 struct window *w;
1397 {
1398 struct Lisp_Char_Table *dp = NULL;
1399
1400 if (DISP_TABLE_P (w->display_table))
1401 dp = XCHAR_TABLE (w->display_table);
1402 else if (BUFFERP (w->buffer))
1403 {
1404 struct buffer *b = XBUFFER (w->buffer);
1405
1406 if (DISP_TABLE_P (b->display_table))
1407 dp = XCHAR_TABLE (b->display_table);
1408 else if (DISP_TABLE_P (Vstandard_display_table))
1409 dp = XCHAR_TABLE (Vstandard_display_table);
1410 }
1411
1412 return dp;
1413 }
1414
1415 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1416 doc: /* Set WINDOW's display-table to TABLE. */)
1417 (window, table)
1418 register Lisp_Object window, table;
1419 {
1420 register struct window *w;
1421
1422 w = decode_window (window);
1423 w->display_table = table;
1424 return table;
1425 }
1426 \f
1427 /* Record info on buffer window w is displaying
1428 when it is about to cease to display that buffer. */
1429 static void
1430 unshow_buffer (w)
1431 register struct window *w;
1432 {
1433 Lisp_Object buf;
1434 struct buffer *b;
1435
1436 buf = w->buffer;
1437 b = XBUFFER (buf);
1438 if (b != XMARKER (w->pointm)->buffer)
1439 abort ();
1440
1441 #if 0
1442 if (w == XWINDOW (selected_window)
1443 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1444 /* Do this except when the selected window's buffer
1445 is being removed from some other window. */
1446 #endif
1447 /* last_window_start records the start position that this buffer
1448 had in the last window to be disconnected from it.
1449 Now that this statement is unconditional,
1450 it is possible for the buffer to be displayed in the
1451 selected window, while last_window_start reflects another
1452 window which was recently showing the same buffer.
1453 Some people might say that might be a good thing. Let's see. */
1454 b->last_window_start = marker_position (w->start);
1455
1456 /* Point in the selected window's buffer
1457 is actually stored in that buffer, and the window's pointm isn't used.
1458 So don't clobber point in that buffer. */
1459 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1460 /* This line helps to fix Horsley's testbug.el bug. */
1461 && !(WINDOWP (b->last_selected_window)
1462 && w != XWINDOW (b->last_selected_window)
1463 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1464 temp_set_point_both (b,
1465 clip_to_bounds (BUF_BEGV (b),
1466 XMARKER (w->pointm)->charpos,
1467 BUF_ZV (b)),
1468 clip_to_bounds (BUF_BEGV_BYTE (b),
1469 marker_byte_position (w->pointm),
1470 BUF_ZV_BYTE (b)));
1471
1472 if (WINDOWP (b->last_selected_window)
1473 && w == XWINDOW (b->last_selected_window))
1474 b->last_selected_window = Qnil;
1475 }
1476
1477 /* Put replacement into the window structure in place of old. */
1478 static void
1479 replace_window (old, replacement)
1480 Lisp_Object old, replacement;
1481 {
1482 register Lisp_Object tem;
1483 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1484
1485 /* If OLD is its frame's root_window, then replacement is the new
1486 root_window for that frame. */
1487
1488 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1489 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1490
1491 p->left_col = o->left_col;
1492 p->top_line = o->top_line;
1493 p->total_cols = o->total_cols;
1494 p->total_lines = o->total_lines;
1495 p->desired_matrix = p->current_matrix = 0;
1496 p->vscroll = 0;
1497 bzero (&p->cursor, sizeof (p->cursor));
1498 bzero (&p->last_cursor, sizeof (p->last_cursor));
1499 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1500 p->phys_cursor_type = -1;
1501 p->phys_cursor_width = -1;
1502 p->must_be_updated_p = 0;
1503 p->pseudo_window_p = 0;
1504 XSETFASTINT (p->window_end_vpos, 0);
1505 XSETFASTINT (p->window_end_pos, 0);
1506 p->window_end_valid = Qnil;
1507 p->frozen_window_start_p = 0;
1508 p->orig_top_line = p->orig_total_lines = Qnil;
1509
1510 p->next = tem = o->next;
1511 if (!NILP (tem))
1512 XWINDOW (tem)->prev = replacement;
1513
1514 p->prev = tem = o->prev;
1515 if (!NILP (tem))
1516 XWINDOW (tem)->next = replacement;
1517
1518 p->parent = tem = o->parent;
1519 if (!NILP (tem))
1520 {
1521 if (EQ (XWINDOW (tem)->vchild, old))
1522 XWINDOW (tem)->vchild = replacement;
1523 if (EQ (XWINDOW (tem)->hchild, old))
1524 XWINDOW (tem)->hchild = replacement;
1525 }
1526
1527 /*** Here, if replacement is a vertical combination
1528 and so is its new parent, we should make replacement's
1529 children be children of that parent instead. ***/
1530 }
1531
1532 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1533 doc: /* Remove WINDOW from the display. Default is selected window. */)
1534 (window)
1535 register Lisp_Object window;
1536 {
1537 struct frame *f;
1538 if (NILP (window))
1539 window = selected_window;
1540 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1541 delete_window (window);
1542
1543 run_window_configuration_change_hook (f);
1544
1545 return Qnil;
1546 }
1547
1548 void
1549 delete_window (window)
1550 register Lisp_Object window;
1551 {
1552 register Lisp_Object tem, parent, sib;
1553 register struct window *p;
1554 register struct window *par;
1555 struct frame *f;
1556
1557 /* Because this function is called by other C code on non-leaf
1558 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1559 so we can't decode_window here. */
1560 CHECK_WINDOW (window);
1561 p = XWINDOW (window);
1562
1563 /* It's a no-op to delete an already-deleted window. */
1564 if (NILP (p->buffer)
1565 && NILP (p->hchild)
1566 && NILP (p->vchild))
1567 return;
1568
1569 parent = p->parent;
1570 if (NILP (parent))
1571 error ("Attempt to delete minibuffer or sole ordinary window");
1572 par = XWINDOW (parent);
1573
1574 windows_or_buffers_changed++;
1575 Vwindow_list = Qnil;
1576 f = XFRAME (WINDOW_FRAME (p));
1577 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1578
1579 /* Are we trying to delete any frame's selected window? */
1580 {
1581 Lisp_Object swindow, pwindow;
1582
1583 /* See if the frame's selected window is either WINDOW
1584 or any subwindow of it, by finding all that window's parents
1585 and comparing each one with WINDOW. */
1586 swindow = FRAME_SELECTED_WINDOW (f);
1587
1588 while (1)
1589 {
1590 pwindow = swindow;
1591 while (!NILP (pwindow))
1592 {
1593 if (EQ (window, pwindow))
1594 break;
1595 pwindow = XWINDOW (pwindow)->parent;
1596 }
1597
1598 /* If the window being deleted is not a parent of SWINDOW,
1599 then SWINDOW is ok as the new selected window. */
1600 if (!EQ (window, pwindow))
1601 break;
1602 /* Otherwise, try another window for SWINDOW. */
1603 swindow = Fnext_window (swindow, Qlambda, Qnil);
1604
1605 /* If we get back to the frame's selected window,
1606 it means there was no acceptable alternative,
1607 so we cannot delete. */
1608 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1609 error ("Cannot delete window");
1610 }
1611
1612 /* If we need to change SWINDOW, do it. */
1613 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1614 {
1615 /* If we're about to delete the selected window on the
1616 selected frame, then we should use Fselect_window to select
1617 the new window. On the other hand, if we're about to
1618 delete the selected window on any other frame, we shouldn't do
1619 anything but set the frame's selected_window slot. */
1620 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1621 Fselect_window (swindow, Qnil);
1622 else
1623 FRAME_SELECTED_WINDOW (f) = swindow;
1624 }
1625 }
1626
1627 /* Now we know we can delete this one. */
1628 window_deletion_count++;
1629
1630 tem = p->buffer;
1631 /* tem is null for dummy parent windows
1632 (which have inferiors but not any contents themselves) */
1633 if (!NILP (tem))
1634 {
1635 unshow_buffer (p);
1636 unchain_marker (XMARKER (p->pointm));
1637 unchain_marker (XMARKER (p->start));
1638 }
1639
1640 /* Free window glyph matrices. It is sure that they are allocated
1641 again when ADJUST_GLYPHS is called. Block input so that expose
1642 events and other events that access glyph matrices are not
1643 processed while we are changing them. */
1644 BLOCK_INPUT;
1645 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1646
1647 tem = p->next;
1648 if (!NILP (tem))
1649 XWINDOW (tem)->prev = p->prev;
1650
1651 tem = p->prev;
1652 if (!NILP (tem))
1653 XWINDOW (tem)->next = p->next;
1654
1655 if (EQ (window, par->hchild))
1656 par->hchild = p->next;
1657 if (EQ (window, par->vchild))
1658 par->vchild = p->next;
1659
1660 /* Find one of our siblings to give our space to. */
1661 sib = p->prev;
1662 if (NILP (sib))
1663 {
1664 /* If p gives its space to its next sibling, that sibling needs
1665 to have its top/left side pulled back to where p's is.
1666 set_window_{height,width} will re-position the sibling's
1667 children. */
1668 sib = p->next;
1669 XWINDOW (sib)->top_line = p->top_line;
1670 XWINDOW (sib)->left_col = p->left_col;
1671 }
1672
1673 /* Stretch that sibling. */
1674 if (!NILP (par->vchild))
1675 set_window_height (sib,
1676 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1677 1);
1678 if (!NILP (par->hchild))
1679 set_window_width (sib,
1680 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1681 1);
1682
1683 /* If parent now has only one child,
1684 put the child into the parent's place. */
1685 tem = par->hchild;
1686 if (NILP (tem))
1687 tem = par->vchild;
1688 if (NILP (XWINDOW (tem)->next)) {
1689 replace_window (parent, tem);
1690 par = XWINDOW (tem);
1691 }
1692
1693 /* Since we may be deleting combination windows, we must make sure that
1694 not only p but all its children have been marked as deleted. */
1695 if (! NILP (p->hchild))
1696 delete_all_subwindows (XWINDOW (p->hchild));
1697 else if (! NILP (p->vchild))
1698 delete_all_subwindows (XWINDOW (p->vchild));
1699
1700 /* Mark this window as deleted. */
1701 p->buffer = p->hchild = p->vchild = Qnil;
1702
1703 if (! NILP (par->parent))
1704 par = XWINDOW (par->parent);
1705
1706 /* Check if we have a v/hchild with a v/hchild. In that case remove
1707 one of them. */
1708
1709 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1710 {
1711 p = XWINDOW (par->vchild);
1712 par->vchild = p->vchild;
1713 tem = p->vchild;
1714 }
1715 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1716 {
1717 p = XWINDOW (par->hchild);
1718 par->hchild = p->hchild;
1719 tem = p->hchild;
1720 }
1721 else
1722 p = 0;
1723
1724 if (p)
1725 {
1726 while (! NILP (tem)) {
1727 XWINDOW (tem)->parent = p->parent;
1728 if (NILP (XWINDOW (tem)->next))
1729 break;
1730 tem = XWINDOW (tem)->next;
1731 }
1732 if (! NILP (tem)) {
1733 /* The next of the v/hchild we are removing is now the next of the
1734 last child for the v/hchild:
1735 Before v/hchild -> v/hchild -> next1 -> next2
1736 |
1737 -> next3
1738 After: v/hchild -> next1 -> next2 -> next3
1739 */
1740 XWINDOW (tem)->next = p->next;
1741 if (! NILP (p->next))
1742 XWINDOW (p->next)->prev = tem;
1743 }
1744 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1745 }
1746
1747
1748 /* Adjust glyph matrices. */
1749 adjust_glyphs (f);
1750 UNBLOCK_INPUT;
1751 }
1752
1753
1754 \f
1755 /***********************************************************************
1756 Window List
1757 ***********************************************************************/
1758
1759 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1760 pointer. This is a callback function for foreach_window, used in
1761 function window_list. */
1762
1763 static int
1764 add_window_to_list (w, user_data)
1765 struct window *w;
1766 void *user_data;
1767 {
1768 Lisp_Object *list = (Lisp_Object *) user_data;
1769 Lisp_Object window;
1770 XSETWINDOW (window, w);
1771 *list = Fcons (window, *list);
1772 return 1;
1773 }
1774
1775
1776 /* Return a list of all windows, for use by next_window. If
1777 Vwindow_list is a list, return that list. Otherwise, build a new
1778 list, cache it in Vwindow_list, and return that. */
1779
1780 static Lisp_Object
1781 window_list ()
1782 {
1783 if (!CONSP (Vwindow_list))
1784 {
1785 Lisp_Object tail;
1786
1787 Vwindow_list = Qnil;
1788 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1789 {
1790 Lisp_Object args[2];
1791
1792 /* We are visiting windows in canonical order, and add
1793 new windows at the front of args[1], which means we
1794 have to reverse this list at the end. */
1795 args[1] = Qnil;
1796 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1797 args[0] = Vwindow_list;
1798 args[1] = Fnreverse (args[1]);
1799 Vwindow_list = Fnconc (2, args);
1800 }
1801 }
1802
1803 return Vwindow_list;
1804 }
1805
1806
1807 /* Value is non-zero if WINDOW satisfies the constraints given by
1808 OWINDOW, MINIBUF and ALL_FRAMES.
1809
1810 MINIBUF t means WINDOW may be minibuffer windows.
1811 `lambda' means WINDOW may not be a minibuffer window.
1812 a window means a specific minibuffer window
1813
1814 ALL_FRAMES t means search all frames,
1815 nil means search just current frame,
1816 `visible' means search just visible frames,
1817 0 means search visible and iconified frames,
1818 a window means search the frame that window belongs to,
1819 a frame means consider windows on that frame, only. */
1820
1821 static int
1822 candidate_window_p (window, owindow, minibuf, all_frames)
1823 Lisp_Object window, owindow, minibuf, all_frames;
1824 {
1825 struct window *w = XWINDOW (window);
1826 struct frame *f = XFRAME (w->frame);
1827 int candidate_p = 1;
1828
1829 if (!BUFFERP (w->buffer))
1830 candidate_p = 0;
1831 else if (MINI_WINDOW_P (w)
1832 && (EQ (minibuf, Qlambda)
1833 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1834 {
1835 /* If MINIBUF is `lambda' don't consider any mini-windows.
1836 If it is a window, consider only that one. */
1837 candidate_p = 0;
1838 }
1839 else if (EQ (all_frames, Qt))
1840 candidate_p = 1;
1841 else if (NILP (all_frames))
1842 {
1843 xassert (WINDOWP (owindow));
1844 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1845 }
1846 else if (EQ (all_frames, Qvisible))
1847 {
1848 FRAME_SAMPLE_VISIBILITY (f);
1849 candidate_p = FRAME_VISIBLE_P (f)
1850 && (FRAME_TERMINAL (XFRAME (w->frame))
1851 == FRAME_TERMINAL (XFRAME (selected_frame)));
1852
1853 }
1854 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1855 {
1856 FRAME_SAMPLE_VISIBILITY (f);
1857 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
1858 #ifdef HAVE_X_WINDOWS
1859 /* Yuck!! If we've just created the frame and the
1860 window-manager requested the user to place it
1861 manually, the window may still not be considered
1862 `visible'. I'd argue it should be at least
1863 something like `iconified', but don't know how to do
1864 that yet. --Stef */
1865 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
1866 && !f->output_data.x->has_been_visible)
1867 #endif
1868 )
1869 && (FRAME_TERMINAL (XFRAME (w->frame))
1870 == FRAME_TERMINAL (XFRAME (selected_frame)));
1871 }
1872 else if (WINDOWP (all_frames))
1873 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1874 || EQ (XWINDOW (all_frames)->frame, w->frame)
1875 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1876 else if (FRAMEP (all_frames))
1877 candidate_p = EQ (all_frames, w->frame);
1878
1879 return candidate_p;
1880 }
1881
1882
1883 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1884 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1885 ALL_FRAMES. */
1886
1887 static void
1888 decode_next_window_args (window, minibuf, all_frames)
1889 Lisp_Object *window, *minibuf, *all_frames;
1890 {
1891 if (NILP (*window))
1892 *window = selected_window;
1893 else
1894 CHECK_LIVE_WINDOW (*window);
1895
1896 /* MINIBUF nil may or may not include minibuffers. Decide if it
1897 does. */
1898 if (NILP (*minibuf))
1899 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1900 else if (!EQ (*minibuf, Qt))
1901 *minibuf = Qlambda;
1902
1903 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1904 => count none of them, or a specific minibuffer window (the
1905 active one) to count. */
1906
1907 /* ALL_FRAMES nil doesn't specify which frames to include. */
1908 if (NILP (*all_frames))
1909 *all_frames = (!EQ (*minibuf, Qlambda)
1910 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1911 : Qnil);
1912 else if (EQ (*all_frames, Qvisible))
1913 ;
1914 else if (EQ (*all_frames, make_number (0)))
1915 ;
1916 else if (FRAMEP (*all_frames))
1917 ;
1918 else if (!EQ (*all_frames, Qt))
1919 *all_frames = Qnil;
1920
1921 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1922 search just current frame, `visible' meaning search just visible
1923 frames, 0 meaning search visible and iconified frames, or a
1924 window, meaning search the frame that window belongs to, or a
1925 frame, meaning consider windows on that frame, only. */
1926 }
1927
1928
1929 /* Return the next or previous window of WINDOW in canonical ordering
1930 of windows. NEXT_P non-zero means return the next window. See the
1931 documentation string of next-window for the meaning of MINIBUF and
1932 ALL_FRAMES. */
1933
1934 static Lisp_Object
1935 next_window (window, minibuf, all_frames, next_p)
1936 Lisp_Object window, minibuf, all_frames;
1937 int next_p;
1938 {
1939 decode_next_window_args (&window, &minibuf, &all_frames);
1940
1941 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1942 return the first window on the frame. */
1943 if (FRAMEP (all_frames)
1944 && !EQ (all_frames, XWINDOW (window)->frame))
1945 return Fframe_first_window (all_frames);
1946
1947 if (next_p)
1948 {
1949 Lisp_Object list;
1950
1951 /* Find WINDOW in the list of all windows. */
1952 list = Fmemq (window, window_list ());
1953
1954 /* Scan forward from WINDOW to the end of the window list. */
1955 if (CONSP (list))
1956 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1957 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1958 break;
1959
1960 /* Scan from the start of the window list up to WINDOW. */
1961 if (!CONSP (list))
1962 for (list = Vwindow_list;
1963 CONSP (list) && !EQ (XCAR (list), window);
1964 list = XCDR (list))
1965 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1966 break;
1967
1968 if (CONSP (list))
1969 window = XCAR (list);
1970 }
1971 else
1972 {
1973 Lisp_Object candidate, list;
1974
1975 /* Scan through the list of windows for candidates. If there are
1976 candidate windows in front of WINDOW, the last one of these
1977 is the one we want. If there are candidates following WINDOW
1978 in the list, again the last one of these is the one we want. */
1979 candidate = Qnil;
1980 for (list = window_list (); CONSP (list); list = XCDR (list))
1981 {
1982 if (EQ (XCAR (list), window))
1983 {
1984 if (WINDOWP (candidate))
1985 break;
1986 }
1987 else if (candidate_window_p (XCAR (list), window, minibuf,
1988 all_frames))
1989 candidate = XCAR (list);
1990 }
1991
1992 if (WINDOWP (candidate))
1993 window = candidate;
1994 }
1995
1996 return window;
1997 }
1998
1999
2000 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2001 doc: /* Return next window after WINDOW in canonical ordering of windows.
2002 If omitted, WINDOW defaults to the selected window.
2003
2004 Optional second arg MINIBUF t means count the minibuffer window even
2005 if not active. MINIBUF nil or omitted means count the minibuffer iff
2006 it is active. MINIBUF neither t nor nil means not to count the
2007 minibuffer even if it is active.
2008
2009 Several frames may share a single minibuffer; if the minibuffer
2010 counts, all windows on all frames that share that minibuffer count
2011 too. Therefore, `next-window' can be used to iterate through the
2012 set of windows even when the minibuffer is on another frame. If the
2013 minibuffer does not count, only windows from WINDOW's frame count.
2014
2015 Optional third arg ALL-FRAMES t means include windows on all frames.
2016 ALL-FRAMES nil or omitted means cycle within the frames as specified
2017 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2018 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2019 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2020 Anything else means restrict to WINDOW's frame.
2021
2022 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2023 `next-window' to iterate through the entire cycle of acceptable
2024 windows, eventually ending up back at the window you started with.
2025 `previous-window' traverses the same cycle, in the reverse order. */)
2026 (window, minibuf, all_frames)
2027 Lisp_Object window, minibuf, all_frames;
2028 {
2029 return next_window (window, minibuf, all_frames, 1);
2030 }
2031
2032
2033 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2034 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
2035 If omitted, WINDOW defaults to the selected window.
2036
2037 Optional second arg MINIBUF t means count the minibuffer window even
2038 if not active. MINIBUF nil or omitted means count the minibuffer iff
2039 it is active. MINIBUF neither t nor nil means not to count the
2040 minibuffer even if it is active.
2041
2042 Several frames may share a single minibuffer; if the minibuffer
2043 counts, all windows on all frames that share that minibuffer count
2044 too. Therefore, `previous-window' can be used to iterate through
2045 the set of windows even when the minibuffer is on another frame. If
2046 the minibuffer does not count, only windows from WINDOW's frame count
2047
2048 Optional third arg ALL-FRAMES t means include windows on all frames.
2049 ALL-FRAMES nil or omitted means cycle within the frames as specified
2050 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2051 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2052 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2053 Anything else means restrict to WINDOW's frame.
2054
2055 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2056 `previous-window' to iterate through the entire cycle of acceptable
2057 windows, eventually ending up back at the window you started with.
2058 `next-window' traverses the same cycle, in the reverse order. */)
2059 (window, minibuf, all_frames)
2060 Lisp_Object window, minibuf, all_frames;
2061 {
2062 return next_window (window, minibuf, all_frames, 0);
2063 }
2064
2065
2066 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2067 doc: /* Select the ARG'th different window on this frame.
2068 All windows on current frame are arranged in a cyclic order.
2069 This command selects the window ARG steps away in that order.
2070 A negative ARG moves in the opposite order. The optional second
2071 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
2072 (arg, all_frames)
2073 Lisp_Object arg, all_frames;
2074 {
2075 Lisp_Object window;
2076 int i;
2077
2078 CHECK_NUMBER (arg);
2079 window = selected_window;
2080
2081 for (i = XINT (arg); i > 0; --i)
2082 window = Fnext_window (window, Qnil, all_frames);
2083 for (; i < 0; ++i)
2084 window = Fprevious_window (window, Qnil, all_frames);
2085
2086 Fselect_window (window, Qnil);
2087 return Qnil;
2088 }
2089
2090
2091 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2092 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2093 FRAME nil or omitted means use the selected frame.
2094 WINDOW nil or omitted means use the selected window.
2095 MINIBUF t means include the minibuffer window, even if it isn't active.
2096 MINIBUF nil or omitted means include the minibuffer window only
2097 if it's active.
2098 MINIBUF neither nil nor t means never include the minibuffer window. */)
2099 (frame, minibuf, window)
2100 Lisp_Object frame, minibuf, window;
2101 {
2102 if (NILP (window))
2103 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2104 CHECK_WINDOW (window);
2105 if (NILP (frame))
2106 frame = selected_frame;
2107
2108 if (!EQ (frame, XWINDOW (window)->frame))
2109 error ("Window is on a different frame");
2110
2111 return window_list_1 (window, minibuf, frame);
2112 }
2113
2114
2115 /* Return a list of windows in canonical ordering. Arguments are like
2116 for `next-window'. */
2117
2118 static Lisp_Object
2119 window_list_1 (window, minibuf, all_frames)
2120 Lisp_Object window, minibuf, all_frames;
2121 {
2122 Lisp_Object tail, list, rest;
2123
2124 decode_next_window_args (&window, &minibuf, &all_frames);
2125 list = Qnil;
2126
2127 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2128 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2129 list = Fcons (XCAR (tail), list);
2130
2131 /* Rotate the list to start with WINDOW. */
2132 list = Fnreverse (list);
2133 rest = Fmemq (window, list);
2134 if (!NILP (rest) && !EQ (rest, list))
2135 {
2136 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2137 ;
2138 XSETCDR (tail, Qnil);
2139 list = nconc2 (rest, list);
2140 }
2141 return list;
2142 }
2143
2144
2145 \f
2146 /* Look at all windows, performing an operation specified by TYPE
2147 with argument OBJ.
2148 If FRAMES is Qt, look at all frames;
2149 Qnil, look at just the selected frame;
2150 Qvisible, look at visible frames;
2151 a frame, just look at windows on that frame.
2152 If MINI is non-zero, perform the operation on minibuffer windows too. */
2153
2154 enum window_loop
2155 {
2156 WINDOW_LOOP_UNUSED,
2157 GET_BUFFER_WINDOW, /* Arg is buffer */
2158 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2159 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2160 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2161 GET_LARGEST_WINDOW,
2162 UNSHOW_BUFFER, /* Arg is buffer */
2163 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2164 CHECK_ALL_WINDOWS
2165 };
2166
2167 static Lisp_Object
2168 window_loop (type, obj, mini, frames)
2169 enum window_loop type;
2170 Lisp_Object obj, frames;
2171 int mini;
2172 {
2173 Lisp_Object window, windows, best_window, frame_arg;
2174 struct frame *f;
2175 struct gcpro gcpro1;
2176
2177 /* If we're only looping through windows on a particular frame,
2178 frame points to that frame. If we're looping through windows
2179 on all frames, frame is 0. */
2180 if (FRAMEP (frames))
2181 f = XFRAME (frames);
2182 else if (NILP (frames))
2183 f = SELECTED_FRAME ();
2184 else
2185 f = NULL;
2186
2187 if (f)
2188 frame_arg = Qlambda;
2189 else if (EQ (frames, make_number (0)))
2190 frame_arg = frames;
2191 else if (EQ (frames, Qvisible))
2192 frame_arg = frames;
2193 else
2194 frame_arg = Qt;
2195
2196 /* frame_arg is Qlambda to stick to one frame,
2197 Qvisible to consider all visible frames,
2198 or Qt otherwise. */
2199
2200 /* Pick a window to start with. */
2201 if (WINDOWP (obj))
2202 window = obj;
2203 else if (f)
2204 window = FRAME_SELECTED_WINDOW (f);
2205 else
2206 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2207
2208 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2209 GCPRO1 (windows);
2210 best_window = Qnil;
2211
2212 for (; CONSP (windows); windows = XCDR (windows))
2213 {
2214 struct window *w;
2215
2216 window = XCAR (windows);
2217 w = XWINDOW (window);
2218
2219 /* Note that we do not pay attention here to whether the frame
2220 is visible, since Fwindow_list skips non-visible frames if
2221 that is desired, under the control of frame_arg. */
2222 if (!MINI_WINDOW_P (w)
2223 /* For UNSHOW_BUFFER, we must always consider all windows. */
2224 || type == UNSHOW_BUFFER
2225 || (mini && minibuf_level > 0))
2226 switch (type)
2227 {
2228 case GET_BUFFER_WINDOW:
2229 if (EQ (w->buffer, obj)
2230 /* Don't find any minibuffer window
2231 except the one that is currently in use. */
2232 && (MINI_WINDOW_P (w)
2233 ? EQ (window, minibuf_window)
2234 : 1))
2235 {
2236 if (NILP (best_window))
2237 best_window = window;
2238 else if (EQ (window, selected_window))
2239 /* Prefer to return selected-window. */
2240 RETURN_UNGCPRO (window);
2241 else if (EQ (Fwindow_frame (window), selected_frame))
2242 /* Prefer windows on the current frame. */
2243 best_window = window;
2244 }
2245 break;
2246
2247 case GET_LRU_WINDOW:
2248 /* `obj' is an integer encoding a bitvector.
2249 `obj & 1' means consider only full-width windows.
2250 `obj & 2' means consider also dedicated windows. */
2251 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2252 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2253 /* Minibuffer windows are always ignored. */
2254 || MINI_WINDOW_P (w))
2255 break;
2256 if (NILP (best_window)
2257 || (XFASTINT (XWINDOW (best_window)->use_time)
2258 > XFASTINT (w->use_time)))
2259 best_window = window;
2260 break;
2261
2262 case DELETE_OTHER_WINDOWS:
2263 if (!EQ (window, obj))
2264 Fdelete_window (window);
2265 break;
2266
2267 case DELETE_BUFFER_WINDOWS:
2268 if (EQ (w->buffer, obj))
2269 {
2270 struct frame *f = XFRAME (WINDOW_FRAME (w));
2271
2272 /* If this window is dedicated, and in a frame of its own,
2273 kill the frame. */
2274 if (EQ (window, FRAME_ROOT_WINDOW (f))
2275 && !NILP (w->dedicated)
2276 && other_visible_frames (f))
2277 {
2278 /* Skip the other windows on this frame.
2279 There might be one, the minibuffer! */
2280 while (CONSP (XCDR (windows))
2281 && EQ (XWINDOW (XCAR (windows))->frame,
2282 XWINDOW (XCAR (XCDR (windows)))->frame))
2283 windows = XCDR (windows);
2284
2285 /* Now we can safely delete the frame. */
2286 Fdelete_frame (w->frame, Qnil);
2287 }
2288 else if (NILP (w->parent))
2289 {
2290 /* If we're deleting the buffer displayed in the
2291 only window on the frame, find a new buffer to
2292 display there. */
2293 Lisp_Object buffer;
2294 buffer = Fother_buffer (obj, Qnil, w->frame);
2295 Fset_window_buffer (window, buffer, Qnil);
2296 if (EQ (window, selected_window))
2297 Fset_buffer (w->buffer);
2298 }
2299 else
2300 Fdelete_window (window);
2301 }
2302 break;
2303
2304 case GET_LARGEST_WINDOW:
2305 { /* nil `obj' means to ignore dedicated windows. */
2306 /* Ignore dedicated windows and minibuffers. */
2307 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2308 break;
2309
2310 if (NILP (best_window))
2311 best_window = window;
2312 else
2313 {
2314 struct window *b = XWINDOW (best_window);
2315 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2316 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2317 best_window = window;
2318 }
2319 }
2320 break;
2321
2322 case UNSHOW_BUFFER:
2323 if (EQ (w->buffer, obj))
2324 {
2325 Lisp_Object buffer;
2326 struct frame *f = XFRAME (w->frame);
2327
2328 /* Find another buffer to show in this window. */
2329 buffer = Fother_buffer (obj, Qnil, w->frame);
2330
2331 /* If this window is dedicated, and in a frame of its own,
2332 kill the frame. */
2333 if (EQ (window, FRAME_ROOT_WINDOW (f))
2334 && !NILP (w->dedicated)
2335 && other_visible_frames (f))
2336 {
2337 /* Skip the other windows on this frame.
2338 There might be one, the minibuffer! */
2339 while (CONSP (XCDR (windows))
2340 && EQ (XWINDOW (XCAR (windows))->frame,
2341 XWINDOW (XCAR (XCDR (windows)))->frame))
2342 windows = XCDR (windows);
2343
2344 /* Now we can safely delete the frame. */
2345 Fdelete_frame (w->frame, Qnil);
2346 }
2347 else if (!NILP (w->dedicated) && !NILP (w->parent))
2348 {
2349 Lisp_Object window;
2350 XSETWINDOW (window, w);
2351 /* If this window is dedicated and not the only window
2352 in its frame, then kill it. */
2353 Fdelete_window (window);
2354 }
2355 else
2356 {
2357 /* Otherwise show a different buffer in the window. */
2358 w->dedicated = Qnil;
2359 Fset_window_buffer (window, buffer, Qnil);
2360 if (EQ (window, selected_window))
2361 Fset_buffer (w->buffer);
2362 }
2363 }
2364 break;
2365
2366 case REDISPLAY_BUFFER_WINDOWS:
2367 if (EQ (w->buffer, obj))
2368 {
2369 mark_window_display_accurate (window, 0);
2370 w->update_mode_line = Qt;
2371 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2372 ++update_mode_lines;
2373 best_window = window;
2374 }
2375 break;
2376
2377 /* Check for a window that has a killed buffer. */
2378 case CHECK_ALL_WINDOWS:
2379 if (! NILP (w->buffer)
2380 && NILP (XBUFFER (w->buffer)->name))
2381 abort ();
2382 break;
2383
2384 case WINDOW_LOOP_UNUSED:
2385 break;
2386 }
2387 }
2388
2389 UNGCPRO;
2390 return best_window;
2391 }
2392
2393 /* Used for debugging. Abort if any window has a dead buffer. */
2394
2395 void
2396 check_all_windows ()
2397 {
2398 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2399 }
2400
2401 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2402 doc: /* Return the window least recently selected or used for display.
2403 \(LRU means Least Recently Used.)
2404
2405 Return a full-width window if possible.
2406 A minibuffer window is never a candidate.
2407 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2408 so if all windows are dedicated, the value is nil.
2409 If optional argument FRAME is `visible', search all visible frames.
2410 If FRAME is 0, search all visible and iconified frames.
2411 If FRAME is t, search all frames.
2412 If FRAME is nil, search only the selected frame.
2413 If FRAME is a frame, search only that frame. */)
2414 (frame, dedicated)
2415 Lisp_Object frame, dedicated;
2416 {
2417 register Lisp_Object w;
2418 /* First try for a window that is full-width */
2419 w = window_loop (GET_LRU_WINDOW,
2420 NILP (dedicated) ? make_number (1) : make_number (3),
2421 0, frame);
2422 if (!NILP (w) && !EQ (w, selected_window))
2423 return w;
2424 /* If none of them, try the rest */
2425 return window_loop (GET_LRU_WINDOW,
2426 NILP (dedicated) ? make_number (0) : make_number (2),
2427 0, frame);
2428 }
2429
2430 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2431 doc: /* Return the largest window in area.
2432 A minibuffer window is never a candidate.
2433 A dedicated window is never a candidate unless DEDICATED is non-nil,
2434 so if all windows are dedicated, the value is nil.
2435 If optional argument FRAME is `visible', search all visible frames.
2436 If FRAME is 0, search all visible and iconified frames.
2437 If FRAME is t, search all frames.
2438 If FRAME is nil, search only the selected frame.
2439 If FRAME is a frame, search only that frame. */)
2440 (frame, dedicated)
2441 Lisp_Object frame, dedicated;
2442 {
2443 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2444 frame);
2445 }
2446
2447 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2448 doc: /* Return a window currently displaying BUFFER, or nil if none.
2449 BUFFER can be a buffer or a buffer name.
2450 If optional argument FRAME is `visible', search all visible frames.
2451 If optional argument FRAME is 0, search all visible and iconified frames.
2452 If FRAME is t, search all frames.
2453 If FRAME is nil, search only the selected frame.
2454 If FRAME is a frame, search only that frame. */)
2455 (buffer, frame)
2456 Lisp_Object buffer, frame;
2457 {
2458 buffer = Fget_buffer (buffer);
2459 if (BUFFERP (buffer))
2460 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2461 else
2462 return Qnil;
2463 }
2464
2465 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2466 0, 1, "",
2467 doc: /* Make WINDOW (or the selected window) fill its frame.
2468 Only the frame WINDOW is on is affected.
2469 This function tries to reduce display jumps
2470 by keeping the text previously visible in WINDOW
2471 in the same place on the frame. Doing this depends on
2472 the value of (window-start WINDOW), so if calling this function
2473 in a program gives strange scrolling, make sure the window-start
2474 value is reasonable when this function is called. */)
2475 (window)
2476 Lisp_Object window;
2477 {
2478 struct window *w;
2479 int startpos;
2480 int top, new_top;
2481
2482 if (NILP (window))
2483 window = selected_window;
2484 else
2485 CHECK_LIVE_WINDOW (window);
2486 w = XWINDOW (window);
2487
2488 startpos = marker_position (w->start);
2489 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2490
2491 if (MINI_WINDOW_P (w) && top > 0)
2492 error ("Can't expand minibuffer to full frame");
2493
2494 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2495
2496 /* Try to minimize scrolling, by setting the window start to the point
2497 will cause the text at the old window start to be at the same place
2498 on the frame. But don't try to do this if the window start is
2499 outside the visible portion (as might happen when the display is
2500 not current, due to typeahead). */
2501 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2502 if (new_top != top
2503 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2504 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2505 {
2506 struct position pos;
2507 struct buffer *obuf = current_buffer;
2508
2509 Fset_buffer (w->buffer);
2510 /* This computation used to temporarily move point, but that can
2511 have unwanted side effects due to text properties. */
2512 pos = *vmotion (startpos, -top, w);
2513
2514 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2515 w->window_end_valid = Qnil;
2516 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2517 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2518 : Qnil);
2519 /* We need to do this, so that the window-scroll-functions
2520 get called. */
2521 w->optional_new_start = Qt;
2522
2523 set_buffer_internal (obuf);
2524 }
2525
2526 return Qnil;
2527 }
2528
2529 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2530 1, 2, "bDelete windows on (buffer): ",
2531 doc: /* Delete all windows showing BUFFER.
2532 BUFFER must be a buffer or the name of an existing buffer.
2533 Optional second argument FRAME controls which frames are affected.
2534 If optional argument FRAME is `visible', search all visible frames.
2535 If FRAME is 0, search all visible and iconified frames.
2536 If FRAME is nil, search all frames.
2537 If FRAME is t, search only the selected frame.
2538 If FRAME is a frame, search only that frame. */)
2539 (buffer, frame)
2540 Lisp_Object buffer, frame;
2541 {
2542 /* FRAME uses t and nil to mean the opposite of what window_loop
2543 expects. */
2544 if (NILP (frame))
2545 frame = Qt;
2546 else if (EQ (frame, Qt))
2547 frame = Qnil;
2548
2549 if (!NILP (buffer))
2550 {
2551 buffer = Fget_buffer (buffer);
2552 CHECK_BUFFER (buffer);
2553 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2554 }
2555
2556 return Qnil;
2557 }
2558
2559 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2560 Sreplace_buffer_in_windows,
2561 1, 1, "bReplace buffer in windows: ",
2562 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2563 BUFFER may be a buffer or the name of an existing buffer. */)
2564 (buffer)
2565 Lisp_Object buffer;
2566 {
2567 if (!NILP (buffer))
2568 {
2569 buffer = Fget_buffer (buffer);
2570 CHECK_BUFFER (buffer);
2571 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2572 }
2573 return Qnil;
2574 }
2575
2576 /* Replace BUFFER with some other buffer in all windows
2577 of all frames, even those on other keyboards. */
2578
2579 void
2580 replace_buffer_in_all_windows (buffer)
2581 Lisp_Object buffer;
2582 {
2583 #ifdef MULTI_KBOARD
2584 Lisp_Object tail, frame;
2585
2586 /* A single call to window_loop won't do the job
2587 because it only considers frames on the current keyboard.
2588 So loop manually over frames, and handle each one. */
2589 FOR_EACH_FRAME (tail, frame)
2590 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2591 #else
2592 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2593 #endif
2594 }
2595 \f
2596 /* Set the height of WINDOW and all its inferiors. */
2597
2598 /* The smallest acceptable dimensions for a window. Anything smaller
2599 might crash Emacs. */
2600
2601 #define MIN_SAFE_WINDOW_WIDTH (2)
2602 #define MIN_SAFE_WINDOW_HEIGHT (1)
2603
2604 /* For wp non-zero the total number of columns of window w. Otherwise
2605 the total number of lines of w. */
2606
2607 #define WINDOW_TOTAL_SIZE(w, wp) \
2608 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2609
2610 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2611 minimum allowable size. */
2612
2613 void
2614 check_frame_size (frame, rows, cols)
2615 FRAME_PTR frame;
2616 int *rows, *cols;
2617 {
2618 /* For height, we have to see:
2619 how many windows the frame has at minimum (one or two),
2620 and whether it has a menu bar or other special stuff at the top. */
2621 int min_height
2622 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2623 ? MIN_SAFE_WINDOW_HEIGHT
2624 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2625
2626 if (FRAME_TOP_MARGIN (frame) > 0)
2627 min_height += FRAME_TOP_MARGIN (frame);
2628
2629 if (*rows < min_height)
2630 *rows = min_height;
2631 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2632 *cols = MIN_SAFE_WINDOW_WIDTH;
2633 }
2634
2635 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2636 check if W's width can be changed, otherwise check W's height.
2637 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2638 siblings, too. If none of the siblings is resizable, WINDOW isn't
2639 either. */
2640
2641 static int
2642 window_fixed_size_p (w, width_p, check_siblings_p)
2643 struct window *w;
2644 int width_p, check_siblings_p;
2645 {
2646 int fixed_p;
2647 struct window *c;
2648
2649 if (!NILP (w->hchild))
2650 {
2651 c = XWINDOW (w->hchild);
2652
2653 if (width_p)
2654 {
2655 /* A horizontal combination is fixed-width if all of if its
2656 children are. */
2657 while (c && window_fixed_size_p (c, width_p, 0))
2658 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2659 fixed_p = c == NULL;
2660 }
2661 else
2662 {
2663 /* A horizontal combination is fixed-height if one of if its
2664 children is. */
2665 while (c && !window_fixed_size_p (c, width_p, 0))
2666 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2667 fixed_p = c != NULL;
2668 }
2669 }
2670 else if (!NILP (w->vchild))
2671 {
2672 c = XWINDOW (w->vchild);
2673
2674 if (width_p)
2675 {
2676 /* A vertical combination is fixed-width if one of if its
2677 children is. */
2678 while (c && !window_fixed_size_p (c, width_p, 0))
2679 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2680 fixed_p = c != NULL;
2681 }
2682 else
2683 {
2684 /* A vertical combination is fixed-height if all of if its
2685 children are. */
2686 while (c && window_fixed_size_p (c, width_p, 0))
2687 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2688 fixed_p = c == NULL;
2689 }
2690 }
2691 else if (BUFFERP (w->buffer))
2692 {
2693 struct buffer *old = current_buffer;
2694 Lisp_Object val;
2695
2696 current_buffer = XBUFFER (w->buffer);
2697 val = find_symbol_value (Qwindow_size_fixed);
2698 current_buffer = old;
2699
2700 fixed_p = 0;
2701 if (!EQ (val, Qunbound))
2702 {
2703 fixed_p = !NILP (val);
2704
2705 if (fixed_p
2706 && ((EQ (val, Qheight) && width_p)
2707 || (EQ (val, Qwidth) && !width_p)))
2708 fixed_p = 0;
2709 }
2710
2711 /* Can't tell if this one is resizable without looking at
2712 siblings. If all siblings are fixed-size this one is too. */
2713 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2714 {
2715 Lisp_Object child;
2716
2717 for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev)
2718 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2719 break;
2720
2721 if (NILP (child))
2722 for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next)
2723 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2724 break;
2725
2726 if (NILP (child))
2727 fixed_p = 1;
2728 }
2729 }
2730 else
2731 fixed_p = 1;
2732
2733 return fixed_p;
2734 }
2735
2736 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2737 the minimum width of W, WIDTH_P zero means return the minimum height
2738 of W. SAFE_P non-zero means ignore window-min-height|width but just
2739 return values that won't crash Emacs and don't hide components like
2740 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2741 minibuffer window, always return 1. */
2742
2743 static int
2744 window_min_size_2 (w, width_p, safe_p)
2745 struct window *w;
2746 int width_p, safe_p;
2747 {
2748 /* We should consider buffer-local values of window_min_height and
2749 window_min_width here. */
2750 if (width_p)
2751 {
2752 int safe_size = (MIN_SAFE_WINDOW_WIDTH
2753 + WINDOW_FRINGE_COLS (w)
2754 + WINDOW_SCROLL_BAR_COLS (w));
2755
2756 return safe_p ? safe_size : max (window_min_width, safe_size);
2757 }
2758 else if (MINI_WINDOW_P (w))
2759 return 1;
2760 else
2761 {
2762 int safe_size = (MIN_SAFE_WINDOW_HEIGHT
2763 + ((BUFFERP (w->buffer)
2764 && !NILP (XBUFFER (w->buffer)->mode_line_format))
2765 ? 1 : 0));
2766
2767 return safe_p ? safe_size : max (window_min_height, safe_size);
2768 }
2769 }
2770
2771 /* Return minimum size of window W, not taking fixed-width windows into
2772 account. WIDTH_P non-zero means return the minimum width, otherwise
2773 return the minimum height. SAFE_P non-zero means ignore
2774 window-min-height|width but just return values that won't crash Emacs
2775 and don't hide components like fringes, scrollbars, or modelines. If
2776 W is a combination window, compute the minimum size from the minimum
2777 sizes of W's children. */
2778
2779 static int
2780 window_min_size_1 (w, width_p, safe_p)
2781 struct window *w;
2782 int width_p, safe_p;
2783 {
2784 struct window *c;
2785 int size;
2786
2787 if (!NILP (w->hchild))
2788 {
2789 /* W is a horizontal combination. */
2790 c = XWINDOW (w->hchild);
2791 size = 0;
2792
2793 if (width_p)
2794 {
2795 /* The minimum width of a horizontal combination is the sum of
2796 the minimum widths of its children. */
2797 while (c)
2798 {
2799 size += window_min_size_1 (c, 1, safe_p);
2800 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2801 }
2802 }
2803 else
2804 {
2805 /* The minimum height of a horizontal combination is the
2806 maximum of the minimum heights of its children. */
2807 while (c)
2808 {
2809 size = max (window_min_size_1 (c, 0, safe_p), size);
2810 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2811 }
2812 }
2813 }
2814 else if (!NILP (w->vchild))
2815 {
2816 /* W is a vertical combination. */
2817 c = XWINDOW (w->vchild);
2818 size = 0;
2819
2820 if (width_p)
2821 {
2822 /* The minimum width of a vertical combination is the maximum
2823 of the minimum widths of its children. */
2824 while (c)
2825 {
2826 size = max (window_min_size_1 (c, 1, safe_p), size);
2827 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2828 }
2829 }
2830 else
2831 {
2832 /* The minimum height of a vertical combination is the sum of
2833 the minimum height of its children. */
2834 while (c)
2835 {
2836 size += window_min_size_1 (c, 0, safe_p);
2837 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2838 }
2839 }
2840 }
2841 else
2842 /* W is a leaf window. */
2843 size = window_min_size_2 (w, width_p, safe_p);
2844
2845 return size;
2846 }
2847
2848 /* Return the minimum size of window W, taking fixed-size windows into
2849 account. WIDTH_P non-zero means return the minimum width, otherwise
2850 return the minimum height. SAFE_P non-zero means ignore
2851 window-min-height|width but just return values that won't crash Emacs
2852 and don't hide components like fringes, scrollbars, or modelines.
2853 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2854 to 1 if W is fixed-size unless FIXED is null. */
2855
2856 static int
2857 window_min_size (w, width_p, safe_p, ignore_fixed_p, fixed)
2858 struct window *w;
2859 int width_p, safe_p, ignore_fixed_p, *fixed;
2860 {
2861 int size, fixed_p;
2862
2863 if (ignore_fixed_p)
2864 fixed_p = 0;
2865 else
2866 fixed_p = window_fixed_size_p (w, width_p, 1);
2867
2868 if (fixed)
2869 *fixed = fixed_p;
2870
2871 if (fixed_p)
2872 size = WINDOW_TOTAL_SIZE (w, width_p);
2873 else
2874 size = window_min_size_1 (w, width_p, safe_p);
2875
2876 return size;
2877 }
2878
2879
2880 /* Adjust the margins of window W if text area is too small.
2881 Return 1 if window width is ok after adjustment; 0 if window
2882 is still too narrow. */
2883
2884 static int
2885 adjust_window_margins (w)
2886 struct window *w;
2887 {
2888 int box_cols = (WINDOW_TOTAL_COLS (w)
2889 - WINDOW_FRINGE_COLS (w)
2890 - WINDOW_SCROLL_BAR_COLS (w));
2891 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2892 + WINDOW_RIGHT_MARGIN_COLS (w));
2893
2894 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2895 return 1;
2896
2897 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2898 return 0;
2899
2900 /* Window's text area is too narrow, but reducing the window
2901 margins will fix that. */
2902 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2903 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2904 {
2905 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2906 w->left_margin_cols = w->right_margin_cols
2907 = make_number (margin_cols/2);
2908 else
2909 w->right_margin_cols = make_number (margin_cols);
2910 }
2911 else
2912 w->left_margin_cols = make_number (margin_cols);
2913 return 1;
2914 }
2915
2916 /* Calculate new sizes for windows in the list FORWARD when their
2917 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2918 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2919 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2920 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2921 shrink columns, otherwise shrink lines.
2922
2923 SAFE_P zero means windows may be sized down to window-min-height
2924 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2925 non-zero means windows may be sized down to their minimum safe sizes
2926 taking into account the space needed to display modelines, fringes,
2927 and scrollbars.
2928
2929 This function returns an allocated array of new sizes that the caller
2930 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2931 zero. A size zero means the window shall be deleted. Array index 0
2932 refers to the first window in FORWARD, 1 to the second, and so on.
2933
2934 This function resizes windows proportionally to their size. It also
2935 tries to preserve smaller windows by resizing larger windows before
2936 resizing any window to zero. If resize_proportionally is non-nil for
2937 a specific window, it will attempt to strictly resize that window
2938 proportionally, even at the expense of deleting smaller windows. */
2939 static int *
2940 shrink_windows (total, size, nchildren, shrinkable, resize_fixed_p,
2941 forward, width_p, safe_p)
2942 int total, size, nchildren, shrinkable;
2943 int resize_fixed_p, width_p, safe_p;
2944 Lisp_Object forward;
2945 {
2946 int available_resize = 0;
2947 int *new_sizes, *min_sizes;
2948 struct window *c;
2949 Lisp_Object child;
2950 int smallest = total;
2951 int total_removed = 0;
2952 int total_shrink = total - size;
2953 int i;
2954
2955 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2956 min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
2957
2958 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2959 {
2960 int child_size;
2961
2962 c = XWINDOW (child);
2963 child_size = WINDOW_TOTAL_SIZE (c, width_p);
2964
2965 if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2966 new_sizes[i] = -1;
2967 else
2968 {
2969 new_sizes[i] = child_size;
2970 min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
2971 if (child_size > min_sizes[i]
2972 && NILP (c->resize_proportionally))
2973 available_resize += child_size - min_sizes[i];
2974 }
2975 }
2976 /* We might need to shrink some windows to zero. Find the smallest
2977 windows and set them to 0 until we can fulfil the new size. */
2978
2979 while (shrinkable > 1 && size + available_resize < total)
2980 {
2981 for (i = 0; i < nchildren; ++i)
2982 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2983 smallest = new_sizes[i];
2984
2985 for (i = 0; i < nchildren; ++i)
2986 if (new_sizes[i] == smallest)
2987 {
2988 /* Resize this window down to zero. */
2989 new_sizes[i] = 0;
2990 if (smallest > min_sizes[i])
2991 available_resize -= smallest - min_sizes[i];
2992 available_resize += smallest;
2993 --shrinkable;
2994 total_removed += smallest;
2995
2996 /* We don't know what the smallest is now. */
2997 smallest = total;
2998
2999 /* Out of for, just remove one window at the time and
3000 check again if we have enough space. */
3001 break;
3002 }
3003 }
3004
3005 /* Now, calculate the new sizes. Try to shrink each window
3006 proportional to its size. */
3007 for (i = 0; i < nchildren; ++i)
3008 {
3009 if (new_sizes[i] > min_sizes[i])
3010 {
3011 int to_shrink = total_shrink * new_sizes[i] / total;
3012
3013 if (new_sizes[i] - to_shrink < min_sizes[i])
3014 to_shrink = new_sizes[i] - min_sizes[i];
3015 new_sizes[i] -= to_shrink;
3016 total_removed += to_shrink;
3017 }
3018 }
3019
3020 /* Any reminder due to rounding, we just subtract from windows
3021 that are left and still can be shrunk. */
3022 while (total_shrink > total_removed)
3023 {
3024 int nonzero_sizes = 0;
3025 int nonzero_idx = -1;
3026
3027 for (i = 0; i < nchildren; ++i)
3028 if (new_sizes[i] > 0)
3029 {
3030 ++nonzero_sizes;
3031 nonzero_idx = i;
3032 }
3033
3034 for (i = 0; i < nchildren; ++i)
3035 if (new_sizes[i] > min_sizes[i])
3036 {
3037 --new_sizes[i];
3038 ++total_removed;
3039
3040 /* Out of for, just shrink one window at the time and
3041 check again if we have enough space. */
3042 break;
3043 }
3044
3045 /* Special case, only one window left. */
3046 if (nonzero_sizes == 1)
3047 break;
3048 }
3049
3050 /* Any surplus due to rounding, we add to windows that are left. */
3051 while (total_shrink < total_removed)
3052 {
3053 for (i = 0; i < nchildren; ++i)
3054 {
3055 if (new_sizes[i] != 0 && total_shrink < total_removed)
3056 {
3057 ++new_sizes[i];
3058 --total_removed;
3059 break;
3060 }
3061 }
3062 }
3063
3064 xfree (min_sizes);
3065
3066 return new_sizes;
3067 }
3068
3069 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3070 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3071 their proportionate size relative to WINDOW.
3072
3073 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3074 they are in series. If LAST_ONLY is 1, change only the last of
3075 WINDOW's children when they are in series.
3076
3077 Propagate WINDOW's top or left edge position to children. Delete
3078 windows that become too small unless NODELETE_P is 1. When
3079 NODELETE_P equals 2 do not honor settings for window-min-height and
3080 window-min-width when resizing windows but use safe defaults instead.
3081 This should give better behavior when resizing frames. */
3082
3083 static void
3084 size_window (window, size, width_p, nodelete_p, first_only, last_only)
3085 Lisp_Object window;
3086 int size, width_p, nodelete_p;
3087 int first_only, last_only;
3088 {
3089 struct window *w = XWINDOW (window);
3090 struct window *c;
3091 Lisp_Object child, *forward, *sideward;
3092 int old_size = WINDOW_TOTAL_SIZE (w, width_p);
3093
3094 size = max (0, size);
3095
3096 /* Delete WINDOW if it's too small. */
3097 if (nodelete_p != 1 && !NILP (w->parent)
3098 && size < window_min_size_1 (w, width_p, nodelete_p == 2))
3099 {
3100 delete_window (window);
3101 return;
3102 }
3103
3104 /* Set redisplay hints. */
3105 w->last_modified = make_number (0);
3106 w->last_overlay_modified = make_number (0);
3107 windows_or_buffers_changed++;
3108 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3109
3110 if (width_p)
3111 {
3112 sideward = &w->vchild;
3113 forward = &w->hchild;
3114 w->total_cols = make_number (size);
3115 adjust_window_margins (w);
3116 }
3117 else
3118 {
3119 sideward = &w->hchild;
3120 forward = &w->vchild;
3121 w->total_lines = make_number (size);
3122 w->orig_total_lines = Qnil;
3123 }
3124
3125 if (!NILP (*sideward))
3126 {
3127 /* We have a chain of parallel siblings whose size should all change. */
3128 for (child = *sideward; !NILP (child); child = c->next)
3129 {
3130 c = XWINDOW (child);
3131 if (width_p)
3132 c->left_col = w->left_col;
3133 else
3134 c->top_line = w->top_line;
3135 size_window (child, size, width_p, nodelete_p,
3136 first_only, last_only);
3137 }
3138 }
3139 else if (!NILP (*forward) && last_only)
3140 {
3141 /* Change the last in a series of siblings. */
3142 Lisp_Object last_child;
3143 int child_size;
3144
3145 for (child = *forward; !NILP (child); child = c->next)
3146 {
3147 c = XWINDOW (child);
3148 last_child = child;
3149 }
3150
3151 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3152 size_window (last_child, size - old_size + child_size,
3153 width_p, nodelete_p, first_only, last_only);
3154 }
3155 else if (!NILP (*forward) && first_only)
3156 {
3157 /* Change the first in a series of siblings. */
3158 int child_size;
3159
3160 child = *forward;
3161 c = XWINDOW (child);
3162
3163 if (width_p)
3164 c->left_col = w->left_col;
3165 else
3166 c->top_line = w->top_line;
3167
3168 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3169 size_window (child, size - old_size + child_size,
3170 width_p, nodelete_p, first_only, last_only);
3171 }
3172 else if (!NILP (*forward))
3173 {
3174 int fixed_size, each, extra, n;
3175 int resize_fixed_p, nfixed;
3176 int last_pos, first_pos, nchildren, total;
3177 int *new_sizes = NULL;
3178
3179 /* Determine the fixed-size portion of this window, and the
3180 number of child windows. */
3181 fixed_size = nchildren = nfixed = total = 0;
3182 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3183 {
3184 int child_size;
3185
3186 c = XWINDOW (child);
3187 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3188 total += child_size;
3189
3190 if (window_fixed_size_p (c, width_p, 0))
3191 {
3192 fixed_size += child_size;
3193 ++nfixed;
3194 }
3195 }
3196
3197 /* If the new size is smaller than fixed_size, or if there
3198 aren't any resizable windows, allow resizing fixed-size
3199 windows. */
3200 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3201
3202 /* Compute how many lines/columns to add/remove to each child. The
3203 value of extra takes care of rounding errors. */
3204 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3205 if (size < total && n > 1)
3206 new_sizes = shrink_windows (total, size, nchildren, n,
3207 resize_fixed_p, *forward, width_p,
3208 nodelete_p == 2);
3209 else
3210 {
3211 each = (size - total) / n;
3212 extra = (size - total) - n * each;
3213 }
3214
3215 /* Compute new children heights and edge positions. */
3216 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3217 last_pos = first_pos;
3218 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3219 {
3220 int new_size, old_size;
3221
3222 c = XWINDOW (child);
3223 old_size = WINDOW_TOTAL_SIZE (c, width_p);
3224 new_size = old_size;
3225
3226 /* The top or left edge position of this child equals the
3227 bottom or right edge of its predecessor. */
3228 if (width_p)
3229 c->left_col = make_number (last_pos);
3230 else
3231 c->top_line = make_number (last_pos);
3232
3233 /* If this child can be resized, do it. */
3234 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3235 {
3236 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3237 extra = 0;
3238 }
3239
3240 /* Set new size. Note that size_window also propagates
3241 edge positions to children, so it's not a no-op if we
3242 didn't change the child's size. */
3243 size_window (child, new_size, width_p, 1, first_only, last_only);
3244
3245 /* Remember the bottom/right edge position of this child; it
3246 will be used to set the top/left edge of the next child. */
3247 last_pos += new_size;
3248 }
3249
3250 xfree (new_sizes);
3251
3252 /* We should have covered the parent exactly with child windows. */
3253 xassert (size == last_pos - first_pos);
3254
3255 /* Now delete any children that became too small. */
3256 if (nodelete_p != 1)
3257 for (child = *forward; !NILP (child); child = c->next)
3258 {
3259 int child_size;
3260
3261 c = XWINDOW (child);
3262 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3263 size_window (child, child_size, width_p, nodelete_p,
3264 first_only, last_only);
3265 }
3266 }
3267 }
3268
3269 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3270 WINDOW's children. NODELETE zero means windows that have become
3271 smaller than window-min-height in the process may be deleted.
3272 NODELETE 1 means never delete windows that become too small in the
3273 process. (The caller should check later and do so if appropriate.)
3274 NODELETE 2 means delete only windows that have become too small to be
3275 displayed correctly. */
3276
3277 void
3278 set_window_height (window, height, nodelete)
3279 Lisp_Object window;
3280 int height;
3281 int nodelete;
3282 {
3283 size_window (window, height, 0, nodelete, 0, 0);
3284 }
3285
3286 /* Set WINDOW's width to WIDTH, and recursively change the width of
3287 WINDOW's children. NODELETE zero means windows that have become
3288 smaller than window-min-width in the process may be deleted.
3289 NODELETE 1 means never delete windows that become too small in the
3290 process. (The caller should check later and do so if appropriate.)
3291 NODELETE 2 means delete only windows that have become too small to be
3292 displayed correctly. */
3293
3294 void
3295 set_window_width (window, width, nodelete)
3296 Lisp_Object window;
3297 int width;
3298 int nodelete;
3299 {
3300 size_window (window, width, 1, nodelete, 0, 0);
3301 }
3302
3303 /* Change window heights in windows rooted in WINDOW by N lines. */
3304
3305 void
3306 change_window_heights (window, n)
3307 Lisp_Object window;
3308 int n;
3309 {
3310 struct window *w = XWINDOW (window);
3311
3312 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3313 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3314
3315 if (INTEGERP (w->orig_top_line))
3316 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3317 if (INTEGERP (w->orig_total_lines))
3318 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3319
3320 /* Handle just the top child in a vertical split. */
3321 if (!NILP (w->vchild))
3322 change_window_heights (w->vchild, n);
3323
3324 /* Adjust all children in a horizontal split. */
3325 for (window = w->hchild; !NILP (window); window = w->next)
3326 {
3327 w = XWINDOW (window);
3328 change_window_heights (window, n);
3329 }
3330 }
3331
3332 \f
3333 int window_select_count;
3334
3335 Lisp_Object
3336 Fset_window_buffer_unwind (obuf)
3337 Lisp_Object obuf;
3338 {
3339 Fset_buffer (obuf);
3340 return Qnil;
3341 }
3342
3343 EXFUN (Fset_window_fringes, 4);
3344 EXFUN (Fset_window_scroll_bars, 4);
3345
3346 static void
3347 run_funs (Lisp_Object funs)
3348 {
3349 for (; CONSP (funs); funs = XCDR (funs))
3350 if (!EQ (XCAR (funs), Qt))
3351 call0 (XCAR (funs));
3352 }
3353
3354 static Lisp_Object select_window_norecord (Lisp_Object window);
3355
3356 void
3357 run_window_configuration_change_hook (struct frame *f)
3358 {
3359 int count = SPECPDL_INDEX ();
3360 Lisp_Object frame, global_wcch
3361 = Fdefault_value (Qwindow_configuration_change_hook);
3362 XSETFRAME (frame, f);
3363
3364 if (NILP (Vrun_hooks))
3365 return;
3366
3367 if (SELECTED_FRAME () != f)
3368 {
3369 record_unwind_protect (Fselect_frame, Fselected_frame ());
3370 Fselect_frame (frame);
3371 }
3372
3373 /* Use the right buffer. Matters when running the local hooks. */
3374 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3375 {
3376 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3377 Fset_buffer (Fwindow_buffer (Qnil));
3378 }
3379
3380 /* Look for buffer-local values. */
3381 {
3382 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3383 for (; CONSP (windows); windows = XCDR (windows))
3384 {
3385 Lisp_Object window = XCAR (windows);
3386 Lisp_Object buffer = Fwindow_buffer (window);
3387 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3388 buffer)))
3389 {
3390 int count = SPECPDL_INDEX ();
3391 record_unwind_protect (select_window_norecord, Fselected_window ());
3392 select_window_norecord (window);
3393 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3394 buffer));
3395 unbind_to (count, Qnil);
3396 }
3397 }
3398 }
3399
3400 run_funs (global_wcch);
3401 unbind_to (count, Qnil);
3402 }
3403
3404 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3405 means it's allowed to run hooks. See make_frame for a case where
3406 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3407 margins, fringes, and scroll-bar settings of the window are not
3408 reset from the buffer's local settings. */
3409
3410 void
3411 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3412 Lisp_Object window, buffer;
3413 int run_hooks_p, keep_margins_p;
3414 {
3415 struct window *w = XWINDOW (window);
3416 struct buffer *b = XBUFFER (buffer);
3417 int count = SPECPDL_INDEX ();
3418 int samebuf = EQ (buffer, w->buffer);
3419
3420 w->buffer = buffer;
3421
3422 if (EQ (window, selected_window))
3423 b->last_selected_window = window;
3424
3425 /* Let redisplay errors through. */
3426 b->display_error_modiff = 0;
3427
3428 /* Update time stamps of buffer display. */
3429 if (INTEGERP (b->display_count))
3430 XSETINT (b->display_count, XINT (b->display_count) + 1);
3431 b->display_time = Fcurrent_time ();
3432
3433 XSETFASTINT (w->window_end_pos, 0);
3434 XSETFASTINT (w->window_end_vpos, 0);
3435 bzero (&w->last_cursor, sizeof w->last_cursor);
3436 w->window_end_valid = Qnil;
3437 if (!(keep_margins_p && samebuf))
3438 { /* If we're not actually changing the buffer, Don't reset hscroll and
3439 vscroll. This case happens for example when called from
3440 change_frame_size_1, where we use a dummy call to
3441 Fset_window_buffer on the frame's selected window (and no other)
3442 just in order to run window-configuration-change-hook.
3443 Resetting hscroll and vscroll here is problematic for things like
3444 image-mode and doc-view-mode since it resets the image's position
3445 whenever we resize the frame. */
3446 w->hscroll = w->min_hscroll = make_number (0);
3447 w->vscroll = 0;
3448 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3449 set_marker_restricted (w->start,
3450 make_number (b->last_window_start),
3451 buffer);
3452 w->start_at_line_beg = Qnil;
3453 w->force_start = Qnil;
3454 XSETFASTINT (w->last_modified, 0);
3455 XSETFASTINT (w->last_overlay_modified, 0);
3456 }
3457 /* Maybe we could move this into the `if' but it's not obviously safe and
3458 I doubt it's worth the trouble. */
3459 windows_or_buffers_changed++;
3460
3461 /* We must select BUFFER for running the window-scroll-functions.
3462 If WINDOW is selected, switch permanently.
3463 Otherwise, switch but go back to the ambient buffer afterward. */
3464 if (EQ (window, selected_window))
3465 Fset_buffer (buffer);
3466 /* We can't check ! NILP (Vwindow_scroll_functions) here
3467 because that might itself be a local variable. */
3468 else if (window_initialized)
3469 {
3470 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
3471 Fset_buffer (buffer);
3472 }
3473
3474 if (!keep_margins_p)
3475 {
3476 /* Set left and right marginal area width etc. from buffer. */
3477
3478 /* This may call adjust_window_margins three times, so
3479 temporarily disable window margins. */
3480 Lisp_Object save_left = w->left_margin_cols;
3481 Lisp_Object save_right = w->right_margin_cols;
3482
3483 w->left_margin_cols = w->right_margin_cols = Qnil;
3484
3485 Fset_window_fringes (window,
3486 b->left_fringe_width, b->right_fringe_width,
3487 b->fringes_outside_margins);
3488
3489 Fset_window_scroll_bars (window,
3490 b->scroll_bar_width,
3491 b->vertical_scroll_bar_type, Qnil);
3492
3493 w->left_margin_cols = save_left;
3494 w->right_margin_cols = save_right;
3495
3496 Fset_window_margins (window,
3497 b->left_margin_cols, b->right_margin_cols);
3498 }
3499
3500 if (run_hooks_p)
3501 {
3502 if (! NILP (Vwindow_scroll_functions))
3503 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3504 Fmarker_position (w->start));
3505 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3506 }
3507
3508 unbind_to (count, Qnil);
3509 }
3510
3511
3512 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3513 doc: /* Make WINDOW display BUFFER as its contents.
3514 BUFFER can be a buffer or the name of an existing buffer.
3515 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3516 display margins, fringe widths, and scroll bar settings are maintained;
3517 the default is to reset these from BUFFER's local settings or the frame
3518 defaults.
3519
3520 This function runs the hook `window-scroll-functions'. */)
3521 (window, buffer, keep_margins)
3522 register Lisp_Object window, buffer, keep_margins;
3523 {
3524 register Lisp_Object tem;
3525 register struct window *w = decode_window (window);
3526
3527 XSETWINDOW (window, w);
3528 buffer = Fget_buffer (buffer);
3529 CHECK_BUFFER (buffer);
3530
3531 if (NILP (XBUFFER (buffer)->name))
3532 error ("Attempt to display deleted buffer");
3533
3534 tem = w->buffer;
3535 if (NILP (tem))
3536 error ("Window is deleted");
3537 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3538 is first being set up. */
3539 {
3540 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3541 error ("Window is dedicated to `%s'",
3542 SDATA (XBUFFER (tem)->name));
3543
3544 unshow_buffer (w);
3545 }
3546
3547 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3548 return Qnil;
3549 }
3550
3551 /* Note that selected_window can be nil
3552 when this is called from Fset_window_configuration. */
3553
3554 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3555 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3556 If WINDOW is not already selected, make WINDOW's buffer current
3557 and make WINDOW the frame's selected window. Return WINDOW.
3558 Optional second arg NORECORD non-nil means
3559 do not put this buffer at the front of the list of recently selected ones.
3560
3561 Note that the main editor command loop
3562 selects the buffer of the selected window before each command. */)
3563 (window, norecord)
3564 register Lisp_Object window, norecord;
3565 {
3566 register struct window *w;
3567 register struct window *ow;
3568 struct frame *sf;
3569
3570 CHECK_LIVE_WINDOW (window);
3571
3572 w = XWINDOW (window);
3573 w->frozen_window_start_p = 0;
3574
3575 ++window_select_count;
3576 XSETFASTINT (w->use_time, window_select_count);
3577 if (EQ (window, selected_window))
3578 return window;
3579
3580 sf = SELECTED_FRAME ();
3581 if (XFRAME (WINDOW_FRAME (w)) != sf)
3582 {
3583 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3584 /* Use this rather than Fhandle_switch_frame
3585 so that FRAME_FOCUS_FRAME is moved appropriately as we
3586 move around in the state where a minibuffer in a separate
3587 frame is active. */
3588 Fselect_frame (WINDOW_FRAME (w));
3589 /* Fselect_frame called us back so we've done all the work already. */
3590 eassert (EQ (window, selected_window));
3591 return window;
3592 }
3593 else
3594 sf->selected_window = window;
3595
3596 /* Store the current buffer's actual point into the
3597 old selected window. It belongs to that window,
3598 and when the window is not selected, must be in the window. */
3599 if (!NILP (selected_window))
3600 {
3601 ow = XWINDOW (selected_window);
3602 if (! NILP (ow->buffer))
3603 set_marker_both (ow->pointm, ow->buffer,
3604 BUF_PT (XBUFFER (ow->buffer)),
3605 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3606 }
3607
3608 selected_window = window;
3609
3610 if (NILP (norecord))
3611 record_buffer (w->buffer);
3612 Fset_buffer (w->buffer);
3613
3614 XBUFFER (w->buffer)->last_selected_window = window;
3615
3616 /* Go to the point recorded in the window.
3617 This is important when the buffer is in more
3618 than one window. It also matters when
3619 redisplay_window has altered point after scrolling,
3620 because it makes the change only in the window. */
3621 {
3622 register int new_point = marker_position (w->pointm);
3623 if (new_point < BEGV)
3624 SET_PT (BEGV);
3625 else if (new_point > ZV)
3626 SET_PT (ZV);
3627 else
3628 SET_PT (new_point);
3629 }
3630
3631 windows_or_buffers_changed++;
3632 return window;
3633 }
3634
3635 static Lisp_Object
3636 select_window_norecord (window)
3637 Lisp_Object window;
3638 {
3639 return Fselect_window (window, Qt);
3640 }
3641 \f
3642 /* Deiconify the frame containing the window WINDOW,
3643 unless it is the selected frame;
3644 then return WINDOW.
3645
3646 The reason for the exception for the selected frame
3647 is that it seems better not to change the selected frames visibility
3648 merely because of displaying a different buffer in it.
3649 The deiconification is useful when a buffer gets shown in
3650 another frame that you were not using lately. */
3651
3652 static Lisp_Object
3653 display_buffer_1 (window)
3654 Lisp_Object window;
3655 {
3656 Lisp_Object frame = XWINDOW (window)->frame;
3657 FRAME_PTR f = XFRAME (frame);
3658
3659 FRAME_SAMPLE_VISIBILITY (f);
3660
3661 if (EQ (frame, selected_frame))
3662 ; /* Assume the selected frame is already visible enough. */
3663 else if (minibuf_level > 0
3664 && MINI_WINDOW_P (XWINDOW (selected_window))
3665 && WINDOW_LIVE_P (minibuf_selected_window)
3666 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3667 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3668 else
3669 {
3670 if (FRAME_ICONIFIED_P (f))
3671 Fmake_frame_visible (frame);
3672 else if (FRAME_VISIBLE_P (f))
3673 Fraise_frame (frame);
3674 }
3675
3676 return window;
3677 }
3678
3679 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3680 doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3681 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3682 special frame for that buffer using the default frame parameters.
3683
3684 If the value is a list, it is a list of frame parameters that would be used
3685 to make a frame for that buffer.
3686 The variables `special-display-buffer-names'
3687 and `special-display-regexps' control this. */)
3688 (buffer_name)
3689 Lisp_Object buffer_name;
3690 {
3691 Lisp_Object tem;
3692
3693 CHECK_STRING (buffer_name);
3694
3695 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3696 if (!NILP (tem))
3697 return Qt;
3698
3699 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3700 if (!NILP (tem))
3701 return XCDR (tem);
3702
3703 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3704 {
3705 Lisp_Object car = XCAR (tem);
3706 if (STRINGP (car)
3707 && fast_string_match (car, buffer_name) >= 0)
3708 return Qt;
3709 else if (CONSP (car)
3710 && STRINGP (XCAR (car))
3711 && fast_string_match (XCAR (car), buffer_name) >= 0)
3712 return XCDR (car);
3713 }
3714 return Qnil;
3715 }
3716
3717 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3718 doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3719 More precisely, if `display-buffer' or `pop-to-buffer' would display
3720 that buffer in the selected window rather than (as usual) in some other window.
3721 See `same-window-buffer-names' and `same-window-regexps'. */)
3722 (buffer_name)
3723 Lisp_Object buffer_name;
3724 {
3725 Lisp_Object tem;
3726
3727 CHECK_STRING (buffer_name);
3728
3729 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3730 if (!NILP (tem))
3731 return Qt;
3732
3733 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3734 if (!NILP (tem))
3735 return Qt;
3736
3737 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3738 {
3739 Lisp_Object car = XCAR (tem);
3740 if (STRINGP (car)
3741 && fast_string_match (car, buffer_name) >= 0)
3742 return Qt;
3743 else if (CONSP (car)
3744 && STRINGP (XCAR (car))
3745 && fast_string_match (XCAR (car), buffer_name) >= 0)
3746 return Qt;
3747 }
3748 return Qnil;
3749 }
3750
3751 /* Use B so the default is (other-buffer). */
3752 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3753 "BDisplay buffer: \nP",
3754 doc: /* Make BUFFER appear in some window but don't select it.
3755 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3756 a buffer.
3757 If BUFFER is shown already in some window, just use that one,
3758 unless the window is the selected window and the optional second
3759 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3760 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3761 Returns the window displaying BUFFER.
3762 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3763 displaying BUFFER, then simply raise that frame.
3764
3765 The variables `special-display-buffer-names',
3766 `special-display-regexps', `same-window-buffer-names', and
3767 `same-window-regexps' customize how certain buffer names are handled.
3768 The latter two take effect only if NOT-THIS-WINDOW is nil.
3769
3770 If optional argument FRAME is `visible', check all visible frames
3771 for a window to use.
3772 If FRAME is 0, check all visible and iconified frames.
3773 If FRAME is t, check all frames.
3774 If FRAME is a frame, check only that frame.
3775 If FRAME is nil, check only the selected frame
3776 (actually the last nonminibuffer frame),
3777 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3778 which means search visible and iconified frames.
3779
3780 If a full-width window on a splittable frame is available to display
3781 the buffer, it may be split, subject to the value of the variable
3782 `split-height-threshold'.
3783
3784 If `even-window-heights' is non-nil, window heights will be evened out
3785 if displaying the buffer causes two vertically adjacent windows to be
3786 displayed. */)
3787 (buffer, not_this_window, frame)
3788 Lisp_Object buffer, not_this_window, frame;
3789 {
3790 register Lisp_Object window, tem, swp;
3791 struct frame *f;
3792
3793 swp = Qnil;
3794 buffer = Fget_buffer (buffer);
3795 CHECK_BUFFER (buffer);
3796
3797 if (!NILP (Vdisplay_buffer_function))
3798 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3799
3800 if (NILP (not_this_window)
3801 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3802 return display_buffer_1 (selected_window);
3803
3804 /* See if the user has specified this buffer should appear
3805 in the selected window. */
3806 if (NILP (not_this_window))
3807 {
3808 swp = Fsame_window_p (XBUFFER (buffer)->name);
3809 if (!NILP (swp) && !no_switch_window (selected_window))
3810 {
3811 Fswitch_to_buffer (buffer, Qnil);
3812 return display_buffer_1 (selected_window);
3813 }
3814 }
3815
3816 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3817 look for a window showing BUFFER on any visible or iconified frame.
3818 Otherwise search only the current frame. */
3819 if (! NILP (frame))
3820 tem = frame;
3821 else if (pop_up_frames
3822 || display_buffer_reuse_frames
3823 || last_nonminibuf_frame == 0)
3824 XSETFASTINT (tem, 0);
3825 else
3826 XSETFRAME (tem, last_nonminibuf_frame);
3827
3828 window = Fget_buffer_window (buffer, tem);
3829 if (!NILP (window)
3830 && (NILP (not_this_window) || !EQ (window, selected_window)))
3831 return display_buffer_1 (window);
3832
3833 /* Certain buffer names get special handling. */
3834 if (!NILP (Vspecial_display_function) && NILP (swp))
3835 {
3836 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3837 if (EQ (tem, Qt))
3838 return call1 (Vspecial_display_function, buffer);
3839 if (CONSP (tem))
3840 return call2 (Vspecial_display_function, buffer, tem);
3841 }
3842
3843 /* If there are no frames open that have more than a minibuffer,
3844 we need to create a new frame. */
3845 if (pop_up_frames || last_nonminibuf_frame == 0)
3846 {
3847 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3848 Fset_window_buffer (window, buffer, Qnil);
3849 return display_buffer_1 (window);
3850 }
3851
3852 f = SELECTED_FRAME ();
3853 if (pop_up_windows
3854 || FRAME_MINIBUF_ONLY_P (f)
3855 /* If the current frame is a special display frame,
3856 don't try to reuse its windows. */
3857 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3858 {
3859 Lisp_Object frames;
3860 struct gcpro gcpro1;
3861 GCPRO1 (buffer);
3862
3863 frames = Qnil;
3864 if (FRAME_MINIBUF_ONLY_P (f))
3865 XSETFRAME (frames, last_nonminibuf_frame);
3866
3867 /* Note that both Fget_largest_window and Fget_lru_window
3868 ignore minibuffers and dedicated windows.
3869 This means they can return nil. */
3870
3871 /* If the frame we would try to split cannot be split,
3872 try other frames. */
3873 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3874 {
3875 /* Try visible frames first. */
3876 window = Fget_largest_window (Qvisible, Qt);
3877 /* If that didn't work, try iconified frames. */
3878 if (NILP (window))
3879 window = Fget_largest_window (make_number (0), Qt);
3880 #if 0 /* Don't try windows on other displays. */
3881 if (NILP (window))
3882 window = Fget_largest_window (Qt, Qt);
3883 #endif
3884 }
3885 else
3886 window = Fget_largest_window (frames, Qt);
3887
3888 tem = Qnil;
3889 if (!NILP (Vsplit_window_preferred_function))
3890 tem = call1 (Vsplit_window_preferred_function, window);
3891
3892 if (!NILP (tem))
3893 window = tem;
3894 else
3895 /* If the largest window is tall enough, full-width, and either eligible
3896 for splitting or the only window, split it. */
3897 if (!NILP (window)
3898 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3899 && WINDOW_FULL_WIDTH_P (XWINDOW (window))
3900 && (window_height (window) >= split_height_threshold
3901 || (NILP (XWINDOW (window)->parent)))
3902 && (window_height (window)
3903 >= (2 * window_min_size_2 (XWINDOW (window), 0, 0))))
3904 window = Fsplit_window (window, Qnil, Qnil);
3905 else
3906 {
3907 Lisp_Object upper, other;
3908
3909 window = Fget_lru_window (frames, Qt);
3910 /* If the LRU window is tall enough, and either eligible for
3911 splitting and selected or the only window, split it. */
3912 if (!NILP (window)
3913 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3914 && ((EQ (window, selected_window)
3915 && window_height (window) >= split_height_threshold)
3916 || (NILP (XWINDOW (window)->parent)))
3917 && (window_height (window)
3918 >= (2 * window_min_size_2 (XWINDOW (window), 0, 0))))
3919 window = Fsplit_window (window, Qnil, Qnil);
3920 else
3921 window = Fget_lru_window (frames, Qnil);
3922 /* If Fget_lru_window returned nil, try other approaches. */
3923
3924 /* Try visible frames first. */
3925 if (NILP (window))
3926 window = Fget_buffer_window (buffer, Qvisible);
3927 if (NILP (window))
3928 window = Fget_largest_window (Qvisible, Qnil);
3929 /* If that didn't work, try iconified frames. */
3930 if (NILP (window))
3931 window = Fget_buffer_window (buffer, make_number (0));
3932 if (NILP (window))
3933 window = Fget_largest_window (make_number (0), Qnil);
3934
3935 #if 0 /* Don't try frames on other displays. */
3936 if (NILP (window))
3937 window = Fget_buffer_window (buffer, Qt);
3938 if (NILP (window))
3939 window = Fget_largest_window (Qt, Qnil);
3940 #endif
3941 /* As a last resort, make a new frame. */
3942 if (NILP (window))
3943 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3944 /* If window appears above or below another,
3945 even out their heights. */
3946 other = upper = Qnil;
3947 if (!NILP (XWINDOW (window)->prev))
3948 other = upper = XWINDOW (window)->prev;
3949 if (!NILP (XWINDOW (window)->next))
3950 other = XWINDOW (window)->next, upper = window;
3951 if (!NILP (other)
3952 && !NILP (Veven_window_heights)
3953 /* Check that OTHER and WINDOW are vertically arrayed. */
3954 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3955 && (XFASTINT (XWINDOW (other)->total_lines)
3956 > XFASTINT (XWINDOW (window)->total_lines)))
3957 {
3958 int total = (XFASTINT (XWINDOW (other)->total_lines)
3959 + XFASTINT (XWINDOW (window)->total_lines));
3960 enlarge_window (upper,
3961 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3962 0);
3963 }
3964 }
3965 UNGCPRO;
3966 }
3967 else
3968 window = Fget_lru_window (Qnil, Qnil);
3969
3970 Fset_window_buffer (window, buffer, Qnil);
3971 return display_buffer_1 (window);
3972 }
3973
3974
3975 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3976 0, 1, 0,
3977 doc: /* Force all windows to be updated on next redisplay.
3978 If optional arg OBJECT is a window, force redisplay of that window only.
3979 If OBJECT is a buffer or buffer name, force redisplay of all windows
3980 displaying that buffer. */)
3981 (object)
3982 Lisp_Object object;
3983 {
3984 if (NILP (object))
3985 {
3986 windows_or_buffers_changed++;
3987 update_mode_lines++;
3988 return Qt;
3989 }
3990
3991 if (WINDOWP (object))
3992 {
3993 struct window *w = XWINDOW (object);
3994 mark_window_display_accurate (object, 0);
3995 w->update_mode_line = Qt;
3996 if (BUFFERP (w->buffer))
3997 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3998 ++update_mode_lines;
3999 return Qt;
4000 }
4001
4002 if (STRINGP (object))
4003 object = Fget_buffer (object);
4004 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
4005 {
4006 /* Walk all windows looking for buffer, and force update
4007 of each of those windows. */
4008
4009 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
4010 return NILP (object) ? Qnil : Qt;
4011 }
4012
4013 /* If nothing suitable was found, just return.
4014 We could signal an error, but this feature will typically be used
4015 asynchronously in timers or process sentinels, so we don't. */
4016 return Qnil;
4017 }
4018
4019
4020 void
4021 temp_output_buffer_show (buf)
4022 register Lisp_Object buf;
4023 {
4024 register struct buffer *old = current_buffer;
4025 register Lisp_Object window;
4026 register struct window *w;
4027
4028 XBUFFER (buf)->directory = current_buffer->directory;
4029
4030 Fset_buffer (buf);
4031 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
4032 BEGV = BEG;
4033 ZV = Z;
4034 SET_PT (BEG);
4035 #if 0 /* rms: there should be no reason for this. */
4036 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
4037 #endif
4038 set_buffer_internal (old);
4039
4040 if (!NILP (Vtemp_buffer_show_function))
4041 call1 (Vtemp_buffer_show_function, buf);
4042 else
4043 {
4044 window = Fdisplay_buffer (buf, Qnil, Qnil);
4045
4046 if (!EQ (XWINDOW (window)->frame, selected_frame))
4047 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
4048 Vminibuf_scroll_window = window;
4049 w = XWINDOW (window);
4050 XSETFASTINT (w->hscroll, 0);
4051 XSETFASTINT (w->min_hscroll, 0);
4052 set_marker_restricted_both (w->start, buf, BEG, BEG);
4053 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
4054
4055 /* Run temp-buffer-show-hook, with the chosen window selected
4056 and its buffer current. */
4057
4058 if (!NILP (Vrun_hooks)
4059 && !NILP (Fboundp (Qtemp_buffer_show_hook))
4060 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
4061 {
4062 int count = SPECPDL_INDEX ();
4063 Lisp_Object prev_window, prev_buffer;
4064 prev_window = selected_window;
4065 XSETBUFFER (prev_buffer, old);
4066
4067 /* Select the window that was chosen, for running the hook.
4068 Note: Both Fselect_window and select_window_norecord may
4069 set-buffer to the buffer displayed in the window,
4070 so we need to save the current buffer. --stef */
4071 record_unwind_protect (Fset_buffer, prev_buffer);
4072 record_unwind_protect (select_window_norecord, prev_window);
4073 Fselect_window (window, Qt);
4074 Fset_buffer (w->buffer);
4075 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
4076 unbind_to (count, Qnil);
4077 }
4078 }
4079 }
4080 \f
4081 static void
4082 make_dummy_parent (window)
4083 Lisp_Object window;
4084 {
4085 Lisp_Object new;
4086 register struct window *o, *p;
4087 int i;
4088
4089 o = XWINDOW (window);
4090 p = allocate_window ();
4091 for (i = 0; i < VECSIZE (struct window); ++i)
4092 ((struct Lisp_Vector *) p)->contents[i]
4093 = ((struct Lisp_Vector *)o)->contents[i];
4094 XSETWINDOW (new, p);
4095
4096 ++sequence_number;
4097 XSETFASTINT (p->sequence_number, sequence_number);
4098
4099 /* Put new into window structure in place of window */
4100 replace_window (window, new);
4101
4102 o->next = Qnil;
4103 o->prev = Qnil;
4104 o->vchild = Qnil;
4105 o->hchild = Qnil;
4106 o->parent = new;
4107
4108 p->start = Qnil;
4109 p->pointm = Qnil;
4110 p->buffer = Qnil;
4111 }
4112
4113 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
4114 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
4115 WINDOW defaults to selected one and SIZE to half its size.
4116 If optional third arg HORFLAG is non-nil, split side by side
4117 and put SIZE columns in the first of the pair. In that case,
4118 SIZE includes that window's scroll bar, or the divider column to its right.
4119 Interactively, all arguments are nil.
4120
4121 Returns the newly created window (which is the lower or rightmost one).
4122 The upper or leftmost window is the original one, and remains selected
4123 if it was selected before.
4124
4125 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
4126 (window, size, horflag)
4127 Lisp_Object window, size, horflag;
4128 {
4129 register Lisp_Object new;
4130 register struct window *o, *p;
4131 FRAME_PTR fo;
4132 register int size_int;
4133
4134 if (NILP (window))
4135 window = selected_window;
4136 else
4137 CHECK_LIVE_WINDOW (window);
4138
4139 o = XWINDOW (window);
4140 fo = XFRAME (WINDOW_FRAME (o));
4141
4142 if (NILP (size))
4143 {
4144 if (!NILP (horflag))
4145 /* Calculate the size of the left-hand window, by dividing
4146 the usable space in columns by two.
4147 We round up, since the left-hand window may include
4148 a dividing line, while the right-hand may not. */
4149 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
4150 else
4151 size_int = XFASTINT (o->total_lines) >> 1;
4152 }
4153 else
4154 {
4155 CHECK_NUMBER (size);
4156 size_int = XINT (size);
4157 }
4158
4159 if (MINI_WINDOW_P (o))
4160 error ("Attempt to split minibuffer window");
4161 else if (window_fixed_size_p (o, !NILP (horflag), 0))
4162 error ("Attempt to split fixed-size window");
4163
4164 if (NILP (horflag))
4165 {
4166 int window_safe_height = window_min_size_2 (o, 0, 0);
4167
4168 if (size_int < window_safe_height)
4169 error ("Window height %d too small (after splitting)", size_int);
4170 if (size_int + window_safe_height > XFASTINT (o->total_lines))
4171 error ("Window height %d too small (after splitting)",
4172 XFASTINT (o->total_lines) - size_int);
4173 if (NILP (o->parent)
4174 || NILP (XWINDOW (o->parent)->vchild))
4175 {
4176 make_dummy_parent (window);
4177 new = o->parent;
4178 XWINDOW (new)->vchild = window;
4179 }
4180 }
4181 else
4182 {
4183 int window_safe_width = window_min_size_2 (o, 1, 0);
4184
4185 if (size_int < window_safe_width)
4186 error ("Window width %d too small (after splitting)", size_int);
4187 if (size_int + window_safe_width > XFASTINT (o->total_cols))
4188 error ("Window width %d too small (after splitting)",
4189 XFASTINT (o->total_cols) - size_int);
4190 if (NILP (o->parent)
4191 || NILP (XWINDOW (o->parent)->hchild))
4192 {
4193 make_dummy_parent (window);
4194 new = o->parent;
4195 XWINDOW (new)->hchild = window;
4196 }
4197 }
4198
4199 /* Now we know that window's parent is a vertical combination
4200 if we are dividing vertically, or a horizontal combination
4201 if we are making side-by-side windows */
4202
4203 windows_or_buffers_changed++;
4204 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
4205 new = make_window ();
4206 p = XWINDOW (new);
4207
4208 p->frame = o->frame;
4209 p->next = o->next;
4210 if (!NILP (p->next))
4211 XWINDOW (p->next)->prev = new;
4212 p->prev = window;
4213 o->next = new;
4214 p->parent = o->parent;
4215 p->buffer = Qt;
4216 p->window_end_valid = Qnil;
4217 bzero (&p->last_cursor, sizeof p->last_cursor);
4218
4219 /* Duplicate special geometry settings. */
4220
4221 p->left_margin_cols = o->left_margin_cols;
4222 p->right_margin_cols = o->right_margin_cols;
4223 p->left_fringe_width = o->left_fringe_width;
4224 p->right_fringe_width = o->right_fringe_width;
4225 p->fringes_outside_margins = o->fringes_outside_margins;
4226 p->scroll_bar_width = o->scroll_bar_width;
4227 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
4228
4229 /* Apportion the available frame space among the two new windows */
4230
4231 if (!NILP (horflag))
4232 {
4233 p->total_lines = o->total_lines;
4234 p->top_line = o->top_line;
4235 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
4236 XSETFASTINT (o->total_cols, size_int);
4237 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
4238 adjust_window_margins (p);
4239 adjust_window_margins (o);
4240 }
4241 else
4242 {
4243 p->left_col = o->left_col;
4244 p->total_cols = o->total_cols;
4245 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
4246 XSETFASTINT (o->total_lines, size_int);
4247 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
4248 }
4249
4250 /* Adjust glyph matrices. */
4251 adjust_glyphs (fo);
4252
4253 Fset_window_buffer (new, o->buffer, Qt);
4254 return new;
4255 }
4256 \f
4257 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
4258 doc: /* Make current window ARG lines bigger.
4259 From program, optional second arg non-nil means grow sideways ARG columns.
4260 Interactively, if an argument is not given, make the window one line bigger.
4261 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
4262 This function can delete windows, even the second window, if they get
4263 too small. */)
4264 (arg, horizontal)
4265 Lisp_Object arg, horizontal;
4266 {
4267 CHECK_NUMBER (arg);
4268 enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
4269
4270 run_window_configuration_change_hook (SELECTED_FRAME ());
4271
4272 return Qnil;
4273 }
4274
4275 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
4276 doc: /* Make current window ARG lines smaller.
4277 From program, optional second arg non-nil means shrink sideways arg columns.
4278 Interactively, if an argument is not given, make the window one line smaller.
4279 Only siblings to the right or below are changed. */)
4280 (arg, side)
4281 Lisp_Object arg, side;
4282 {
4283 CHECK_NUMBER (arg);
4284 enlarge_window (selected_window, -XINT (arg), !NILP (side));
4285
4286 run_window_configuration_change_hook (SELECTED_FRAME ());
4287
4288 return Qnil;
4289 }
4290
4291 int
4292 window_height (window)
4293 Lisp_Object window;
4294 {
4295 register struct window *p = XWINDOW (window);
4296 return WINDOW_TOTAL_LINES (p);
4297 }
4298
4299 int
4300 window_width (window)
4301 Lisp_Object window;
4302 {
4303 register struct window *p = XWINDOW (window);
4304 return WINDOW_TOTAL_COLS (p);
4305 }
4306
4307
4308 #define CURBEG(w) \
4309 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4310
4311 #define CURSIZE(w) \
4312 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4313
4314
4315 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4316 horizontally; zero means do it vertically.
4317
4318 Siblings of the selected window are resized to fulfill the size
4319 request. If they become too small in the process, they may be
4320 deleted. */
4321
4322 static void
4323 enlarge_window (window, delta, horiz_flag)
4324 Lisp_Object window;
4325 int delta, horiz_flag;
4326 {
4327 Lisp_Object parent, next, prev;
4328 struct window *p;
4329 Lisp_Object *sizep;
4330 int maximum;
4331 int (*sizefun) P_ ((Lisp_Object))
4332 = horiz_flag ? window_width : window_height;
4333 void (*setsizefun) P_ ((Lisp_Object, int, int))
4334 = (horiz_flag ? set_window_width : set_window_height);
4335
4336 /* Give up if this window cannot be resized. */
4337 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4338 error ("Window is not resizable");
4339
4340 /* Find the parent of the selected window. */
4341 while (1)
4342 {
4343 p = XWINDOW (window);
4344 parent = p->parent;
4345
4346 if (NILP (parent))
4347 {
4348 if (horiz_flag)
4349 error ("No other window to side of this one");
4350 break;
4351 }
4352
4353 if (horiz_flag
4354 ? !NILP (XWINDOW (parent)->hchild)
4355 : !NILP (XWINDOW (parent)->vchild))
4356 break;
4357
4358 window = parent;
4359 }
4360
4361 sizep = &CURSIZE (window);
4362
4363 {
4364 register int maxdelta;
4365
4366 /* Compute the maximum size increment this window can have. */
4367
4368 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4369 /* This is a main window followed by a minibuffer. */
4370 : !NILP (p->next) ? ((*sizefun) (p->next)
4371 - window_min_size (XWINDOW (p->next),
4372 horiz_flag, 0, 0, 0))
4373 /* This is a minibuffer following a main window. */
4374 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4375 - window_min_size (XWINDOW (p->prev),
4376 horiz_flag, 0, 0, 0))
4377 /* This is a frame with only one window, a minibuffer-only
4378 or a minibufferless frame. */
4379 : (delta = 0));
4380
4381 if (delta > maxdelta)
4382 /* This case traps trying to make the minibuffer
4383 the full frame, or make the only window aside from the
4384 minibuffer the full frame. */
4385 delta = maxdelta;
4386 }
4387
4388 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
4389 horiz_flag, 0, 0, 0))
4390 {
4391 delete_window (window);
4392 return;
4393 }
4394
4395 if (delta == 0)
4396 return;
4397
4398 /* Find the total we can get from other siblings without deleting them. */
4399 maximum = 0;
4400 for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
4401 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4402 horiz_flag, 0, 0, 0);
4403 for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
4404 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4405 horiz_flag, 0, 0, 0);
4406
4407 /* If we can get it all from them without deleting them, do so. */
4408 if (delta <= maximum)
4409 {
4410 Lisp_Object first_unaffected;
4411 Lisp_Object first_affected;
4412 int fixed_p;
4413
4414 next = p->next;
4415 prev = p->prev;
4416 first_affected = window;
4417 /* Look at one sibling at a time,
4418 moving away from this window in both directions alternately,
4419 and take as much as we can get without deleting that sibling. */
4420 while (delta != 0
4421 && (!NILP (next) || !NILP (prev)))
4422 {
4423 if (! NILP (next))
4424 {
4425 int this_one = ((*sizefun) (next)
4426 - window_min_size (XWINDOW (next), horiz_flag,
4427 0, 0, &fixed_p));
4428 if (!fixed_p)
4429 {
4430 if (this_one > delta)
4431 this_one = delta;
4432
4433 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4434 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4435
4436 delta -= this_one;
4437 }
4438
4439 next = XWINDOW (next)->next;
4440 }
4441
4442 if (delta == 0)
4443 break;
4444
4445 if (! NILP (prev))
4446 {
4447 int this_one = ((*sizefun) (prev)
4448 - window_min_size (XWINDOW (prev), horiz_flag,
4449 0, 0, &fixed_p));
4450 if (!fixed_p)
4451 {
4452 if (this_one > delta)
4453 this_one = delta;
4454
4455 first_affected = prev;
4456
4457 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4458 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4459
4460 delta -= this_one;
4461 }
4462
4463 prev = XWINDOW (prev)->prev;
4464 }
4465 }
4466
4467 xassert (delta == 0);
4468
4469 /* Now recalculate the edge positions of all the windows affected,
4470 based on the new sizes. */
4471 first_unaffected = next;
4472 prev = first_affected;
4473 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4474 prev = next, next = XWINDOW (next)->next)
4475 {
4476 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4477 /* This does not change size of NEXT,
4478 but it propagates the new top edge to its children */
4479 (*setsizefun) (next, (*sizefun) (next), 0);
4480 }
4481 }
4482 else
4483 {
4484 register int delta1;
4485 register int opht = (*sizefun) (parent);
4486
4487 if (opht <= XINT (*sizep) + delta)
4488 {
4489 /* If trying to grow this window to or beyond size of the parent,
4490 just delete all the sibling windows. */
4491 Lisp_Object start, tem, next;
4492
4493 start = XWINDOW (parent)->vchild;
4494 if (NILP (start))
4495 start = XWINDOW (parent)->hchild;
4496
4497 /* Delete any siblings that come after WINDOW. */
4498 tem = XWINDOW (window)->next;
4499 while (! NILP (tem))
4500 {
4501 next = XWINDOW (tem)->next;
4502 delete_window (tem);
4503 tem = next;
4504 }
4505
4506 /* Delete any siblings that come after WINDOW.
4507 Note that if START is not WINDOW, then WINDOW still
4508 has siblings, so WINDOW has not yet replaced its parent. */
4509 tem = start;
4510 while (! EQ (tem, window))
4511 {
4512 next = XWINDOW (tem)->next;
4513 delete_window (tem);
4514 tem = next;
4515 }
4516 }
4517 else
4518 {
4519 /* Otherwise, make delta1 just right so that if we add
4520 delta1 lines to this window and to the parent, and then
4521 shrink the parent back to its original size, the new
4522 proportional size of this window will increase by delta.
4523
4524 The function size_window will compute the new height h'
4525 of the window from delta1 as:
4526
4527 e = delta1/n
4528 x = delta1 - delta1/n * n for the 1st resizable child
4529 h' = h + e + x
4530
4531 where n is the number of children that can be resized.
4532 We can ignore x by choosing a delta1 that is a multiple of
4533 n. We want the height of this window to come out as
4534
4535 h' = h + delta
4536
4537 So, delta1 must be
4538
4539 h + e = h + delta
4540 delta1/n = delta
4541 delta1 = n * delta.
4542
4543 The number of children n equals the number of resizable
4544 children of this window + 1 because we know window itself
4545 is resizable (otherwise we would have signalled an error).
4546
4547 This reasoning is not correct when other windows become too
4548 small and shrink_windows refuses to delete them. Below we
4549 use resize_proportionally to work around this problem. */
4550
4551 struct window *w = XWINDOW (window);
4552 Lisp_Object s;
4553 int n = 1;
4554
4555 for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next)
4556 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4557 ++n;
4558 for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev)
4559 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4560 ++n;
4561
4562 delta1 = n * delta;
4563
4564 /* Add delta1 lines or columns to this window, and to the parent,
4565 keeping things consistent while not affecting siblings. */
4566 XSETINT (CURSIZE (parent), opht + delta1);
4567 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4568
4569 /* Squeeze out delta1 lines or columns from our parent,
4570 shrinking this window and siblings proportionately. This
4571 brings parent back to correct size. Delta1 was calculated
4572 so this makes this window the desired size, taking it all
4573 out of the siblings.
4574
4575 Temporarily set resize_proportionally to Qt to assure that,
4576 if necessary, shrink_windows deletes smaller windows rather
4577 than shrink this window. */
4578 w->resize_proportionally = Qt;
4579 (*setsizefun) (parent, opht, 0);
4580 w->resize_proportionally = Qnil;
4581 }
4582 }
4583
4584 XSETFASTINT (p->last_modified, 0);
4585 XSETFASTINT (p->last_overlay_modified, 0);
4586
4587 /* Adjust glyph matrices. */
4588 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4589 }
4590
4591
4592 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4593 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4594 zero means adjust the height, moving the bottom edge.
4595
4596 Following siblings of the selected window are resized to fulfill
4597 the size request. If they become too small in the process, they
4598 are not deleted; instead, we signal an error. */
4599
4600 static void
4601 adjust_window_trailing_edge (window, delta, horiz_flag)
4602 Lisp_Object window;
4603 int delta, horiz_flag;
4604 {
4605 Lisp_Object parent, child;
4606 struct window *p;
4607 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4608 int delcount = window_deletion_count;
4609
4610 CHECK_WINDOW (window);
4611
4612 /* Give up if this window cannot be resized. */
4613 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4614 error ("Window is not resizable");
4615
4616 while (1)
4617 {
4618 Lisp_Object first_parallel = Qnil;
4619
4620 if (NILP (window))
4621 {
4622 /* This happens if WINDOW on the previous iteration was
4623 at top level of the window tree. */
4624 Fset_window_configuration (old_config);
4625 error ("Specified window edge is fixed");
4626 }
4627
4628 p = XWINDOW (window);
4629 parent = p->parent;
4630
4631 /* See if this level has windows in parallel in the specified
4632 direction. If so, set FIRST_PARALLEL to the first one. */
4633 if (horiz_flag)
4634 {
4635 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4636 first_parallel = XWINDOW (parent)->vchild;
4637 else if (NILP (parent) && !NILP (p->next))
4638 {
4639 /* Handle the vertical chain of main window and minibuffer
4640 which has no parent. */
4641 first_parallel = window;
4642 while (! NILP (XWINDOW (first_parallel)->prev))
4643 first_parallel = XWINDOW (first_parallel)->prev;
4644 }
4645 }
4646 else
4647 {
4648 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4649 first_parallel = XWINDOW (parent)->hchild;
4650 }
4651
4652 /* If this level's succession is in the desired dimension,
4653 and this window is the last one, and there is no higher level,
4654 its trailing edge is fixed. */
4655 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4656 && NILP (parent))
4657 {
4658 Fset_window_configuration (old_config);
4659 error ("Specified window edge is fixed");
4660 }
4661
4662 /* Don't make this window too small. */
4663 if (XINT (CURSIZE (window)) + delta
4664 < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
4665 {
4666 Fset_window_configuration (old_config);
4667 error ("Cannot adjust window size as specified");
4668 }
4669
4670 /* Clear out some redisplay caches. */
4671 XSETFASTINT (p->last_modified, 0);
4672 XSETFASTINT (p->last_overlay_modified, 0);
4673
4674 /* Adjust this window's edge. */
4675 XSETINT (CURSIZE (window),
4676 XINT (CURSIZE (window)) + delta);
4677
4678 /* If this window has following siblings in the desired dimension,
4679 make them smaller, and exit the loop.
4680
4681 (If we reach the top of the tree and can never do this,
4682 we will fail and report an error, above.) */
4683 if (NILP (first_parallel))
4684 {
4685 if (!NILP (p->next))
4686 {
4687 /* This may happen for the minibuffer. In that case
4688 the window_deletion_count check below does not work. */
4689 if (XINT (CURSIZE (p->next)) - delta <= 0)
4690 {
4691 Fset_window_configuration (old_config);
4692 error ("Cannot adjust window size as specified");
4693 }
4694
4695 XSETINT (CURBEG (p->next),
4696 XINT (CURBEG (p->next)) + delta);
4697 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4698 horiz_flag, 0, 1, 0);
4699 break;
4700 }
4701 }
4702 else
4703 /* Here we have a chain of parallel siblings, in the other dimension.
4704 Change the size of the other siblings. */
4705 for (child = first_parallel;
4706 ! NILP (child);
4707 child = XWINDOW (child)->next)
4708 if (! EQ (child, window))
4709 size_window (child, XINT (CURSIZE (child)) + delta,
4710 horiz_flag, 0, 0, 1);
4711
4712 window = parent;
4713 }
4714
4715 /* If we made a window so small it got deleted,
4716 we failed. Report failure. */
4717 if (delcount != window_deletion_count)
4718 {
4719 Fset_window_configuration (old_config);
4720 error ("Cannot adjust window size as specified");
4721 }
4722
4723 /* Adjust glyph matrices. */
4724 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4725 }
4726
4727 #undef CURBEG
4728 #undef CURSIZE
4729
4730 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4731 Sadjust_window_trailing_edge, 3, 3, 0,
4732 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4733 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4734 Otherwise, adjust the height, moving the bottom edge.
4735
4736 Following siblings of the selected window are resized to fulfill
4737 the size request. If they become too small in the process, they
4738 are not deleted; instead, we signal an error. */)
4739 (window, delta, horizontal)
4740 Lisp_Object window, delta, horizontal;
4741 {
4742 CHECK_NUMBER (delta);
4743 if (NILP (window))
4744 window = selected_window;
4745 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4746
4747 run_window_configuration_change_hook
4748 (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4749
4750 return Qnil;
4751 }
4752
4753
4754 \f
4755 /***********************************************************************
4756 Resizing Mini-Windows
4757 ***********************************************************************/
4758
4759 static void shrink_window_lowest_first P_ ((struct window *, int));
4760
4761 enum save_restore_action
4762 {
4763 CHECK_ORIG_SIZES,
4764 SAVE_ORIG_SIZES,
4765 RESTORE_ORIG_SIZES
4766 };
4767
4768 static int save_restore_orig_size P_ ((struct window *,
4769 enum save_restore_action));
4770
4771 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4772 from lowest windows first. */
4773
4774 static void
4775 shrink_window_lowest_first (w, height)
4776 struct window *w;
4777 int height;
4778 {
4779 struct window *c;
4780 Lisp_Object child;
4781 int old_height;
4782
4783 xassert (!MINI_WINDOW_P (w));
4784
4785 /* Set redisplay hints. */
4786 XSETFASTINT (w->last_modified, 0);
4787 XSETFASTINT (w->last_overlay_modified, 0);
4788 windows_or_buffers_changed++;
4789 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4790
4791 old_height = XFASTINT (w->total_lines);
4792 XSETFASTINT (w->total_lines, height);
4793
4794 if (!NILP (w->hchild))
4795 {
4796 for (child = w->hchild; !NILP (child); child = c->next)
4797 {
4798 c = XWINDOW (child);
4799 c->top_line = w->top_line;
4800 shrink_window_lowest_first (c, height);
4801 }
4802 }
4803 else if (!NILP (w->vchild))
4804 {
4805 Lisp_Object last_child;
4806 int delta = old_height - height;
4807 int last_top;
4808
4809 last_child = Qnil;
4810
4811 /* Find the last child. We are taking space from lowest windows
4812 first, so we iterate over children from the last child
4813 backwards. */
4814 for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
4815 last_child = child;
4816
4817 /* Size children down to their safe heights. */
4818 for (child = last_child; delta && !NILP (child); child = c->prev)
4819 {
4820 int this_one;
4821
4822 c = XWINDOW (child);
4823 this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
4824
4825 if (this_one > delta)
4826 this_one = delta;
4827
4828 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4829 delta -= this_one;
4830 }
4831
4832 /* Compute new positions. */
4833 last_top = XINT (w->top_line);
4834 for (child = w->vchild; !NILP (child); child = c->next)
4835 {
4836 c = XWINDOW (child);
4837 c->top_line = make_number (last_top);
4838 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4839 last_top += XFASTINT (c->total_lines);
4840 }
4841 }
4842 }
4843
4844
4845 /* Save, restore, or check positions and sizes in the window tree
4846 rooted at W. ACTION says what to do.
4847
4848 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4849 orig_total_lines members are valid for all windows in the window
4850 tree. Value is non-zero if they are valid.
4851
4852 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4853 orig_top_line and orig_total_lines for all windows in the tree.
4854
4855 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4856 stored in orig_top_line and orig_total_lines for all windows. */
4857
4858 static int
4859 save_restore_orig_size (w, action)
4860 struct window *w;
4861 enum save_restore_action action;
4862 {
4863 int success_p = 1;
4864
4865 while (w)
4866 {
4867 if (!NILP (w->hchild))
4868 {
4869 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4870 success_p = 0;
4871 }
4872 else if (!NILP (w->vchild))
4873 {
4874 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4875 success_p = 0;
4876 }
4877
4878 switch (action)
4879 {
4880 case CHECK_ORIG_SIZES:
4881 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4882 return 0;
4883 break;
4884
4885 case SAVE_ORIG_SIZES:
4886 w->orig_top_line = w->top_line;
4887 w->orig_total_lines = w->total_lines;
4888 XSETFASTINT (w->last_modified, 0);
4889 XSETFASTINT (w->last_overlay_modified, 0);
4890 break;
4891
4892 case RESTORE_ORIG_SIZES:
4893 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4894 w->top_line = w->orig_top_line;
4895 w->total_lines = w->orig_total_lines;
4896 w->orig_total_lines = w->orig_top_line = Qnil;
4897 XSETFASTINT (w->last_modified, 0);
4898 XSETFASTINT (w->last_overlay_modified, 0);
4899 break;
4900
4901 default:
4902 abort ();
4903 }
4904
4905 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4906 }
4907
4908 return success_p;
4909 }
4910
4911
4912 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4913 without deleting other windows. */
4914
4915 void
4916 grow_mini_window (w, delta)
4917 struct window *w;
4918 int delta;
4919 {
4920 struct frame *f = XFRAME (w->frame);
4921 struct window *root;
4922
4923 xassert (MINI_WINDOW_P (w));
4924 xassert (delta >= 0);
4925
4926 /* Compute how much we can enlarge the mini-window without deleting
4927 other windows. */
4928 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4929 if (delta)
4930 {
4931 int min_height = window_min_size (root, 0, 0, 0, 0);
4932 if (XFASTINT (root->total_lines) - delta < min_height)
4933 /* Note that the root window may already be smaller than
4934 min_height. */
4935 delta = max (0, XFASTINT (root->total_lines) - min_height);
4936 }
4937
4938 if (delta)
4939 {
4940 /* Save original window sizes and positions, if not already done. */
4941 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4942 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4943
4944 /* Shrink other windows. */
4945 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4946
4947 /* Grow the mini-window. */
4948 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4949 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4950 XSETFASTINT (w->last_modified, 0);
4951 XSETFASTINT (w->last_overlay_modified, 0);
4952
4953 adjust_glyphs (f);
4954 }
4955 }
4956
4957
4958 /* Shrink mini-window W. If there is recorded info about window sizes
4959 before a call to grow_mini_window, restore recorded window sizes.
4960 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4961 line. */
4962
4963 void
4964 shrink_mini_window (w)
4965 struct window *w;
4966 {
4967 struct frame *f = XFRAME (w->frame);
4968 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4969
4970 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4971 {
4972 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4973 adjust_glyphs (f);
4974 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4975 windows_or_buffers_changed = 1;
4976 }
4977 else if (XFASTINT (w->total_lines) > 1)
4978 {
4979 /* Distribute the additional lines of the mini-window
4980 among the other windows. */
4981 Lisp_Object window;
4982 XSETWINDOW (window, w);
4983 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4984 }
4985 }
4986
4987
4988 \f
4989 /* Mark window cursors off for all windows in the window tree rooted
4990 at W by setting their phys_cursor_on_p flag to zero. Called from
4991 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4992 the frame are cleared. */
4993
4994 void
4995 mark_window_cursors_off (w)
4996 struct window *w;
4997 {
4998 while (w)
4999 {
5000 if (!NILP (w->hchild))
5001 mark_window_cursors_off (XWINDOW (w->hchild));
5002 else if (!NILP (w->vchild))
5003 mark_window_cursors_off (XWINDOW (w->vchild));
5004 else
5005 w->phys_cursor_on_p = 0;
5006
5007 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5008 }
5009 }
5010
5011
5012 /* Return number of lines of text (not counting mode lines) in W. */
5013
5014 int
5015 window_internal_height (w)
5016 struct window *w;
5017 {
5018 int ht = XFASTINT (w->total_lines);
5019
5020 if (!MINI_WINDOW_P (w))
5021 {
5022 if (!NILP (w->parent)
5023 || !NILP (w->vchild)
5024 || !NILP (w->hchild)
5025 || !NILP (w->next)
5026 || !NILP (w->prev)
5027 || WINDOW_WANTS_MODELINE_P (w))
5028 --ht;
5029
5030 if (WINDOW_WANTS_HEADER_LINE_P (w))
5031 --ht;
5032 }
5033
5034 return ht;
5035 }
5036
5037
5038 /* Return the number of columns in W.
5039 Don't count columns occupied by scroll bars or the vertical bar
5040 separating W from the sibling to its right. */
5041
5042 int
5043 window_box_text_cols (w)
5044 struct window *w;
5045 {
5046 struct frame *f = XFRAME (WINDOW_FRAME (w));
5047 int width = XINT (w->total_cols);
5048
5049 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
5050 /* Scroll bars occupy a few columns. */
5051 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
5052 else if (!FRAME_WINDOW_P (f)
5053 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
5054 /* The column of `|' characters separating side-by-side windows
5055 occupies one column only. */
5056 width -= 1;
5057
5058 if (FRAME_WINDOW_P (f))
5059 /* On window-systems, fringes and display margins cannot be
5060 used for normal text. */
5061 width -= (WINDOW_FRINGE_COLS (w)
5062 + WINDOW_LEFT_MARGIN_COLS (w)
5063 + WINDOW_RIGHT_MARGIN_COLS (w));
5064
5065 return width;
5066 }
5067
5068 \f
5069 /************************************************************************
5070 Window Scrolling
5071 ***********************************************************************/
5072
5073 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
5074 N screen-fulls, which is defined as the height of the window minus
5075 next_screen_context_lines. If WHOLE is zero, scroll up N lines
5076 instead. Negative values of N mean scroll down. NOERROR non-zero
5077 means don't signal an error if we try to move over BEGV or ZV,
5078 respectively. */
5079
5080 static void
5081 window_scroll (window, n, whole, noerror)
5082 Lisp_Object window;
5083 int n;
5084 int whole;
5085 int noerror;
5086 {
5087 immediate_quit = 1;
5088
5089 /* If we must, use the pixel-based version which is much slower than
5090 the line-based one but can handle varying line heights. */
5091 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
5092 window_scroll_pixel_based (window, n, whole, noerror);
5093 else
5094 window_scroll_line_based (window, n, whole, noerror);
5095
5096 immediate_quit = 0;
5097 }
5098
5099
5100 /* Implementation of window_scroll that works based on pixel line
5101 heights. See the comment of window_scroll for parameter
5102 descriptions. */
5103
5104 static void
5105 window_scroll_pixel_based (window, n, whole, noerror)
5106 Lisp_Object window;
5107 int n;
5108 int whole;
5109 int noerror;
5110 {
5111 struct it it;
5112 struct window *w = XWINDOW (window);
5113 struct text_pos start;
5114 int this_scroll_margin;
5115 /* True if we fiddled the window vscroll field without really scrolling. */
5116 int vscrolled = 0;
5117 int x, y, rtop, rbot, rowh, vpos;
5118
5119 SET_TEXT_POS_FROM_MARKER (start, w->start);
5120
5121 /* If PT is not visible in WINDOW, move back one half of
5122 the screen. Allow PT to be partially visible, otherwise
5123 something like (scroll-down 1) with PT in the line before
5124 the partially visible one would recenter. */
5125
5126 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
5127 {
5128 /* Move backward half the height of the window. Performance note:
5129 vmotion used here is about 10% faster, but would give wrong
5130 results for variable height lines. */
5131 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5132 it.current_y = it.last_visible_y;
5133 move_it_vertically_backward (&it, window_box_height (w) / 2);
5134
5135 /* The function move_iterator_vertically may move over more than
5136 the specified y-distance. If it->w is small, e.g. a
5137 mini-buffer window, we may end up in front of the window's
5138 display area. This is the case when Start displaying at the
5139 start of the line containing PT in this case. */
5140 if (it.current_y <= 0)
5141 {
5142 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5143 move_it_vertically_backward (&it, 0);
5144 it.current_y = 0;
5145 }
5146
5147 start = it.current.pos;
5148 }
5149 else if (auto_window_vscroll_p)
5150 {
5151 if (rtop || rbot) /* partially visible */
5152 {
5153 int px;
5154 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5155 if (whole)
5156 dy = max ((window_box_height (w)
5157 - next_screen_context_lines * dy),
5158 dy);
5159 dy *= n;
5160
5161 if (n < 0)
5162 {
5163 /* Only vscroll backwards if already vscrolled forwards. */
5164 if (w->vscroll < 0 && rtop > 0)
5165 {
5166 px = max (0, -w->vscroll - min (rtop, -dy));
5167 Fset_window_vscroll (window, make_number (px), Qt);
5168 return;
5169 }
5170 }
5171 if (n > 0)
5172 {
5173 /* Do vscroll if already vscrolled or only display line. */
5174 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
5175 {
5176 px = max (0, -w->vscroll + min (rbot, dy));
5177 Fset_window_vscroll (window, make_number (px), Qt);
5178 return;
5179 }
5180
5181 /* Maybe modify window start instead of scrolling. */
5182 if (rbot > 0 || w->vscroll < 0)
5183 {
5184 int spos;
5185
5186 Fset_window_vscroll (window, make_number (0), Qt);
5187 /* If there are other text lines above the current row,
5188 move window start to current row. Else to next row. */
5189 if (rbot > 0)
5190 spos = XINT (Fline_beginning_position (Qnil));
5191 else
5192 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
5193 set_marker_restricted (w->start, make_number (spos),
5194 w->buffer);
5195 w->start_at_line_beg = Qt;
5196 w->update_mode_line = Qt;
5197 XSETFASTINT (w->last_modified, 0);
5198 XSETFASTINT (w->last_overlay_modified, 0);
5199 /* Set force_start so that redisplay_window will run the
5200 window-scroll-functions. */
5201 w->force_start = Qt;
5202 return;
5203 }
5204 }
5205 }
5206 /* Cancel previous vscroll. */
5207 Fset_window_vscroll (window, make_number (0), Qt);
5208 }
5209
5210 /* If scroll_preserve_screen_position is non-nil, we try to set
5211 point in the same window line as it is now, so get that line. */
5212 if (!NILP (Vscroll_preserve_screen_position))
5213 {
5214 /* We preserve the goal pixel coordinate across consecutive
5215 calls to scroll-up or scroll-down. This avoids the
5216 possibility of point becoming "stuck" on a tall line when
5217 scrolling by one line. */
5218 if (window_scroll_pixel_based_preserve_y < 0
5219 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5220 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5221 {
5222 start_display (&it, w, start);
5223 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5224 window_scroll_pixel_based_preserve_y = it.current_y;
5225 window_scroll_pixel_based_preserve_x = it.current_x;
5226 }
5227 }
5228 else
5229 window_scroll_pixel_based_preserve_y
5230 = window_scroll_pixel_based_preserve_x = -1;
5231
5232 /* Move iterator it from start the specified distance forward or
5233 backward. The result is the new window start. */
5234 start_display (&it, w, start);
5235 if (whole)
5236 {
5237 int start_pos = IT_CHARPOS (it);
5238 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5239 dy = max ((window_box_height (w)
5240 - next_screen_context_lines * dy),
5241 dy) * n;
5242
5243 /* Note that move_it_vertically always moves the iterator to the
5244 start of a line. So, if the last line doesn't have a newline,
5245 we would end up at the start of the line ending at ZV. */
5246 if (dy <= 0)
5247 {
5248 move_it_vertically_backward (&it, -dy);
5249 /* Ensure we actually do move, e.g. in case we are currently
5250 looking at an image that is taller that the window height. */
5251 while (start_pos == IT_CHARPOS (it)
5252 && start_pos > BEGV)
5253 move_it_by_lines (&it, -1, 1);
5254 }
5255 else if (dy > 0)
5256 {
5257 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5258 MOVE_TO_POS | MOVE_TO_Y);
5259 /* Ensure we actually do move, e.g. in case we are currently
5260 looking at an image that is taller that the window height. */
5261 while (start_pos == IT_CHARPOS (it)
5262 && start_pos < ZV)
5263 move_it_by_lines (&it, 1, 1);
5264 }
5265 }
5266 else
5267 move_it_by_lines (&it, n, 1);
5268
5269 /* We failed if we find ZV is already on the screen (scrolling up,
5270 means there's nothing past the end), or if we can't start any
5271 earlier (scrolling down, means there's nothing past the top). */
5272 if ((n > 0 && IT_CHARPOS (it) == ZV)
5273 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5274 {
5275 if (IT_CHARPOS (it) == ZV)
5276 {
5277 if (it.current_y < it.last_visible_y
5278 && (it.current_y + it.max_ascent + it.max_descent
5279 > it.last_visible_y))
5280 {
5281 /* The last line was only partially visible, make it fully
5282 visible. */
5283 w->vscroll = (it.last_visible_y
5284 - it.current_y + it.max_ascent + it.max_descent);
5285 adjust_glyphs (it.f);
5286 }
5287 else if (noerror)
5288 return;
5289 else if (n < 0) /* could happen with empty buffers */
5290 xsignal0 (Qbeginning_of_buffer);
5291 else
5292 xsignal0 (Qend_of_buffer);
5293 }
5294 else
5295 {
5296 if (w->vscroll != 0)
5297 /* The first line was only partially visible, make it fully
5298 visible. */
5299 w->vscroll = 0;
5300 else if (noerror)
5301 return;
5302 else
5303 xsignal0 (Qbeginning_of_buffer);
5304 }
5305
5306 /* If control gets here, then we vscrolled. */
5307
5308 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5309
5310 /* Don't try to change the window start below. */
5311 vscrolled = 1;
5312 }
5313
5314 if (! vscrolled)
5315 {
5316 int pos = IT_CHARPOS (it);
5317 int bytepos;
5318
5319 /* If in the middle of a multi-glyph character move forward to
5320 the next character. */
5321 if (in_display_vector_p (&it))
5322 {
5323 ++pos;
5324 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5325 }
5326
5327 /* Set the window start, and set up the window for redisplay. */
5328 set_marker_restricted (w->start, make_number (pos),
5329 w->buffer);
5330 bytepos = XMARKER (w->start)->bytepos;
5331 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5332 ? Qt : Qnil);
5333 w->update_mode_line = Qt;
5334 XSETFASTINT (w->last_modified, 0);
5335 XSETFASTINT (w->last_overlay_modified, 0);
5336 /* Set force_start so that redisplay_window will run the
5337 window-scroll-functions. */
5338 w->force_start = Qt;
5339 }
5340
5341 /* The rest of this function uses current_y in a nonstandard way,
5342 not including the height of the header line if any. */
5343 it.current_y = it.vpos = 0;
5344
5345 /* Move PT out of scroll margins.
5346 This code wants current_y to be zero at the window start position
5347 even if there is a header line. */
5348 this_scroll_margin = max (0, scroll_margin);
5349 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5350 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5351
5352 if (n > 0)
5353 {
5354 /* We moved the window start towards ZV, so PT may be now
5355 in the scroll margin at the top. */
5356 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5357 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5358 && (NILP (Vscroll_preserve_screen_position)
5359 || EQ (Vscroll_preserve_screen_position, Qt)))
5360 /* We found PT at a legitimate height. Leave it alone. */
5361 ;
5362 else if (window_scroll_pixel_based_preserve_y >= 0)
5363 {
5364 /* If we have a header line, take account of it.
5365 This is necessary because we set it.current_y to 0, above. */
5366 move_it_to (&it, -1,
5367 window_scroll_pixel_based_preserve_x,
5368 window_scroll_pixel_based_preserve_y
5369 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5370 -1, MOVE_TO_Y | MOVE_TO_X);
5371 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5372 }
5373 else
5374 {
5375 while (it.current_y < this_scroll_margin)
5376 {
5377 int prev = it.current_y;
5378 move_it_by_lines (&it, 1, 1);
5379 if (prev == it.current_y)
5380 break;
5381 }
5382 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5383 }
5384 }
5385 else if (n < 0)
5386 {
5387 int charpos, bytepos;
5388 int partial_p;
5389
5390 /* Save our position, for the
5391 window_scroll_pixel_based_preserve_y case. */
5392 charpos = IT_CHARPOS (it);
5393 bytepos = IT_BYTEPOS (it);
5394
5395 /* We moved the window start towards BEGV, so PT may be now
5396 in the scroll margin at the bottom. */
5397 move_it_to (&it, PT, -1,
5398 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5399 - this_scroll_margin - 1),
5400 -1,
5401 MOVE_TO_POS | MOVE_TO_Y);
5402
5403 /* Save our position, in case it's correct. */
5404 charpos = IT_CHARPOS (it);
5405 bytepos = IT_BYTEPOS (it);
5406
5407 /* See if point is on a partially visible line at the end. */
5408 if (it.what == IT_EOB)
5409 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5410 else
5411 {
5412 move_it_by_lines (&it, 1, 1);
5413 partial_p = it.current_y > it.last_visible_y;
5414 }
5415
5416 if (charpos == PT && !partial_p
5417 && (NILP (Vscroll_preserve_screen_position)
5418 || EQ (Vscroll_preserve_screen_position, Qt)))
5419 /* We found PT before we found the display margin, so PT is ok. */
5420 ;
5421 else if (window_scroll_pixel_based_preserve_y >= 0)
5422 {
5423 SET_TEXT_POS_FROM_MARKER (start, w->start);
5424 start_display (&it, w, start);
5425 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5426 here because we called start_display again and did not
5427 alter it.current_y this time. */
5428 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5429 window_scroll_pixel_based_preserve_y, -1,
5430 MOVE_TO_Y | MOVE_TO_X);
5431 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5432 }
5433 else
5434 {
5435 if (partial_p)
5436 /* The last line was only partially visible, so back up two
5437 lines to make sure we're on a fully visible line. */
5438 {
5439 move_it_by_lines (&it, -2, 0);
5440 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5441 }
5442 else
5443 /* No, the position we saved is OK, so use it. */
5444 SET_PT_BOTH (charpos, bytepos);
5445 }
5446 }
5447 }
5448
5449
5450 /* Implementation of window_scroll that works based on screen lines.
5451 See the comment of window_scroll for parameter descriptions. */
5452
5453 static void
5454 window_scroll_line_based (window, n, whole, noerror)
5455 Lisp_Object window;
5456 int n;
5457 int whole;
5458 int noerror;
5459 {
5460 register struct window *w = XWINDOW (window);
5461 register int opoint = PT, opoint_byte = PT_BYTE;
5462 register int pos, pos_byte;
5463 register int ht = window_internal_height (w);
5464 register Lisp_Object tem;
5465 int lose;
5466 Lisp_Object bolp;
5467 int startpos;
5468 Lisp_Object original_pos = Qnil;
5469
5470 /* If scrolling screen-fulls, compute the number of lines to
5471 scroll from the window's height. */
5472 if (whole)
5473 n *= max (1, ht - next_screen_context_lines);
5474
5475 startpos = marker_position (w->start);
5476
5477 if (!NILP (Vscroll_preserve_screen_position))
5478 {
5479 if (window_scroll_preserve_vpos <= 0
5480 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5481 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5482 {
5483 struct position posit
5484 = *compute_motion (startpos, 0, 0, 0,
5485 PT, ht, 0,
5486 -1, XINT (w->hscroll),
5487 0, w);
5488 window_scroll_preserve_vpos = posit.vpos;
5489 window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
5490 }
5491
5492 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5493 make_number (window_scroll_preserve_vpos));
5494 }
5495
5496 XSETFASTINT (tem, PT);
5497 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5498
5499 if (NILP (tem))
5500 {
5501 Fvertical_motion (make_number (- (ht / 2)), window);
5502 startpos = PT;
5503 }
5504
5505 SET_PT (startpos);
5506 lose = n < 0 && PT == BEGV;
5507 Fvertical_motion (make_number (n), window);
5508 pos = PT;
5509 pos_byte = PT_BYTE;
5510 bolp = Fbolp ();
5511 SET_PT_BOTH (opoint, opoint_byte);
5512
5513 if (lose)
5514 {
5515 if (noerror)
5516 return;
5517 else
5518 xsignal0 (Qbeginning_of_buffer);
5519 }
5520
5521 if (pos < ZV)
5522 {
5523 int this_scroll_margin = scroll_margin;
5524
5525 /* Don't use a scroll margin that is negative or too large. */
5526 if (this_scroll_margin < 0)
5527 this_scroll_margin = 0;
5528
5529 if (XINT (w->total_lines) < 4 * scroll_margin)
5530 this_scroll_margin = XINT (w->total_lines) / 4;
5531
5532 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5533 w->start_at_line_beg = bolp;
5534 w->update_mode_line = Qt;
5535 XSETFASTINT (w->last_modified, 0);
5536 XSETFASTINT (w->last_overlay_modified, 0);
5537 /* Set force_start so that redisplay_window will run
5538 the window-scroll-functions. */
5539 w->force_start = Qt;
5540
5541 if (!NILP (Vscroll_preserve_screen_position)
5542 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5543 {
5544 SET_PT_BOTH (pos, pos_byte);
5545 Fvertical_motion (original_pos, window);
5546 }
5547 /* If we scrolled forward, put point enough lines down
5548 that it is outside the scroll margin. */
5549 else if (n > 0)
5550 {
5551 int top_margin;
5552
5553 if (this_scroll_margin > 0)
5554 {
5555 SET_PT_BOTH (pos, pos_byte);
5556 Fvertical_motion (make_number (this_scroll_margin), window);
5557 top_margin = PT;
5558 }
5559 else
5560 top_margin = pos;
5561
5562 if (top_margin <= opoint)
5563 SET_PT_BOTH (opoint, opoint_byte);
5564 else if (!NILP (Vscroll_preserve_screen_position))
5565 {
5566 SET_PT_BOTH (pos, pos_byte);
5567 Fvertical_motion (original_pos, window);
5568 }
5569 else
5570 SET_PT (top_margin);
5571 }
5572 else if (n < 0)
5573 {
5574 int bottom_margin;
5575
5576 /* If we scrolled backward, put point near the end of the window
5577 but not within the scroll margin. */
5578 SET_PT_BOTH (pos, pos_byte);
5579 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5580 if (XFASTINT (tem) == ht - this_scroll_margin)
5581 bottom_margin = PT;
5582 else
5583 bottom_margin = PT + 1;
5584
5585 if (bottom_margin > opoint)
5586 SET_PT_BOTH (opoint, opoint_byte);
5587 else
5588 {
5589 if (!NILP (Vscroll_preserve_screen_position))
5590 {
5591 SET_PT_BOTH (pos, pos_byte);
5592 Fvertical_motion (original_pos, window);
5593 }
5594 else
5595 Fvertical_motion (make_number (-1), window);
5596 }
5597 }
5598 }
5599 else
5600 {
5601 if (noerror)
5602 return;
5603 else
5604 xsignal0 (Qend_of_buffer);
5605 }
5606 }
5607
5608
5609 /* Scroll selected_window up or down. If N is nil, scroll a
5610 screen-full which is defined as the height of the window minus
5611 next_screen_context_lines. If N is the symbol `-', scroll.
5612 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5613 up. This is the guts of Fscroll_up and Fscroll_down. */
5614
5615 static void
5616 scroll_command (n, direction)
5617 Lisp_Object n;
5618 int direction;
5619 {
5620 int count = SPECPDL_INDEX ();
5621
5622 xassert (eabs (direction) == 1);
5623
5624 /* If selected window's buffer isn't current, make it current for
5625 the moment. But don't screw up if window_scroll gets an error. */
5626 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5627 {
5628 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5629 Fset_buffer (XWINDOW (selected_window)->buffer);
5630
5631 /* Make redisplay consider other windows than just selected_window. */
5632 ++windows_or_buffers_changed;
5633 }
5634
5635 if (NILP (n))
5636 window_scroll (selected_window, direction, 1, 0);
5637 else if (EQ (n, Qminus))
5638 window_scroll (selected_window, -direction, 1, 0);
5639 else
5640 {
5641 n = Fprefix_numeric_value (n);
5642 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5643 }
5644
5645 unbind_to (count, Qnil);
5646 }
5647
5648 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5649 doc: /* Scroll text of current window upward ARG lines.
5650 If ARG is omitted or nil, scroll upward by a near full screen.
5651 A near full screen is `next-screen-context-lines' less than a full screen.
5652 Negative ARG means scroll downward.
5653 If ARG is the atom `-', scroll downward by nearly full screen.
5654 When calling from a program, supply as argument a number, nil, or `-'. */)
5655 (arg)
5656 Lisp_Object arg;
5657 {
5658 scroll_command (arg, 1);
5659 return Qnil;
5660 }
5661
5662 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5663 doc: /* Scroll text of current window down ARG lines.
5664 If ARG is omitted or nil, scroll down by a near full screen.
5665 A near full screen is `next-screen-context-lines' less than a full screen.
5666 Negative ARG means scroll upward.
5667 If ARG is the atom `-', scroll upward by nearly full screen.
5668 When calling from a program, supply as argument a number, nil, or `-'. */)
5669 (arg)
5670 Lisp_Object arg;
5671 {
5672 scroll_command (arg, -1);
5673 return Qnil;
5674 }
5675 \f
5676 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5677 doc: /* Return the other window for \"other window scroll\" commands.
5678 If `other-window-scroll-buffer' is non-nil, a window
5679 showing that buffer is used.
5680 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5681 specifies the window. This takes precedence over
5682 `other-window-scroll-buffer'. */)
5683 ()
5684 {
5685 Lisp_Object window;
5686
5687 if (MINI_WINDOW_P (XWINDOW (selected_window))
5688 && !NILP (Vminibuf_scroll_window))
5689 window = Vminibuf_scroll_window;
5690 /* If buffer is specified, scroll that buffer. */
5691 else if (!NILP (Vother_window_scroll_buffer))
5692 {
5693 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5694 if (NILP (window))
5695 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5696 }
5697 else
5698 {
5699 /* Nothing specified; look for a neighboring window on the same
5700 frame. */
5701 window = Fnext_window (selected_window, Qnil, Qnil);
5702
5703 if (EQ (window, selected_window))
5704 /* That didn't get us anywhere; look for a window on another
5705 visible frame. */
5706 do
5707 window = Fnext_window (window, Qnil, Qt);
5708 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5709 && ! EQ (window, selected_window));
5710 }
5711
5712 CHECK_LIVE_WINDOW (window);
5713
5714 if (EQ (window, selected_window))
5715 error ("There is no other window");
5716
5717 return window;
5718 }
5719
5720 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5721 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5722 A near full screen is `next-screen-context-lines' less than a full screen.
5723 The next window is the one below the current one; or the one at the top
5724 if the current one is at the bottom. Negative ARG means scroll downward.
5725 If ARG is the atom `-', scroll downward by nearly full screen.
5726 When calling from a program, supply as argument a number, nil, or `-'.
5727
5728 If `other-window-scroll-buffer' is non-nil, scroll the window
5729 showing that buffer, popping the buffer up if necessary.
5730 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5731 specifies the window to scroll. This takes precedence over
5732 `other-window-scroll-buffer'. */)
5733 (arg)
5734 Lisp_Object arg;
5735 {
5736 Lisp_Object window;
5737 struct window *w;
5738 int count = SPECPDL_INDEX ();
5739
5740 window = Fother_window_for_scrolling ();
5741 w = XWINDOW (window);
5742
5743 /* Don't screw up if window_scroll gets an error. */
5744 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5745 ++windows_or_buffers_changed;
5746
5747 Fset_buffer (w->buffer);
5748 SET_PT (marker_position (w->pointm));
5749
5750 if (NILP (arg))
5751 window_scroll (window, 1, 1, 1);
5752 else if (EQ (arg, Qminus))
5753 window_scroll (window, -1, 1, 1);
5754 else
5755 {
5756 if (CONSP (arg))
5757 arg = Fcar (arg);
5758 CHECK_NUMBER (arg);
5759 window_scroll (window, XINT (arg), 0, 1);
5760 }
5761
5762 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5763 unbind_to (count, Qnil);
5764
5765 return Qnil;
5766 }
5767 \f
5768 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5769 doc: /* Scroll selected window display ARG columns left.
5770 Default for ARG is window width minus 2.
5771 Value is the total amount of leftward horizontal scrolling in
5772 effect after the change.
5773 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5774 lower bound for automatic scrolling, i.e. automatic scrolling
5775 will not scroll a window to a column less than the value returned
5776 by this function. This happens in an interactive call. */)
5777 (arg, set_minimum)
5778 register Lisp_Object arg, set_minimum;
5779 {
5780 Lisp_Object result;
5781 int hscroll;
5782 struct window *w = XWINDOW (selected_window);
5783
5784 if (NILP (arg))
5785 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5786 else
5787 arg = Fprefix_numeric_value (arg);
5788
5789 hscroll = XINT (w->hscroll) + XINT (arg);
5790 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5791
5792 if (!NILP (set_minimum))
5793 w->min_hscroll = w->hscroll;
5794
5795 return result;
5796 }
5797
5798 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5799 doc: /* Scroll selected window display ARG columns right.
5800 Default for ARG is window width minus 2.
5801 Value is the total amount of leftward horizontal scrolling in
5802 effect after the change.
5803 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5804 lower bound for automatic scrolling, i.e. automatic scrolling
5805 will not scroll a window to a column less than the value returned
5806 by this function. This happens in an interactive call. */)
5807 (arg, set_minimum)
5808 register Lisp_Object arg, set_minimum;
5809 {
5810 Lisp_Object result;
5811 int hscroll;
5812 struct window *w = XWINDOW (selected_window);
5813
5814 if (NILP (arg))
5815 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5816 else
5817 arg = Fprefix_numeric_value (arg);
5818
5819 hscroll = XINT (w->hscroll) - XINT (arg);
5820 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5821
5822 if (!NILP (set_minimum))
5823 w->min_hscroll = w->hscroll;
5824
5825 return result;
5826 }
5827
5828 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5829 doc: /* Return the window which was selected when entering the minibuffer.
5830 Returns nil, if current window is not a minibuffer window. */)
5831 ()
5832 {
5833 if (minibuf_level > 0
5834 && MINI_WINDOW_P (XWINDOW (selected_window))
5835 && WINDOW_LIVE_P (minibuf_selected_window))
5836 return minibuf_selected_window;
5837
5838 return Qnil;
5839 }
5840
5841 /* Value is the number of lines actually displayed in window W,
5842 as opposed to its height. */
5843
5844 static int
5845 displayed_window_lines (w)
5846 struct window *w;
5847 {
5848 struct it it;
5849 struct text_pos start;
5850 int height = window_box_height (w);
5851 struct buffer *old_buffer;
5852 int bottom_y;
5853
5854 if (XBUFFER (w->buffer) != current_buffer)
5855 {
5856 old_buffer = current_buffer;
5857 set_buffer_internal (XBUFFER (w->buffer));
5858 }
5859 else
5860 old_buffer = NULL;
5861
5862 /* In case W->start is out of the accessible range, do something
5863 reasonable. This happens in Info mode when Info-scroll-down
5864 calls (recenter -1) while W->start is 1. */
5865 if (XMARKER (w->start)->charpos < BEGV)
5866 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5867 else if (XMARKER (w->start)->charpos > ZV)
5868 SET_TEXT_POS (start, ZV, ZV_BYTE);
5869 else
5870 SET_TEXT_POS_FROM_MARKER (start, w->start);
5871
5872 start_display (&it, w, start);
5873 move_it_vertically (&it, height);
5874 bottom_y = line_bottom_y (&it);
5875
5876 /* rms: On a non-window display,
5877 the value of it.vpos at the bottom of the screen
5878 seems to be 1 larger than window_box_height (w).
5879 This kludge fixes a bug whereby (move-to-window-line -1)
5880 when ZV is on the last screen line
5881 moves to the previous screen line instead of the last one. */
5882 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5883 height++;
5884
5885 /* Add in empty lines at the bottom of the window. */
5886 if (bottom_y < height)
5887 {
5888 int uy = FRAME_LINE_HEIGHT (it.f);
5889 it.vpos += (height - bottom_y + uy - 1) / uy;
5890 }
5891
5892 if (old_buffer)
5893 set_buffer_internal (old_buffer);
5894
5895 return it.vpos;
5896 }
5897
5898
5899 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5900 doc: /* Center point in window and redisplay frame.
5901 With prefix argument ARG, recenter putting point on screen line ARG
5902 relative to the current window. If ARG is negative, it counts up from the
5903 bottom of the window. (ARG should be less than the height of the window.)
5904
5905 If ARG is omitted or nil, erase the entire frame and then redraw with point
5906 in the center of the current window. If `auto-resize-tool-bars' is set to
5907 `grow-only', this resets the tool-bar's height to the minimum height needed.
5908
5909 Just C-u as prefix means put point in the center of the window
5910 and redisplay normally--don't erase and redraw the frame. */)
5911 (arg)
5912 register Lisp_Object arg;
5913 {
5914 struct window *w = XWINDOW (selected_window);
5915 struct buffer *buf = XBUFFER (w->buffer);
5916 struct buffer *obuf = current_buffer;
5917 int center_p = 0;
5918 int charpos, bytepos;
5919 int iarg;
5920 int this_scroll_margin;
5921
5922 /* If redisplay is suppressed due to an error, try again. */
5923 obuf->display_error_modiff = 0;
5924
5925 if (NILP (arg))
5926 {
5927 int i;
5928
5929 /* Invalidate pixel data calculated for all compositions. */
5930 for (i = 0; i < n_compositions; i++)
5931 composition_table[i]->font = NULL;
5932
5933 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5934
5935 Fredraw_frame (WINDOW_FRAME (w));
5936 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5937 center_p = 1;
5938 }
5939 else if (CONSP (arg)) /* Just C-u. */
5940 center_p = 1;
5941 else
5942 {
5943 arg = Fprefix_numeric_value (arg);
5944 CHECK_NUMBER (arg);
5945 iarg = XINT (arg);
5946 }
5947
5948 set_buffer_internal (buf);
5949
5950 /* Do this after making BUF current
5951 in case scroll_margin is buffer-local. */
5952 this_scroll_margin = max (0, scroll_margin);
5953 this_scroll_margin = min (this_scroll_margin,
5954 XFASTINT (w->total_lines) / 4);
5955
5956 /* Handle centering on a graphical frame specially. Such frames can
5957 have variable-height lines and centering point on the basis of
5958 line counts would lead to strange effects. */
5959 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5960 {
5961 if (center_p)
5962 {
5963 struct it it;
5964 struct text_pos pt;
5965
5966 SET_TEXT_POS (pt, PT, PT_BYTE);
5967 start_display (&it, w, pt);
5968 move_it_vertically_backward (&it, window_box_height (w) / 2);
5969 charpos = IT_CHARPOS (it);
5970 bytepos = IT_BYTEPOS (it);
5971 }
5972 else if (iarg < 0)
5973 {
5974 struct it it;
5975 struct text_pos pt;
5976 int nlines = -iarg;
5977 int extra_line_spacing;
5978 int h = window_box_height (w);
5979
5980 iarg = - max (-iarg, this_scroll_margin);
5981
5982 SET_TEXT_POS (pt, PT, PT_BYTE);
5983 start_display (&it, w, pt);
5984
5985 /* Be sure we have the exact height of the full line containing PT. */
5986 move_it_by_lines (&it, 0, 1);
5987
5988 /* The amount of pixels we have to move back is the window
5989 height minus what's displayed in the line containing PT,
5990 and the lines below. */
5991 it.current_y = 0;
5992 it.vpos = 0;
5993 move_it_by_lines (&it, nlines, 1);
5994
5995 if (it.vpos == nlines)
5996 h -= it.current_y;
5997 else
5998 {
5999 /* Last line has no newline */
6000 h -= line_bottom_y (&it);
6001 it.vpos++;
6002 }
6003
6004 /* Don't reserve space for extra line spacing of last line. */
6005 extra_line_spacing = it.max_extra_line_spacing;
6006
6007 /* If we can't move down NLINES lines because we hit
6008 the end of the buffer, count in some empty lines. */
6009 if (it.vpos < nlines)
6010 {
6011 nlines -= it.vpos;
6012 extra_line_spacing = it.extra_line_spacing;
6013 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
6014 }
6015 if (h <= 0)
6016 return Qnil;
6017
6018 /* Now find the new top line (starting position) of the window. */
6019 start_display (&it, w, pt);
6020 it.current_y = 0;
6021 move_it_vertically_backward (&it, h);
6022
6023 /* If extra line spacing is present, we may move too far
6024 back. This causes the last line to be only partially
6025 visible (which triggers redisplay to recenter that line
6026 in the middle), so move forward.
6027 But ignore extra line spacing on last line, as it is not
6028 considered to be part of the visible height of the line.
6029 */
6030 h += extra_line_spacing;
6031 while (-it.current_y > h)
6032 move_it_by_lines (&it, 1, 1);
6033
6034 charpos = IT_CHARPOS (it);
6035 bytepos = IT_BYTEPOS (it);
6036 }
6037 else
6038 {
6039 struct position pos;
6040
6041 iarg = max (iarg, this_scroll_margin);
6042
6043 pos = *vmotion (PT, -iarg, w);
6044 charpos = pos.bufpos;
6045 bytepos = pos.bytepos;
6046 }
6047 }
6048 else
6049 {
6050 struct position pos;
6051 int ht = window_internal_height (w);
6052
6053 if (center_p)
6054 iarg = ht / 2;
6055 else if (iarg < 0)
6056 iarg += ht;
6057
6058 /* Don't let it get into the margin at either top or bottom. */
6059 iarg = max (iarg, this_scroll_margin);
6060 iarg = min (iarg, ht - this_scroll_margin - 1);
6061
6062 pos = *vmotion (PT, - iarg, w);
6063 charpos = pos.bufpos;
6064 bytepos = pos.bytepos;
6065 }
6066
6067 /* Set the new window start. */
6068 set_marker_both (w->start, w->buffer, charpos, bytepos);
6069 w->window_end_valid = Qnil;
6070
6071 w->optional_new_start = Qt;
6072
6073 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
6074 w->start_at_line_beg = Qt;
6075 else
6076 w->start_at_line_beg = Qnil;
6077
6078 set_buffer_internal (obuf);
6079 return Qnil;
6080 }
6081
6082
6083 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
6084 0, 1, 0,
6085 doc: /* Return the height in lines of the text display area of WINDOW.
6086 WINDOW defaults to the selected window.
6087 This doesn't include the mode-line (or header-line if any) or any
6088 partial-height lines in the text display area. */)
6089 (window)
6090 Lisp_Object window;
6091 {
6092 struct window *w = decode_window (window);
6093 int pixel_height = window_box_height (w);
6094 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
6095 return make_number (line_height);
6096 }
6097
6098
6099 \f
6100 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
6101 1, 1, "P",
6102 doc: /* Position point relative to window.
6103 With no argument, position point at center of window.
6104 An argument specifies vertical position within the window;
6105 zero means top of window, negative means relative to bottom of window. */)
6106 (arg)
6107 Lisp_Object arg;
6108 {
6109 struct window *w = XWINDOW (selected_window);
6110 int lines, start;
6111 Lisp_Object window;
6112 #if 0
6113 int this_scroll_margin;
6114 #endif
6115
6116 window = selected_window;
6117 start = marker_position (w->start);
6118 if (start < BEGV || start > ZV)
6119 {
6120 int height = window_internal_height (w);
6121 Fvertical_motion (make_number (- (height / 2)), window);
6122 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
6123 w->start_at_line_beg = Fbolp ();
6124 w->force_start = Qt;
6125 }
6126 else
6127 Fgoto_char (w->start);
6128
6129 lines = displayed_window_lines (w);
6130
6131 #if 0
6132 this_scroll_margin = max (0, scroll_margin);
6133 this_scroll_margin = min (this_scroll_margin, lines / 4);
6134 #endif
6135
6136 if (NILP (arg))
6137 XSETFASTINT (arg, lines / 2);
6138 else
6139 {
6140 int iarg = XINT (Fprefix_numeric_value (arg));
6141
6142 if (iarg < 0)
6143 iarg = iarg + lines;
6144
6145 #if 0 /* This code would prevent move-to-window-line from moving point
6146 to a place inside the scroll margins (which would cause the
6147 next redisplay to scroll). I wrote this code, but then concluded
6148 it is probably better not to install it. However, it is here
6149 inside #if 0 so as not to lose it. -- rms. */
6150
6151 /* Don't let it get into the margin at either top or bottom. */
6152 iarg = max (iarg, this_scroll_margin);
6153 iarg = min (iarg, lines - this_scroll_margin - 1);
6154 #endif
6155
6156 arg = make_number (iarg);
6157 }
6158
6159 /* Skip past a partially visible first line. */
6160 if (w->vscroll)
6161 XSETINT (arg, XINT (arg) + 1);
6162
6163 return Fvertical_motion (arg, window);
6164 }
6165
6166
6167 \f
6168 /***********************************************************************
6169 Window Configuration
6170 ***********************************************************************/
6171
6172 struct save_window_data
6173 {
6174 EMACS_UINT size;
6175 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6176 Lisp_Object selected_frame;
6177 Lisp_Object current_window;
6178 Lisp_Object current_buffer;
6179 Lisp_Object minibuf_scroll_window;
6180 Lisp_Object minibuf_selected_window;
6181 Lisp_Object root_window;
6182 Lisp_Object focus_frame;
6183 /* A vector, each of whose elements is a struct saved_window
6184 for one window. */
6185 Lisp_Object saved_windows;
6186
6187 /* All fields above are traced by the GC.
6188 From `fame-cols' down, the fields are ignored by the GC. */
6189
6190 int frame_cols, frame_lines, frame_menu_bar_lines;
6191 int frame_tool_bar_lines;
6192 };
6193
6194 /* This is saved as a Lisp_Vector */
6195 struct saved_window
6196 {
6197 /* these first two must agree with struct Lisp_Vector in lisp.h */
6198 EMACS_UINT size;
6199 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6200
6201 Lisp_Object window;
6202 Lisp_Object buffer, start, pointm, mark;
6203 Lisp_Object left_col, top_line, total_cols, total_lines;
6204 Lisp_Object hscroll, min_hscroll;
6205 Lisp_Object parent, prev;
6206 Lisp_Object start_at_line_beg;
6207 Lisp_Object display_table;
6208 Lisp_Object orig_top_line, orig_total_lines;
6209 Lisp_Object left_margin_cols, right_margin_cols;
6210 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
6211 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
6212 Lisp_Object dedicated, resize_proportionally;
6213 };
6214
6215 #define SAVED_WINDOW_N(swv,n) \
6216 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6217
6218 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
6219 doc: /* Return t if OBJECT is a window-configuration object. */)
6220 (object)
6221 Lisp_Object object;
6222 {
6223 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
6224 }
6225
6226 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
6227 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6228 (config)
6229 Lisp_Object config;
6230 {
6231 register struct save_window_data *data;
6232 struct Lisp_Vector *saved_windows;
6233
6234 CHECK_WINDOW_CONFIGURATION (config);
6235
6236 data = (struct save_window_data *) XVECTOR (config);
6237 saved_windows = XVECTOR (data->saved_windows);
6238 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6239 }
6240
6241 DEFUN ("set-window-configuration", Fset_window_configuration,
6242 Sset_window_configuration, 1, 1, 0,
6243 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6244 CONFIGURATION must be a value previously returned
6245 by `current-window-configuration' (which see).
6246 If CONFIGURATION was made from a frame that is now deleted,
6247 only frame-independent values can be restored. In this case,
6248 the return value is nil. Otherwise the value is t. */)
6249 (configuration)
6250 Lisp_Object configuration;
6251 {
6252 register struct save_window_data *data;
6253 struct Lisp_Vector *saved_windows;
6254 Lisp_Object new_current_buffer;
6255 Lisp_Object frame;
6256 FRAME_PTR f;
6257 int old_point = -1;
6258
6259 CHECK_WINDOW_CONFIGURATION (configuration);
6260
6261 data = (struct save_window_data *) XVECTOR (configuration);
6262 saved_windows = XVECTOR (data->saved_windows);
6263
6264 new_current_buffer = data->current_buffer;
6265 if (NILP (XBUFFER (new_current_buffer)->name))
6266 new_current_buffer = Qnil;
6267 else
6268 {
6269 if (XBUFFER (new_current_buffer) == current_buffer)
6270 /* The code further down "preserves point" by saving here PT in
6271 old_point and then setting it later back into PT. When the
6272 current-selected-window and the final-selected-window both show
6273 the current buffer, this suffers from the problem that the
6274 current PT is the window-point of the current-selected-window,
6275 while the final PT is the point of the final-selected-window, so
6276 this copy from one PT to the other would end up moving the
6277 window-point of the final-selected-window to the window-point of
6278 the current-selected-window. So we have to be careful which
6279 point of the current-buffer we copy into old_point. */
6280 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6281 && WINDOWP (selected_window)
6282 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
6283 && !EQ (selected_window, data->current_window))
6284 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6285 else
6286 old_point = PT;
6287 else
6288 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6289 point in new_current_buffer as of the last time this buffer was
6290 used. This can be non-deterministic since it can be changed by
6291 things like jit-lock by mere temporary selection of some random
6292 window that happens to show this buffer.
6293 So if possible we want this arbitrary choice of "which point" to
6294 be the one from the to-be-selected-window so as to prevent this
6295 window's cursor from being copied from another window. */
6296 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6297 /* If current_window = selected_window, its point is in BUF_PT. */
6298 && !EQ (selected_window, data->current_window))
6299 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6300 else
6301 old_point = BUF_PT (XBUFFER (new_current_buffer));
6302 }
6303
6304 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6305 f = XFRAME (frame);
6306
6307 /* If f is a dead frame, don't bother rebuilding its window tree.
6308 However, there is other stuff we should still try to do below. */
6309 if (FRAME_LIVE_P (f))
6310 {
6311 register struct window *w;
6312 register struct saved_window *p;
6313 struct window *root_window;
6314 struct window **leaf_windows;
6315 int n_leaf_windows;
6316 int k, i, n;
6317
6318 /* If the frame has been resized since this window configuration was
6319 made, we change the frame to the size specified in the
6320 configuration, restore the configuration, and then resize it
6321 back. We keep track of the prevailing height in these variables. */
6322 int previous_frame_lines = FRAME_LINES (f);
6323 int previous_frame_cols = FRAME_COLS (f);
6324 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6325 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6326
6327 /* The mouse highlighting code could get screwed up
6328 if it runs during this. */
6329 BLOCK_INPUT;
6330
6331 if (data->frame_lines != previous_frame_lines
6332 || data->frame_cols != previous_frame_cols)
6333 change_frame_size (f, data->frame_lines,
6334 data->frame_cols, 0, 0, 0);
6335 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6336 if (data->frame_menu_bar_lines
6337 != previous_frame_menu_bar_lines)
6338 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
6339 make_number (0));
6340 #ifdef HAVE_WINDOW_SYSTEM
6341 if (data->frame_tool_bar_lines
6342 != previous_frame_tool_bar_lines)
6343 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
6344 make_number (0));
6345 #endif
6346 #endif
6347
6348 /* "Swap out" point from the selected window's buffer
6349 into the window itself. (Normally the pointm of the selected
6350 window holds garbage.) We do this now, before
6351 restoring the window contents, and prevent it from
6352 being done later on when we select a new window. */
6353 if (! NILP (XWINDOW (selected_window)->buffer))
6354 {
6355 w = XWINDOW (selected_window);
6356 set_marker_both (w->pointm,
6357 w->buffer,
6358 BUF_PT (XBUFFER (w->buffer)),
6359 BUF_PT_BYTE (XBUFFER (w->buffer)));
6360 }
6361
6362 windows_or_buffers_changed++;
6363 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6364
6365 /* Problem: Freeing all matrices and later allocating them again
6366 is a serious redisplay flickering problem. What we would
6367 really like to do is to free only those matrices not reused
6368 below. */
6369 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6370 leaf_windows
6371 = (struct window **) alloca (count_windows (root_window)
6372 * sizeof (struct window *));
6373 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6374
6375 /* Kludge Alert!
6376 Mark all windows now on frame as "deleted".
6377 Restoring the new configuration "undeletes" any that are in it.
6378
6379 Save their current buffers in their height fields, since we may
6380 need it later, if a buffer saved in the configuration is now
6381 dead. */
6382 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6383
6384 for (k = 0; k < saved_windows->size; k++)
6385 {
6386 p = SAVED_WINDOW_N (saved_windows, k);
6387 w = XWINDOW (p->window);
6388 w->next = Qnil;
6389
6390 if (!NILP (p->parent))
6391 w->parent = SAVED_WINDOW_N (saved_windows,
6392 XFASTINT (p->parent))->window;
6393 else
6394 w->parent = Qnil;
6395
6396 if (!NILP (p->prev))
6397 {
6398 w->prev = SAVED_WINDOW_N (saved_windows,
6399 XFASTINT (p->prev))->window;
6400 XWINDOW (w->prev)->next = p->window;
6401 }
6402 else
6403 {
6404 w->prev = Qnil;
6405 if (!NILP (w->parent))
6406 {
6407 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6408 {
6409 XWINDOW (w->parent)->vchild = p->window;
6410 XWINDOW (w->parent)->hchild = Qnil;
6411 }
6412 else
6413 {
6414 XWINDOW (w->parent)->hchild = p->window;
6415 XWINDOW (w->parent)->vchild = Qnil;
6416 }
6417 }
6418 }
6419
6420 /* If we squirreled away the buffer in the window's height,
6421 restore it now. */
6422 if (BUFFERP (w->total_lines))
6423 w->buffer = w->total_lines;
6424 w->left_col = p->left_col;
6425 w->top_line = p->top_line;
6426 w->total_cols = p->total_cols;
6427 w->total_lines = p->total_lines;
6428 w->hscroll = p->hscroll;
6429 w->min_hscroll = p->min_hscroll;
6430 w->display_table = p->display_table;
6431 w->orig_top_line = p->orig_top_line;
6432 w->orig_total_lines = p->orig_total_lines;
6433 w->left_margin_cols = p->left_margin_cols;
6434 w->right_margin_cols = p->right_margin_cols;
6435 w->left_fringe_width = p->left_fringe_width;
6436 w->right_fringe_width = p->right_fringe_width;
6437 w->fringes_outside_margins = p->fringes_outside_margins;
6438 w->scroll_bar_width = p->scroll_bar_width;
6439 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6440 w->dedicated = p->dedicated;
6441 w->resize_proportionally = p->resize_proportionally;
6442 XSETFASTINT (w->last_modified, 0);
6443 XSETFASTINT (w->last_overlay_modified, 0);
6444
6445 /* Reinstall the saved buffer and pointers into it. */
6446 if (NILP (p->buffer))
6447 w->buffer = p->buffer;
6448 else
6449 {
6450 if (!NILP (XBUFFER (p->buffer)->name))
6451 /* If saved buffer is alive, install it. */
6452 {
6453 w->buffer = p->buffer;
6454 w->start_at_line_beg = p->start_at_line_beg;
6455 set_marker_restricted (w->start, p->start, w->buffer);
6456 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6457 Fset_marker (XBUFFER (w->buffer)->mark,
6458 p->mark, w->buffer);
6459
6460 /* As documented in Fcurrent_window_configuration, don't
6461 restore the location of point in the buffer which was
6462 current when the window configuration was recorded. */
6463 if (!EQ (p->buffer, new_current_buffer)
6464 && XBUFFER (p->buffer) == current_buffer)
6465 Fgoto_char (w->pointm);
6466 }
6467 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6468 /* Else unless window has a live buffer, get one. */
6469 {
6470 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6471 /* This will set the markers to beginning of visible
6472 range. */
6473 set_marker_restricted (w->start, make_number (0), w->buffer);
6474 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6475 w->start_at_line_beg = Qt;
6476 }
6477 else
6478 /* Keeping window's old buffer; make sure the markers
6479 are real. */
6480 {
6481 /* Set window markers at start of visible range. */
6482 if (XMARKER (w->start)->buffer == 0)
6483 set_marker_restricted (w->start, make_number (0),
6484 w->buffer);
6485 if (XMARKER (w->pointm)->buffer == 0)
6486 set_marker_restricted_both (w->pointm, w->buffer,
6487 BUF_PT (XBUFFER (w->buffer)),
6488 BUF_PT_BYTE (XBUFFER (w->buffer)));
6489 w->start_at_line_beg = Qt;
6490 }
6491 }
6492 }
6493
6494 FRAME_ROOT_WINDOW (f) = data->root_window;
6495 /* Prevent "swapping out point" in the old selected window
6496 using the buffer that has been restored into it.
6497 We already swapped out point that from that window's old buffer. */
6498 selected_window = Qnil;
6499
6500 /* Arrange *not* to restore point in the buffer that was
6501 current when the window configuration was saved. */
6502 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6503 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6504 make_number (old_point),
6505 XWINDOW (data->current_window)->buffer);
6506
6507 Fselect_window (data->current_window, Qnil);
6508 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6509 = selected_window;
6510
6511 if (NILP (data->focus_frame)
6512 || (FRAMEP (data->focus_frame)
6513 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6514 Fredirect_frame_focus (frame, data->focus_frame);
6515
6516 #if 0 /* I don't understand why this is needed, and it causes problems
6517 when the frame's old selected window has been deleted. */
6518 if (f != selected_frame && FRAME_WINDOW_P (f))
6519 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6520 0, 0);
6521 #endif
6522
6523 /* Set the screen height to the value it had before this function. */
6524 if (previous_frame_lines != FRAME_LINES (f)
6525 || previous_frame_cols != FRAME_COLS (f))
6526 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6527 0, 0, 0);
6528 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6529 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6530 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6531 make_number (0));
6532 #ifdef HAVE_WINDOW_SYSTEM
6533 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6534 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6535 make_number (0));
6536 #endif
6537 #endif
6538
6539 /* Now, free glyph matrices in windows that were not reused. */
6540 for (i = n = 0; i < n_leaf_windows; ++i)
6541 {
6542 if (NILP (leaf_windows[i]->buffer))
6543 {
6544 /* Assert it's not reused as a combination. */
6545 xassert (NILP (leaf_windows[i]->hchild)
6546 && NILP (leaf_windows[i]->vchild));
6547 free_window_matrices (leaf_windows[i]);
6548 }
6549 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6550 ++n;
6551 }
6552
6553 adjust_glyphs (f);
6554
6555 UNBLOCK_INPUT;
6556
6557 /* Fselect_window will have made f the selected frame, so we
6558 reselect the proper frame here. Fhandle_switch_frame will change the
6559 selected window too, but that doesn't make the call to
6560 Fselect_window above totally superfluous; it still sets f's
6561 selected window. */
6562 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6563 do_switch_frame (data->selected_frame, 0, 0);
6564
6565 run_window_configuration_change_hook (f);
6566 }
6567
6568 if (!NILP (new_current_buffer))
6569 Fset_buffer (new_current_buffer);
6570
6571 Vminibuf_scroll_window = data->minibuf_scroll_window;
6572 minibuf_selected_window = data->minibuf_selected_window;
6573
6574 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6575 }
6576
6577 /* Mark all windows now on frame as deleted
6578 by setting their buffers to nil. */
6579
6580 void
6581 delete_all_subwindows (w)
6582 register struct window *w;
6583 {
6584 if (!NILP (w->next))
6585 delete_all_subwindows (XWINDOW (w->next));
6586 if (!NILP (w->vchild))
6587 delete_all_subwindows (XWINDOW (w->vchild));
6588 if (!NILP (w->hchild))
6589 delete_all_subwindows (XWINDOW (w->hchild));
6590
6591 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6592
6593 if (!NILP (w->buffer))
6594 unshow_buffer (w);
6595
6596 /* We set all three of these fields to nil, to make sure that we can
6597 distinguish this dead window from any live window. Live leaf
6598 windows will have buffer set, and combination windows will have
6599 vchild or hchild set. */
6600 w->buffer = Qnil;
6601 w->vchild = Qnil;
6602 w->hchild = Qnil;
6603
6604 Vwindow_list = Qnil;
6605 }
6606 \f
6607 static int
6608 count_windows (window)
6609 register struct window *window;
6610 {
6611 register int count = 1;
6612 if (!NILP (window->next))
6613 count += count_windows (XWINDOW (window->next));
6614 if (!NILP (window->vchild))
6615 count += count_windows (XWINDOW (window->vchild));
6616 if (!NILP (window->hchild))
6617 count += count_windows (XWINDOW (window->hchild));
6618 return count;
6619 }
6620
6621
6622 /* Fill vector FLAT with leaf windows under W, starting at index I.
6623 Value is last index + 1. */
6624
6625 static int
6626 get_leaf_windows (w, flat, i)
6627 struct window *w;
6628 struct window **flat;
6629 int i;
6630 {
6631 while (w)
6632 {
6633 if (!NILP (w->hchild))
6634 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6635 else if (!NILP (w->vchild))
6636 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6637 else
6638 flat[i++] = w;
6639
6640 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6641 }
6642
6643 return i;
6644 }
6645
6646
6647 /* Return a pointer to the glyph W's physical cursor is on. Value is
6648 null if W's current matrix is invalid, so that no meaningfull glyph
6649 can be returned. */
6650
6651 struct glyph *
6652 get_phys_cursor_glyph (w)
6653 struct window *w;
6654 {
6655 struct glyph_row *row;
6656 struct glyph *glyph;
6657
6658 if (w->phys_cursor.vpos >= 0
6659 && w->phys_cursor.vpos < w->current_matrix->nrows
6660 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6661 row->enabled_p)
6662 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6663 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6664 else
6665 glyph = NULL;
6666
6667 return glyph;
6668 }
6669
6670
6671 static int
6672 save_window_save (window, vector, i)
6673 Lisp_Object window;
6674 struct Lisp_Vector *vector;
6675 int i;
6676 {
6677 register struct saved_window *p;
6678 register struct window *w;
6679 register Lisp_Object tem;
6680
6681 for (;!NILP (window); window = w->next)
6682 {
6683 p = SAVED_WINDOW_N (vector, i);
6684 w = XWINDOW (window);
6685
6686 XSETFASTINT (w->temslot, i); i++;
6687 p->window = window;
6688 p->buffer = w->buffer;
6689 p->left_col = w->left_col;
6690 p->top_line = w->top_line;
6691 p->total_cols = w->total_cols;
6692 p->total_lines = w->total_lines;
6693 p->hscroll = w->hscroll;
6694 p->min_hscroll = w->min_hscroll;
6695 p->display_table = w->display_table;
6696 p->orig_top_line = w->orig_top_line;
6697 p->orig_total_lines = w->orig_total_lines;
6698 p->left_margin_cols = w->left_margin_cols;
6699 p->right_margin_cols = w->right_margin_cols;
6700 p->left_fringe_width = w->left_fringe_width;
6701 p->right_fringe_width = w->right_fringe_width;
6702 p->fringes_outside_margins = w->fringes_outside_margins;
6703 p->scroll_bar_width = w->scroll_bar_width;
6704 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6705 p->dedicated = w->dedicated;
6706 p->resize_proportionally = w->resize_proportionally;
6707 if (!NILP (w->buffer))
6708 {
6709 /* Save w's value of point in the window configuration.
6710 If w is the selected window, then get the value of point
6711 from the buffer; pointm is garbage in the selected window. */
6712 if (EQ (window, selected_window))
6713 {
6714 p->pointm = Fmake_marker ();
6715 set_marker_both (p->pointm, w->buffer,
6716 BUF_PT (XBUFFER (w->buffer)),
6717 BUF_PT_BYTE (XBUFFER (w->buffer)));
6718 }
6719 else
6720 p->pointm = Fcopy_marker (w->pointm, Qnil);
6721
6722 p->start = Fcopy_marker (w->start, Qnil);
6723 p->start_at_line_beg = w->start_at_line_beg;
6724
6725 tem = XBUFFER (w->buffer)->mark;
6726 p->mark = Fcopy_marker (tem, Qnil);
6727 }
6728 else
6729 {
6730 p->pointm = Qnil;
6731 p->start = Qnil;
6732 p->mark = Qnil;
6733 p->start_at_line_beg = Qnil;
6734 }
6735
6736 if (NILP (w->parent))
6737 p->parent = Qnil;
6738 else
6739 p->parent = XWINDOW (w->parent)->temslot;
6740
6741 if (NILP (w->prev))
6742 p->prev = Qnil;
6743 else
6744 p->prev = XWINDOW (w->prev)->temslot;
6745
6746 if (!NILP (w->vchild))
6747 i = save_window_save (w->vchild, vector, i);
6748 if (!NILP (w->hchild))
6749 i = save_window_save (w->hchild, vector, i);
6750 }
6751
6752 return i;
6753 }
6754
6755 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6756 Scurrent_window_configuration, 0, 1, 0,
6757 doc: /* Return an object representing the current window configuration of FRAME.
6758 If FRAME is nil or omitted, use the selected frame.
6759 This describes the number of windows, their sizes and current buffers,
6760 and for each displayed buffer, where display starts, and the positions of
6761 point and mark. An exception is made for point in the current buffer:
6762 its value is -not- saved.
6763 This also records the currently selected frame, and FRAME's focus
6764 redirection (see `redirect-frame-focus'). */)
6765 (frame)
6766 Lisp_Object frame;
6767 {
6768 register Lisp_Object tem;
6769 register int n_windows;
6770 register struct save_window_data *data;
6771 register int i;
6772 FRAME_PTR f;
6773
6774 if (NILP (frame))
6775 frame = selected_frame;
6776 CHECK_LIVE_FRAME (frame);
6777 f = XFRAME (frame);
6778
6779 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6780 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6781 PVEC_WINDOW_CONFIGURATION);
6782
6783 data->frame_cols = FRAME_COLS (f);
6784 data->frame_lines = FRAME_LINES (f);
6785 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6786 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6787 data->selected_frame = selected_frame;
6788 data->current_window = FRAME_SELECTED_WINDOW (f);
6789 XSETBUFFER (data->current_buffer, current_buffer);
6790 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6791 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6792 data->root_window = FRAME_ROOT_WINDOW (f);
6793 data->focus_frame = FRAME_FOCUS_FRAME (f);
6794 tem = Fmake_vector (make_number (n_windows), Qnil);
6795 data->saved_windows = tem;
6796 for (i = 0; i < n_windows; i++)
6797 XVECTOR (tem)->contents[i]
6798 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6799 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6800 XSETWINDOW_CONFIGURATION (tem, data);
6801 return (tem);
6802 }
6803
6804 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6805 0, UNEVALLED, 0,
6806 doc: /* Execute BODY, preserving window sizes and contents.
6807 Return the value of the last form in BODY.
6808 Restore which buffer appears in which window, where display starts,
6809 and the value of point and mark for each window.
6810 Also restore the choice of selected window.
6811 Also restore which buffer is current.
6812 Does not restore the value of point in current buffer.
6813 usage: (save-window-excursion BODY...) */)
6814 (args)
6815 Lisp_Object args;
6816 {
6817 register Lisp_Object val;
6818 register int count = SPECPDL_INDEX ();
6819
6820 record_unwind_protect (Fset_window_configuration,
6821 Fcurrent_window_configuration (Qnil));
6822 val = Fprogn (args);
6823 return unbind_to (count, val);
6824 }
6825
6826
6827 \f
6828 /***********************************************************************
6829 Window Split Tree
6830 ***********************************************************************/
6831
6832 static Lisp_Object
6833 window_tree (w)
6834 struct window *w;
6835 {
6836 Lisp_Object tail = Qnil;
6837 Lisp_Object result = Qnil;
6838
6839 while (w)
6840 {
6841 Lisp_Object wn;
6842
6843 XSETWINDOW (wn, w);
6844 if (!NILP (w->hchild))
6845 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6846 window_tree (XWINDOW (w->hchild))));
6847 else if (!NILP (w->vchild))
6848 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6849 window_tree (XWINDOW (w->vchild))));
6850
6851 if (NILP (result))
6852 {
6853 result = tail = Fcons (wn, Qnil);
6854 }
6855 else
6856 {
6857 XSETCDR (tail, Fcons (wn, Qnil));
6858 tail = XCDR (tail);
6859 }
6860
6861 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6862 }
6863
6864 return result;
6865 }
6866
6867
6868
6869 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6870 0, 1, 0,
6871 doc: /* Return the window tree for frame FRAME.
6872
6873 The return value is a list of the form (ROOT MINI), where ROOT
6874 represents the window tree of the frame's root window, and MINI
6875 is the frame's minibuffer window.
6876
6877 If the root window is not split, ROOT is the root window itself.
6878 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6879 horizontal split, and t for a vertical split, EDGES gives the combined
6880 size and position of the subwindows in the split, and the rest of the
6881 elements are the subwindows in the split. Each of the subwindows may
6882 again be a window or a list representing a window split, and so on.
6883 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6884
6885 If FRAME is nil or omitted, return information on the currently
6886 selected frame. */)
6887 (frame)
6888 Lisp_Object frame;
6889 {
6890 FRAME_PTR f;
6891
6892 if (NILP (frame))
6893 frame = selected_frame;
6894
6895 CHECK_FRAME (frame);
6896 f = XFRAME (frame);
6897
6898 if (!FRAME_LIVE_P (f))
6899 return Qnil;
6900
6901 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6902 }
6903
6904 \f
6905 /***********************************************************************
6906 Marginal Areas
6907 ***********************************************************************/
6908
6909 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6910 2, 3, 0,
6911 doc: /* Set width of marginal areas of window WINDOW.
6912 If WINDOW is nil, set margins of the currently selected window.
6913 Second arg LEFT-WIDTH specifies the number of character cells to
6914 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6915 does the same for the right marginal area. A nil width parameter
6916 means no margin. */)
6917 (window, left_width, right_width)
6918 Lisp_Object window, left_width, right_width;
6919 {
6920 struct window *w = decode_window (window);
6921
6922 /* Translate negative or zero widths to nil.
6923 Margins that are too wide have to be checked elsewhere. */
6924
6925 if (!NILP (left_width))
6926 {
6927 CHECK_NUMBER (left_width);
6928 if (XINT (left_width) <= 0)
6929 left_width = Qnil;
6930 }
6931
6932 if (!NILP (right_width))
6933 {
6934 CHECK_NUMBER (right_width);
6935 if (XINT (right_width) <= 0)
6936 right_width = Qnil;
6937 }
6938
6939 if (!EQ (w->left_margin_cols, left_width)
6940 || !EQ (w->right_margin_cols, right_width))
6941 {
6942 w->left_margin_cols = left_width;
6943 w->right_margin_cols = right_width;
6944
6945 adjust_window_margins (w);
6946
6947 ++windows_or_buffers_changed;
6948 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6949 }
6950
6951 return Qnil;
6952 }
6953
6954
6955 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6956 0, 1, 0,
6957 doc: /* Get width of marginal areas of window WINDOW.
6958 If WINDOW is omitted or nil, use the currently selected window.
6959 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6960 If a marginal area does not exist, its width will be returned
6961 as nil. */)
6962 (window)
6963 Lisp_Object window;
6964 {
6965 struct window *w = decode_window (window);
6966 return Fcons (w->left_margin_cols, w->right_margin_cols);
6967 }
6968
6969
6970 \f
6971 /***********************************************************************
6972 Fringes
6973 ***********************************************************************/
6974
6975 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6976 2, 4, 0,
6977 doc: /* Set the fringe widths of window WINDOW.
6978 If WINDOW is nil, set the fringe widths of the currently selected
6979 window.
6980 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6981 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6982 fringe width. If a fringe width arg is nil, that means to use the
6983 frame's default fringe width. Default fringe widths can be set with
6984 the command `set-fringe-style'.
6985 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6986 outside of the display margins. By default, fringes are drawn between
6987 display marginal areas and the text area. */)
6988 (window, left_width, right_width, outside_margins)
6989 Lisp_Object window, left_width, right_width, outside_margins;
6990 {
6991 struct window *w = decode_window (window);
6992
6993 if (!NILP (left_width))
6994 CHECK_NATNUM (left_width);
6995 if (!NILP (right_width))
6996 CHECK_NATNUM (right_width);
6997
6998 /* Do nothing on a tty. */
6999 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
7000 && (!EQ (w->left_fringe_width, left_width)
7001 || !EQ (w->right_fringe_width, right_width)
7002 || !EQ (w->fringes_outside_margins, outside_margins)))
7003 {
7004 w->left_fringe_width = left_width;
7005 w->right_fringe_width = right_width;
7006 w->fringes_outside_margins = outside_margins;
7007
7008 adjust_window_margins (w);
7009
7010 clear_glyph_matrix (w->current_matrix);
7011 w->window_end_valid = Qnil;
7012
7013 ++windows_or_buffers_changed;
7014 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
7015 }
7016
7017 return Qnil;
7018 }
7019
7020
7021 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
7022 0, 1, 0,
7023 doc: /* Get width of fringes of window WINDOW.
7024 If WINDOW is omitted or nil, use the currently selected window.
7025 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
7026 (window)
7027 Lisp_Object window;
7028 {
7029 struct window *w = decode_window (window);
7030
7031 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
7032 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
7033 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
7034 ? Qt : Qnil), Qnil)));
7035 }
7036
7037
7038 \f
7039 /***********************************************************************
7040 Scroll bars
7041 ***********************************************************************/
7042
7043 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
7044 2, 4, 0,
7045 doc: /* Set width and type of scroll bars of window WINDOW.
7046 If window is nil, set scroll bars of the currently selected window.
7047 Second parameter WIDTH specifies the pixel width for the scroll bar;
7048 this is automatically adjusted to a multiple of the frame column width.
7049 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
7050 bar: left, right, or nil.
7051 If WIDTH is nil, use the frame's scroll-bar width.
7052 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
7053 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
7054 (window, width, vertical_type, horizontal_type)
7055 Lisp_Object window, width, vertical_type, horizontal_type;
7056 {
7057 struct window *w = decode_window (window);
7058
7059 if (!NILP (width))
7060 {
7061 CHECK_NATNUM (width);
7062
7063 if (XINT (width) == 0)
7064 vertical_type = Qnil;
7065 }
7066
7067 if (!(NILP (vertical_type)
7068 || EQ (vertical_type, Qleft)
7069 || EQ (vertical_type, Qright)
7070 || EQ (vertical_type, Qt)))
7071 error ("Invalid type of vertical scroll bar");
7072
7073 if (!EQ (w->scroll_bar_width, width)
7074 || !EQ (w->vertical_scroll_bar_type, vertical_type))
7075 {
7076 w->scroll_bar_width = width;
7077 w->vertical_scroll_bar_type = vertical_type;
7078
7079 adjust_window_margins (w);
7080
7081 clear_glyph_matrix (w->current_matrix);
7082 w->window_end_valid = Qnil;
7083
7084 ++windows_or_buffers_changed;
7085 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
7086 }
7087
7088 return Qnil;
7089 }
7090
7091
7092 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
7093 0, 1, 0,
7094 doc: /* Get width and type of scroll bars of window WINDOW.
7095 If WINDOW is omitted or nil, use the currently selected window.
7096 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
7097 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
7098 value. */)
7099 (window)
7100 Lisp_Object window;
7101 {
7102 struct window *w = decode_window (window);
7103 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
7104 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
7105 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
7106 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
7107 Fcons (w->vertical_scroll_bar_type,
7108 Fcons (Qnil, Qnil))));
7109 }
7110
7111
7112 \f
7113 /***********************************************************************
7114 Smooth scrolling
7115 ***********************************************************************/
7116
7117 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
7118 doc: /* Return the amount by which WINDOW is scrolled vertically.
7119 Use the selected window if WINDOW is nil or omitted.
7120 Normally, value is a multiple of the canonical character height of WINDOW;
7121 optional second arg PIXELS-P means value is measured in pixels. */)
7122 (window, pixels_p)
7123 Lisp_Object window, pixels_p;
7124 {
7125 Lisp_Object result;
7126 struct frame *f;
7127 struct window *w;
7128
7129 if (NILP (window))
7130 window = selected_window;
7131 else
7132 CHECK_WINDOW (window);
7133 w = XWINDOW (window);
7134 f = XFRAME (w->frame);
7135
7136 if (FRAME_WINDOW_P (f))
7137 result = (NILP (pixels_p)
7138 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
7139 : make_number (-w->vscroll));
7140 else
7141 result = make_number (0);
7142 return result;
7143 }
7144
7145
7146 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
7147 2, 3, 0,
7148 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7149 WINDOW nil means use the selected window. Normally, VSCROLL is a
7150 non-negative multiple of the canonical character height of WINDOW;
7151 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7152 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7153 corresponds to an integral number of pixels. The return value is the
7154 result of this rounding.
7155 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7156 (window, vscroll, pixels_p)
7157 Lisp_Object window, vscroll, pixels_p;
7158 {
7159 struct window *w;
7160 struct frame *f;
7161
7162 if (NILP (window))
7163 window = selected_window;
7164 else
7165 CHECK_WINDOW (window);
7166 CHECK_NUMBER_OR_FLOAT (vscroll);
7167
7168 w = XWINDOW (window);
7169 f = XFRAME (w->frame);
7170
7171 if (FRAME_WINDOW_P (f))
7172 {
7173 int old_dy = w->vscroll;
7174
7175 w->vscroll = - (NILP (pixels_p)
7176 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
7177 : XFLOATINT (vscroll));
7178 w->vscroll = min (w->vscroll, 0);
7179
7180 if (w->vscroll != old_dy)
7181 {
7182 /* Adjust glyph matrix of the frame if the virtual display
7183 area becomes larger than before. */
7184 if (w->vscroll < 0 && w->vscroll < old_dy)
7185 adjust_glyphs (f);
7186
7187 /* Prevent redisplay shortcuts. */
7188 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
7189 }
7190 }
7191
7192 return Fwindow_vscroll (window, pixels_p);
7193 }
7194
7195 \f
7196 /* Call FN for all leaf windows on frame F. FN is called with the
7197 first argument being a pointer to the leaf window, and with
7198 additional argument USER_DATA. Stops when FN returns 0. */
7199
7200 void
7201 foreach_window (f, fn, user_data)
7202 struct frame *f;
7203 int (* fn) P_ ((struct window *, void *));
7204 void *user_data;
7205 {
7206 /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7207 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
7208 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7209 }
7210
7211
7212 /* Helper function for foreach_window. Call FN for all leaf windows
7213 reachable from W. FN is called with the first argument being a
7214 pointer to the leaf window, and with additional argument USER_DATA.
7215 Stop when FN returns 0. Value is 0 if stopped by FN. */
7216
7217 static int
7218 foreach_window_1 (w, fn, user_data)
7219 struct window *w;
7220 int (* fn) P_ ((struct window *, void *));
7221 void *user_data;
7222 {
7223 int cont;
7224
7225 for (cont = 1; w && cont;)
7226 {
7227 if (!NILP (w->hchild))
7228 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
7229 else if (!NILP (w->vchild))
7230 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
7231 else
7232 cont = fn (w, user_data);
7233
7234 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7235 }
7236
7237 return cont;
7238 }
7239
7240
7241 /* Freeze or unfreeze the window start of W unless it is a
7242 mini-window or the selected window. FREEZE_P non-null means freeze
7243 the window start. */
7244
7245 static int
7246 freeze_window_start (w, freeze_p)
7247 struct window *w;
7248 void *freeze_p;
7249 {
7250 if (MINI_WINDOW_P (w)
7251 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
7252 && (w == XWINDOW (selected_window)
7253 || (MINI_WINDOW_P (XWINDOW (selected_window))
7254 && ! NILP (Vminibuf_scroll_window)
7255 && w == XWINDOW (Vminibuf_scroll_window)))))
7256 freeze_p = NULL;
7257
7258 w->frozen_window_start_p = freeze_p != NULL;
7259 return 1;
7260 }
7261
7262
7263 /* Freeze or unfreeze the window starts of all leaf windows on frame
7264 F, except the selected window and a mini-window. FREEZE_P non-zero
7265 means freeze the window start. */
7266
7267 void
7268 freeze_window_starts (f, freeze_p)
7269 struct frame *f;
7270 int freeze_p;
7271 {
7272 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7273 }
7274
7275 \f
7276 /***********************************************************************
7277 Initialization
7278 ***********************************************************************/
7279
7280 /* Return 1 if window configurations C1 and C2
7281 describe the same state of affairs. This is used by Fequal. */
7282
7283 int
7284 compare_window_configurations (c1, c2, ignore_positions)
7285 Lisp_Object c1, c2;
7286 int ignore_positions;
7287 {
7288 register struct save_window_data *d1, *d2;
7289 struct Lisp_Vector *sw1, *sw2;
7290 int i;
7291
7292 CHECK_WINDOW_CONFIGURATION (c1);
7293 CHECK_WINDOW_CONFIGURATION (c2);
7294
7295 d1 = (struct save_window_data *) XVECTOR (c1);
7296 d2 = (struct save_window_data *) XVECTOR (c2);
7297 sw1 = XVECTOR (d1->saved_windows);
7298 sw2 = XVECTOR (d2->saved_windows);
7299
7300 if (d1->frame_cols != d2->frame_cols)
7301 return 0;
7302 if (d1->frame_lines != d2->frame_lines)
7303 return 0;
7304 if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines)
7305 return 0;
7306 if (! EQ (d1->selected_frame, d2->selected_frame))
7307 return 0;
7308 /* Don't compare the current_window field directly.
7309 Instead see w1_is_current and w2_is_current, below. */
7310 if (! EQ (d1->current_buffer, d2->current_buffer))
7311 return 0;
7312 if (! ignore_positions)
7313 {
7314 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
7315 return 0;
7316 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
7317 return 0;
7318 }
7319 /* Don't compare the root_window field.
7320 We don't require the two configurations
7321 to use the same window object,
7322 and the two root windows must be equivalent
7323 if everything else compares equal. */
7324 if (! EQ (d1->focus_frame, d2->focus_frame))
7325 return 0;
7326
7327 /* Verify that the two confis have the same number of windows. */
7328 if (sw1->size != sw2->size)
7329 return 0;
7330
7331 for (i = 0; i < sw1->size; i++)
7332 {
7333 struct saved_window *p1, *p2;
7334 int w1_is_current, w2_is_current;
7335
7336 p1 = SAVED_WINDOW_N (sw1, i);
7337 p2 = SAVED_WINDOW_N (sw2, i);
7338
7339 /* Verify that the current windows in the two
7340 configurations correspond to each other. */
7341 w1_is_current = EQ (d1->current_window, p1->window);
7342 w2_is_current = EQ (d2->current_window, p2->window);
7343
7344 if (w1_is_current != w2_is_current)
7345 return 0;
7346
7347 /* Verify that the corresponding windows do match. */
7348 if (! EQ (p1->buffer, p2->buffer))
7349 return 0;
7350 if (! EQ (p1->left_col, p2->left_col))
7351 return 0;
7352 if (! EQ (p1->top_line, p2->top_line))
7353 return 0;
7354 if (! EQ (p1->total_cols, p2->total_cols))
7355 return 0;
7356 if (! EQ (p1->total_lines, p2->total_lines))
7357 return 0;
7358 if (! EQ (p1->display_table, p2->display_table))
7359 return 0;
7360 if (! EQ (p1->parent, p2->parent))
7361 return 0;
7362 if (! EQ (p1->prev, p2->prev))
7363 return 0;
7364 if (! ignore_positions)
7365 {
7366 if (! EQ (p1->hscroll, p2->hscroll))
7367 return 0;
7368 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7369 return 0;
7370 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7371 return 0;
7372 if (NILP (Fequal (p1->start, p2->start)))
7373 return 0;
7374 if (NILP (Fequal (p1->pointm, p2->pointm)))
7375 return 0;
7376 if (NILP (Fequal (p1->mark, p2->mark)))
7377 return 0;
7378 }
7379 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7380 return 0;
7381 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7382 return 0;
7383 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7384 return 0;
7385 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7386 return 0;
7387 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7388 return 0;
7389 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7390 return 0;
7391 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7392 return 0;
7393 }
7394
7395 return 1;
7396 }
7397
7398 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7399 Scompare_window_configurations, 2, 2, 0,
7400 doc: /* Compare two window configurations as regards the structure of windows.
7401 This function ignores details such as the values of point and mark
7402 and scrolling positions. */)
7403 (x, y)
7404 Lisp_Object x, y;
7405 {
7406 if (compare_window_configurations (x, y, 1))
7407 return Qt;
7408 return Qnil;
7409 }
7410 \f
7411 void
7412 init_window_once ()
7413 {
7414 struct frame *f = make_initial_frame ();
7415 XSETFRAME (selected_frame, f);
7416 Vterminal_frame = selected_frame;
7417 minibuf_window = f->minibuffer_window;
7418 selected_window = f->selected_window;
7419 last_nonminibuf_frame = f;
7420
7421 window_initialized = 1;
7422 }
7423
7424 void
7425 init_window ()
7426 {
7427 Vwindow_list = Qnil;
7428 }
7429
7430 void
7431 syms_of_window ()
7432 {
7433 Qscroll_up = intern ("scroll-up");
7434 staticpro (&Qscroll_up);
7435
7436 Qscroll_down = intern ("scroll-down");
7437 staticpro (&Qscroll_down);
7438
7439 Qwindow_size_fixed = intern ("window-size-fixed");
7440 staticpro (&Qwindow_size_fixed);
7441 Fset (Qwindow_size_fixed, Qnil);
7442
7443 staticpro (&Qwindow_configuration_change_hook);
7444 Qwindow_configuration_change_hook
7445 = intern ("window-configuration-change-hook");
7446
7447 Qwindowp = intern ("windowp");
7448 staticpro (&Qwindowp);
7449
7450 Qwindow_configuration_p = intern ("window-configuration-p");
7451 staticpro (&Qwindow_configuration_p);
7452
7453 Qwindow_live_p = intern ("window-live-p");
7454 staticpro (&Qwindow_live_p);
7455
7456 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
7457 staticpro (&Qtemp_buffer_show_hook);
7458
7459 staticpro (&Vwindow_list);
7460
7461 minibuf_selected_window = Qnil;
7462 staticpro (&minibuf_selected_window);
7463
7464 window_scroll_pixel_based_preserve_x = -1;
7465 window_scroll_pixel_based_preserve_y = -1;
7466 window_scroll_preserve_hpos = -1;
7467 window_scroll_preserve_vpos = -1;
7468
7469 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7470 doc: /* Non-nil means call as function to display a help buffer.
7471 The function is called with one argument, the buffer to be displayed.
7472 Used by `with-output-to-temp-buffer'.
7473 If this function is used, then it must do the entire job of showing
7474 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7475 Vtemp_buffer_show_function = Qnil;
7476
7477 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
7478 doc: /* If non-nil, function to call to handle `display-buffer'.
7479 It will receive two args, the buffer and a flag which if non-nil means
7480 that the currently selected window is not acceptable.
7481 It should choose or create a window, display the specified buffer in it,
7482 and return the window.
7483 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7484 work using this function. */);
7485 Vdisplay_buffer_function = Qnil;
7486
7487 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
7488 doc: /* *If non-nil, `display-buffer' should even the window heights.
7489 If nil, `display-buffer' will leave the window configuration alone. */);
7490 Veven_window_heights = Qt;
7491
7492 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7493 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7494 Vminibuf_scroll_window = Qnil;
7495
7496 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7497 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7498 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7499 is displayed in the `mode-line' face. */);
7500 mode_line_in_non_selected_windows = 1;
7501
7502 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7503 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7504 Vother_window_scroll_buffer = Qnil;
7505
7506 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
7507 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
7508 pop_up_frames = 0;
7509
7510 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7511 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7512 auto_window_vscroll_p = 1;
7513
7514 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
7515 doc: /* *Non-nil means `display-buffer' should reuse frames.
7516 If the buffer in question is already displayed in a frame, raise that frame. */);
7517 display_buffer_reuse_frames = 0;
7518
7519 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
7520 doc: /* Function to call to handle automatic new frame creation.
7521 It is called with no arguments and should return a newly created frame.
7522
7523 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7524 where `pop-up-frame-alist' would hold the default frame parameters. */);
7525 Vpop_up_frame_function = Qnil;
7526
7527 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
7528 doc: /* *List of buffer names that should have their own special frames.
7529 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7530 if its name is in this list, makes a special frame for it
7531 using `special-display-function'. See also `special-display-regexps'.
7532
7533 An element of the list can be a list instead of just a string.
7534 There are two ways to use a list as an element:
7535 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7536 In the first case, the FRAME-PARAMETERS are pairs of the form
7537 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7538 In the second case, FUNCTION is called with BUFFER as the first argument,
7539 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7540 All this is done by the function found in `special-display-function'.
7541
7542 If the specified frame parameters include (same-buffer . t), the
7543 buffer is displayed in the currently selected window. Otherwise, if
7544 they include (same-frame . t), the buffer is displayed in a new window
7545 in the currently selected frame.
7546
7547 If this variable appears \"not to work\", because you add a name to it
7548 but that buffer still appears in the selected window, look at the
7549 values of `same-window-buffer-names' and `same-window-regexps'.
7550 Those variables take precedence over this one. */);
7551 Vspecial_display_buffer_names = Qnil;
7552
7553 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
7554 doc: /* *List of regexps saying which buffers should have their own special frames.
7555 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7556 if any regexp in this list matches the buffer name, it makes a
7557 special frame for the buffer by calling `special-display-function'.
7558
7559 An element of the list can be a list instead of just a string.
7560 There are two ways to use a list as an element:
7561 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7562 In the first case, the FRAME-PARAMETERS are pairs of the form
7563 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7564 In the second case, FUNCTION is called with BUFFER as the first argument,
7565 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7566 All this is done by the function found in `special-display-function'.
7567
7568 If the specified frame parameters include (same-buffer . t), the
7569 buffer is displayed in the currently selected window. Otherwise, if
7570 they include (same-frame . t), the buffer is displayed in a new window
7571 in the currently selected frame.
7572
7573 If this variable appears \"not to work\", because you add a regexp to it
7574 but the matching buffers still appear in the selected window, look at the
7575 values of `same-window-buffer-names' and `same-window-regexps'.
7576 Those variables take precedence over this one. */);
7577 Vspecial_display_regexps = Qnil;
7578
7579 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
7580 doc: /* Function to call to make a new frame for a special buffer.
7581 It is called with two arguments, the buffer and optional buffer specific
7582 data, and should return a window displaying that buffer.
7583 The default value normally makes a separate frame for the buffer,
7584 using `special-display-frame-alist' to specify the frame parameters.
7585 But if the buffer specific data includes (same-buffer . t) then the
7586 buffer is displayed in the current selected window.
7587 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7588 a new window in the currently selected frame.
7589
7590 A buffer is special if it is listed in `special-display-buffer-names'
7591 or matches a regexp in `special-display-regexps'. */);
7592 Vspecial_display_function = Qnil;
7593
7594 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
7595 doc: /* *List of buffer names that should appear in the selected window.
7596 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7597 switches to it in the selected window, rather than making it appear
7598 in some other window.
7599
7600 An element of the list can be a cons cell instead of just a string.
7601 Then the car must be a string, which specifies the buffer name.
7602 This is for compatibility with `special-display-buffer-names';
7603 the cdr of the cons cell is ignored.
7604
7605 See also `same-window-regexps'. */);
7606 Vsame_window_buffer_names = Qnil;
7607
7608 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
7609 doc: /* *List of regexps saying which buffers should appear in the selected window.
7610 If a buffer name matches one of these regexps, then displaying it
7611 using `display-buffer' or `pop-to-buffer' switches to it
7612 in the selected window, rather than making it appear in some other window.
7613
7614 An element of the list can be a cons cell instead of just a string.
7615 Then the car must be a string, which specifies the buffer name.
7616 This is for compatibility with `special-display-buffer-names';
7617 the cdr of the cons cell is ignored.
7618
7619 See also `same-window-buffer-names'. */);
7620 Vsame_window_regexps = Qnil;
7621
7622 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
7623 doc: /* *Non-nil means display-buffer should make new windows. */);
7624 pop_up_windows = 1;
7625
7626 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7627 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7628 next_screen_context_lines = 2;
7629
7630 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
7631 doc: /* *A window must be at least this tall to be eligible for splitting
7632 by `display-buffer'. The value is in line units.
7633 If there is only one window, it is split regardless of this value. */);
7634 split_height_threshold = 500;
7635
7636 DEFVAR_LISP ("split-window-preferred-function",
7637 &Vsplit_window_preferred_function,
7638 doc: /* Function to use to split a window.
7639 This is used by `display-buffer' to allow the user to choose whether
7640 to split windows horizontally or vertically or some mix of the two.
7641 When this variable is nil, `display-buffer' splits windows vertically.
7642 Otherwise, `display-buffer' calls this function to split a window.
7643 It is called with a window as single argument and should split it in two
7644 and return the new window, or return an appropriate existing window
7645 if splitting is not eligible. */);
7646 Vsplit_window_preferred_function = Qnil;
7647
7648 DEFVAR_INT ("window-min-height", &window_min_height,
7649 doc: /* Allow deleting windows less than this tall.
7650 The value is measured in line units. If a window wants a modeline it
7651 is counted as one line.
7652
7653 Emacs honors settings of this variable when enlarging or shrinking
7654 windows vertically. A value less than 1 is invalid. */);
7655 window_min_height = 4;
7656
7657 DEFVAR_INT ("window-min-width", &window_min_width,
7658 doc: /* Allow deleting windows less than this wide.
7659 The value is measured in characters and includes any fringes or
7660 the scrollbar.
7661
7662 Emacs honors settings of this variable when enlarging or shrinking
7663 windows horizontally. A value less than 2 is invalid. */);
7664 window_min_width = 10;
7665
7666 DEFVAR_LISP ("scroll-preserve-screen-position",
7667 &Vscroll_preserve_screen_position,
7668 doc: /* *Controls if scroll commands move point to keep its screen position unchanged.
7669 A value of nil means point does not keep its screen position except
7670 at the scroll margin or window boundary respectively.
7671 A value of t means point keeps its screen position if the scroll
7672 command moved it vertically out of the window, e.g. when scrolling
7673 by full screens.
7674 Any other value means point always keeps its screen position. */);
7675 Vscroll_preserve_screen_position = Qnil;
7676
7677 DEFVAR_LISP ("window-configuration-change-hook",
7678 &Vwindow_configuration_change_hook,
7679 doc: /* Functions to call when window configuration changes.
7680 The buffer-local part is run once per window, with the relevant window
7681 selected; while the global part is run only once for the modified frame,
7682 with the relevant frame selected. */);
7683 Vwindow_configuration_change_hook = Qnil;
7684
7685 defsubr (&Sselected_window);
7686 defsubr (&Sminibuffer_window);
7687 defsubr (&Swindow_minibuffer_p);
7688 defsubr (&Swindowp);
7689 defsubr (&Swindow_live_p);
7690 defsubr (&Spos_visible_in_window_p);
7691 defsubr (&Swindow_line_height);
7692 defsubr (&Swindow_buffer);
7693 defsubr (&Swindow_height);
7694 defsubr (&Swindow_width);
7695 defsubr (&Swindow_full_width_p);
7696 defsubr (&Swindow_hscroll);
7697 defsubr (&Sset_window_hscroll);
7698 defsubr (&Swindow_redisplay_end_trigger);
7699 defsubr (&Sset_window_redisplay_end_trigger);
7700 defsubr (&Swindow_edges);
7701 defsubr (&Swindow_pixel_edges);
7702 defsubr (&Swindow_inside_edges);
7703 defsubr (&Swindow_inside_pixel_edges);
7704 defsubr (&Scoordinates_in_window_p);
7705 defsubr (&Swindow_at);
7706 defsubr (&Swindow_point);
7707 defsubr (&Swindow_start);
7708 defsubr (&Swindow_end);
7709 defsubr (&Sset_window_point);
7710 defsubr (&Sset_window_start);
7711 defsubr (&Swindow_dedicated_p);
7712 defsubr (&Sset_window_dedicated_p);
7713 defsubr (&Swindow_display_table);
7714 defsubr (&Sset_window_display_table);
7715 defsubr (&Snext_window);
7716 defsubr (&Sprevious_window);
7717 defsubr (&Sother_window);
7718 defsubr (&Sget_lru_window);
7719 defsubr (&Sget_largest_window);
7720 defsubr (&Sget_buffer_window);
7721 defsubr (&Sdelete_other_windows);
7722 defsubr (&Sdelete_windows_on);
7723 defsubr (&Sreplace_buffer_in_windows);
7724 defsubr (&Sdelete_window);
7725 defsubr (&Sset_window_buffer);
7726 defsubr (&Sselect_window);
7727 defsubr (&Sspecial_display_p);
7728 defsubr (&Ssame_window_p);
7729 defsubr (&Sdisplay_buffer);
7730 defsubr (&Sforce_window_update);
7731 defsubr (&Ssplit_window);
7732 defsubr (&Senlarge_window);
7733 defsubr (&Sshrink_window);
7734 defsubr (&Sadjust_window_trailing_edge);
7735 defsubr (&Sscroll_up);
7736 defsubr (&Sscroll_down);
7737 defsubr (&Sscroll_left);
7738 defsubr (&Sscroll_right);
7739 defsubr (&Sother_window_for_scrolling);
7740 defsubr (&Sscroll_other_window);
7741 defsubr (&Sminibuffer_selected_window);
7742 defsubr (&Srecenter);
7743 defsubr (&Swindow_text_height);
7744 defsubr (&Smove_to_window_line);
7745 defsubr (&Swindow_configuration_p);
7746 defsubr (&Swindow_configuration_frame);
7747 defsubr (&Sset_window_configuration);
7748 defsubr (&Scurrent_window_configuration);
7749 defsubr (&Ssave_window_excursion);
7750 defsubr (&Swindow_tree);
7751 defsubr (&Sset_window_margins);
7752 defsubr (&Swindow_margins);
7753 defsubr (&Sset_window_fringes);
7754 defsubr (&Swindow_fringes);
7755 defsubr (&Sset_window_scroll_bars);
7756 defsubr (&Swindow_scroll_bars);
7757 defsubr (&Swindow_vscroll);
7758 defsubr (&Sset_window_vscroll);
7759 defsubr (&Scompare_window_configurations);
7760 defsubr (&Swindow_list);
7761 defsubr (&Swindow_parameters);
7762 defsubr (&Swindow_parameter);
7763 defsubr (&Sset_window_parameter);
7764
7765 }
7766
7767 void
7768 keys_of_window ()
7769 {
7770 initial_define_key (control_x_map, '1', "delete-other-windows");
7771 initial_define_key (control_x_map, '2', "split-window");
7772 initial_define_key (control_x_map, '0', "delete-window");
7773 initial_define_key (control_x_map, 'o', "other-window");
7774 initial_define_key (control_x_map, '^', "enlarge-window");
7775 initial_define_key (control_x_map, '<', "scroll-left");
7776 initial_define_key (control_x_map, '>', "scroll-right");
7777
7778 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7779 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7780 initial_define_key (meta_map, 'v', "scroll-down");
7781
7782 initial_define_key (global_map, Ctl('L'), "recenter");
7783 initial_define_key (meta_map, 'r', "move-to-window-line");
7784 }
7785
7786 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7787 (do not change this comment) */