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