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