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