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