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