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