]> code.delx.au - gnu-emacs/blob - src/window.c
Changes from yesterday
[gnu-emacs] / 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 EXFUN (Fset_window_fringes, 4);
2711 EXFUN (Fset_window_scroll_bars, 4);
2712
2713 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2714 means it's allowed to run hooks. See make_frame for a case where
2715 it's not allowed. KEEP_MARGINS_P non-zero means that the current
2716 margins, fringes, and scroll-bar settings of the window are not
2717 reset from the buffer's local settings. */
2718
2719 void
2720 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
2721 Lisp_Object window, buffer;
2722 int run_hooks_p, keep_margins_p;
2723 {
2724 struct window *w = XWINDOW (window);
2725 struct buffer *b = XBUFFER (buffer);
2726 int count = SPECPDL_INDEX ();
2727
2728 w->buffer = buffer;
2729
2730 if (EQ (window, selected_window))
2731 b->last_selected_window = window;
2732
2733 /* Update time stamps of buffer display. */
2734 if (INTEGERP (b->display_count))
2735 XSETINT (b->display_count, XINT (b->display_count) + 1);
2736 b->display_time = Fcurrent_time ();
2737
2738 XSETFASTINT (w->window_end_pos, 0);
2739 XSETFASTINT (w->window_end_vpos, 0);
2740 bzero (&w->last_cursor, sizeof w->last_cursor);
2741 w->window_end_valid = Qnil;
2742 w->hscroll = w->min_hscroll = make_number (0);
2743 w->vscroll = 0;
2744 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2745 set_marker_restricted (w->start,
2746 make_number (b->last_window_start),
2747 buffer);
2748 w->start_at_line_beg = Qnil;
2749 w->force_start = Qnil;
2750 XSETFASTINT (w->last_modified, 0);
2751 XSETFASTINT (w->last_overlay_modified, 0);
2752 windows_or_buffers_changed++;
2753
2754 /* We must select BUFFER for running the window-scroll-functions.
2755 If WINDOW is selected, switch permanently.
2756 Otherwise, switch but go back to the ambient buffer afterward. */
2757 if (EQ (window, selected_window))
2758 Fset_buffer (buffer);
2759 /* We can't check ! NILP (Vwindow_scroll_functions) here
2760 because that might itself be a local variable. */
2761 else if (window_initialized)
2762 {
2763 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2764 Fset_buffer (buffer);
2765 }
2766
2767 if (!keep_margins_p)
2768 {
2769 /* Set left and right marginal area width etc. from buffer. */
2770
2771 /* This may call adjust_window_margins three times, so
2772 temporarily disable window margins. */
2773 w->left_margin_cols = w->right_margin_cols = Qnil;
2774
2775 Fset_window_fringes (window,
2776 b->left_fringe_width, b->right_fringe_width,
2777 b->fringes_outside_margins);
2778
2779 Fset_window_scroll_bars (window,
2780 b->scroll_bar_width,
2781 b->vertical_scroll_bar_type, Qnil);
2782
2783 Fset_window_margins (window,
2784 b->left_margin_cols, b->right_margin_cols);
2785 }
2786
2787 if (run_hooks_p)
2788 {
2789 if (! NILP (Vwindow_scroll_functions))
2790 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2791 Fmarker_position (w->start));
2792
2793 if (! NILP (Vwindow_configuration_change_hook)
2794 && ! NILP (Vrun_hooks))
2795 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2796 }
2797
2798 unbind_to (count, Qnil);
2799 }
2800
2801
2802 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
2803 doc: /* Make WINDOW display BUFFER as its contents.
2804 BUFFER can be a buffer or buffer name.
2805 Optional third arg KEEP_MARGINS non-nil means that WINDOW's current
2806 display margins, fringe widths, and scroll bar settings are maintained;
2807 the default is to reset these from BUFFER's local settings or the frame
2808 defaults. */)
2809 (window, buffer, keep_margins)
2810 register Lisp_Object window, buffer, keep_margins;
2811 {
2812 register Lisp_Object tem;
2813 register struct window *w = decode_window (window);
2814
2815 XSETWINDOW (window, w);
2816 buffer = Fget_buffer (buffer);
2817 CHECK_BUFFER (buffer);
2818
2819 if (NILP (XBUFFER (buffer)->name))
2820 error ("Attempt to display deleted buffer");
2821
2822 tem = w->buffer;
2823 if (NILP (tem))
2824 error ("Window is deleted");
2825 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2826 is first being set up. */
2827 {
2828 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2829 error ("Window is dedicated to `%s'",
2830 SDATA (XBUFFER (tem)->name));
2831
2832 unshow_buffer (w);
2833 }
2834
2835 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
2836 return Qnil;
2837 }
2838
2839 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
2840 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
2841 If WINDOW is not already selected, also make WINDOW's buffer current.
2842 Also make WINDOW the frame's selected window.
2843 Optional second arg NORECORD non-nil means
2844 do not put this buffer at the front of the list of recently selected ones.
2845
2846 Note that the main editor command loop
2847 selects the buffer of the selected window before each command. */)
2848 (window, norecord)
2849 register Lisp_Object window, norecord;
2850 {
2851 register struct window *w;
2852 register struct window *ow;
2853 struct frame *sf;
2854
2855 CHECK_LIVE_WINDOW (window);
2856
2857 w = XWINDOW (window);
2858 w->frozen_window_start_p = 0;
2859
2860 XSETFASTINT (w->use_time, ++window_select_count);
2861 if (EQ (window, selected_window))
2862 return window;
2863
2864 if (!NILP (selected_window))
2865 {
2866 ow = XWINDOW (selected_window);
2867 if (! NILP (ow->buffer))
2868 set_marker_both (ow->pointm, ow->buffer,
2869 BUF_PT (XBUFFER (ow->buffer)),
2870 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2871 }
2872
2873 selected_window = window;
2874 sf = SELECTED_FRAME ();
2875 if (XFRAME (WINDOW_FRAME (w)) != sf)
2876 {
2877 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2878 /* Use this rather than Fhandle_switch_frame
2879 so that FRAME_FOCUS_FRAME is moved appropriately as we
2880 move around in the state where a minibuffer in a separate
2881 frame is active. */
2882 Fselect_frame (WINDOW_FRAME (w), Qnil);
2883 }
2884 else
2885 sf->selected_window = window;
2886
2887 if (NILP (norecord))
2888 record_buffer (w->buffer);
2889 Fset_buffer (w->buffer);
2890
2891 XBUFFER (w->buffer)->last_selected_window = window;
2892
2893 /* Go to the point recorded in the window.
2894 This is important when the buffer is in more
2895 than one window. It also matters when
2896 redisplay_window has altered point after scrolling,
2897 because it makes the change only in the window. */
2898 {
2899 register int new_point = marker_position (w->pointm);
2900 if (new_point < BEGV)
2901 SET_PT (BEGV);
2902 else if (new_point > ZV)
2903 SET_PT (ZV);
2904 else
2905 SET_PT (new_point);
2906 }
2907
2908 windows_or_buffers_changed++;
2909 return window;
2910 }
2911
2912 static Lisp_Object
2913 select_window_norecord (window)
2914 Lisp_Object window;
2915 {
2916 return Fselect_window (window, Qt);
2917 }
2918 \f
2919 /* Deiconify the frame containing the window WINDOW,
2920 unless it is the selected frame;
2921 then return WINDOW.
2922
2923 The reason for the exception for the selected frame
2924 is that it seems better not to change the selected frames visibility
2925 merely because of displaying a different buffer in it.
2926 The deiconification is useful when a buffer gets shown in
2927 another frame that you were not using lately. */
2928
2929 static Lisp_Object
2930 display_buffer_1 (window)
2931 Lisp_Object window;
2932 {
2933 Lisp_Object frame = XWINDOW (window)->frame;
2934 FRAME_PTR f = XFRAME (frame);
2935
2936 FRAME_SAMPLE_VISIBILITY (f);
2937
2938 if (!EQ (frame, selected_frame))
2939 {
2940 if (FRAME_ICONIFIED_P (f))
2941 Fmake_frame_visible (frame);
2942 else if (FRAME_VISIBLE_P (f))
2943 Fraise_frame (frame);
2944 }
2945
2946 return window;
2947 }
2948
2949 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2950 doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
2951 The value is actually t if the frame should be called with default frame
2952 parameters, and a list of frame parameters if they were specified.
2953 See `special-display-buffer-names', and `special-display-regexps'. */)
2954 (buffer_name)
2955 Lisp_Object buffer_name;
2956 {
2957 Lisp_Object tem;
2958
2959 CHECK_STRING (buffer_name);
2960
2961 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2962 if (!NILP (tem))
2963 return Qt;
2964
2965 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2966 if (!NILP (tem))
2967 return XCDR (tem);
2968
2969 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2970 {
2971 Lisp_Object car = XCAR (tem);
2972 if (STRINGP (car)
2973 && fast_string_match (car, buffer_name) >= 0)
2974 return Qt;
2975 else if (CONSP (car)
2976 && STRINGP (XCAR (car))
2977 && fast_string_match (XCAR (car), buffer_name) >= 0)
2978 return XCDR (car);
2979 }
2980 return Qnil;
2981 }
2982
2983 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2984 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
2985 See `same-window-buffer-names' and `same-window-regexps'. */)
2986 (buffer_name)
2987 Lisp_Object buffer_name;
2988 {
2989 Lisp_Object tem;
2990
2991 CHECK_STRING (buffer_name);
2992
2993 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2994 if (!NILP (tem))
2995 return Qt;
2996
2997 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2998 if (!NILP (tem))
2999 return Qt;
3000
3001 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3002 {
3003 Lisp_Object car = XCAR (tem);
3004 if (STRINGP (car)
3005 && fast_string_match (car, buffer_name) >= 0)
3006 return Qt;
3007 else if (CONSP (car)
3008 && STRINGP (XCAR (car))
3009 && fast_string_match (XCAR (car), buffer_name) >= 0)
3010 return Qt;
3011 }
3012 return Qnil;
3013 }
3014
3015 /* Use B so the default is (other-buffer). */
3016 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3017 "BDisplay buffer: \nP",
3018 doc: /* Make BUFFER appear in some window but don't select it.
3019 BUFFER can be a buffer or a buffer name.
3020 If BUFFER is shown already in some window, just use that one,
3021 unless the window is the selected window and the optional second
3022 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3023 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3024 Returns the window displaying BUFFER.
3025 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3026 displaying BUFFER, then simply raise that frame.
3027
3028 The variables `special-display-buffer-names', `special-display-regexps',
3029 `same-window-buffer-names', and `same-window-regexps' customize how certain
3030 buffer names are handled.
3031
3032 If optional argument FRAME is `visible', search all visible frames.
3033 If FRAME is 0, search all visible and iconified frames.
3034 If FRAME is t, search all frames.
3035 If FRAME is a frame, search only that frame.
3036 If FRAME is nil, search only the selected frame
3037 (actually the last nonminibuffer frame),
3038 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3039 which means search visible and iconified frames.
3040
3041 If `even-window-heights' is non-nil, window heights will be evened out
3042 if displaying the buffer causes two vertically adjacent windows to be
3043 displayed. */)
3044 (buffer, not_this_window, frame)
3045 register Lisp_Object buffer, not_this_window, frame;
3046 {
3047 register Lisp_Object window, tem, swp;
3048 struct frame *f;
3049
3050 swp = Qnil;
3051 buffer = Fget_buffer (buffer);
3052 CHECK_BUFFER (buffer);
3053
3054 if (!NILP (Vdisplay_buffer_function))
3055 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3056
3057 if (NILP (not_this_window)
3058 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3059 return display_buffer_1 (selected_window);
3060
3061 /* See if the user has specified this buffer should appear
3062 in the selected window. */
3063 if (NILP (not_this_window))
3064 {
3065 swp = Fsame_window_p (XBUFFER (buffer)->name);
3066 if (!NILP (swp) && !no_switch_window (selected_window))
3067 {
3068 Fswitch_to_buffer (buffer, Qnil);
3069 return display_buffer_1 (selected_window);
3070 }
3071 }
3072
3073 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3074 look for a window showing BUFFER on any visible or iconified frame.
3075 Otherwise search only the current frame. */
3076 if (! NILP (frame))
3077 tem = frame;
3078 else if (pop_up_frames
3079 || display_buffer_reuse_frames
3080 || last_nonminibuf_frame == 0)
3081 XSETFASTINT (tem, 0);
3082 else
3083 XSETFRAME (tem, last_nonminibuf_frame);
3084
3085 window = Fget_buffer_window (buffer, tem);
3086 if (!NILP (window)
3087 && (NILP (not_this_window) || !EQ (window, selected_window)))
3088 return display_buffer_1 (window);
3089
3090 /* Certain buffer names get special handling. */
3091 if (!NILP (Vspecial_display_function) && NILP (swp))
3092 {
3093 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3094 if (EQ (tem, Qt))
3095 return call1 (Vspecial_display_function, buffer);
3096 if (CONSP (tem))
3097 return call2 (Vspecial_display_function, buffer, tem);
3098 }
3099
3100 /* If there are no frames open that have more than a minibuffer,
3101 we need to create a new frame. */
3102 if (pop_up_frames || last_nonminibuf_frame == 0)
3103 {
3104 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3105 Fset_window_buffer (window, buffer, Qnil);
3106 return display_buffer_1 (window);
3107 }
3108
3109 f = SELECTED_FRAME ();
3110 if (pop_up_windows
3111 || FRAME_MINIBUF_ONLY_P (f)
3112 /* If the current frame is a special display frame,
3113 don't try to reuse its windows. */
3114 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3115 {
3116 Lisp_Object frames;
3117
3118 frames = Qnil;
3119 if (FRAME_MINIBUF_ONLY_P (f))
3120 XSETFRAME (frames, last_nonminibuf_frame);
3121 /* Don't try to create a window if we would get an error. */
3122 if (split_height_threshold < window_min_height << 1)
3123 split_height_threshold = window_min_height << 1;
3124
3125 /* Note that both Fget_largest_window and Fget_lru_window
3126 ignore minibuffers and dedicated windows.
3127 This means they can return nil. */
3128
3129 /* If the frame we would try to split cannot be split,
3130 try other frames. */
3131 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3132 {
3133 /* Try visible frames first. */
3134 window = Fget_largest_window (Qvisible);
3135 /* If that didn't work, try iconified frames. */
3136 if (NILP (window))
3137 window = Fget_largest_window (make_number (0));
3138 if (NILP (window))
3139 window = Fget_largest_window (Qt);
3140 }
3141 else
3142 window = Fget_largest_window (frames);
3143
3144 /* If we got a tall enough full-width window that can be split,
3145 split it. */
3146 if (!NILP (window)
3147 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3148 && window_height (window) >= split_height_threshold
3149 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3150 window = Fsplit_window (window, Qnil, Qnil);
3151 else
3152 {
3153 Lisp_Object upper, lower, other;
3154
3155 window = Fget_lru_window (frames);
3156 /* If the LRU window is selected, and big enough,
3157 and can be split, split it. */
3158 if (!NILP (window)
3159 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3160 && (EQ (window, selected_window)
3161 || EQ (XWINDOW (window)->parent, Qnil))
3162 && window_height (window) >= window_min_height << 1)
3163 window = Fsplit_window (window, Qnil, Qnil);
3164 /* If Fget_lru_window returned nil, try other approaches. */
3165
3166 /* Try visible frames first. */
3167 if (NILP (window))
3168 window = Fget_buffer_window (buffer, Qvisible);
3169 if (NILP (window))
3170 window = Fget_largest_window (Qvisible);
3171 /* If that didn't work, try iconified frames. */
3172 if (NILP (window))
3173 window = Fget_buffer_window (buffer, make_number (0));
3174 if (NILP (window))
3175 window = Fget_largest_window (make_number (0));
3176 /* Try invisible frames. */
3177 if (NILP (window))
3178 window = Fget_buffer_window (buffer, Qt);
3179 if (NILP (window))
3180 window = Fget_largest_window (Qt);
3181 /* As a last resort, make a new frame. */
3182 if (NILP (window))
3183 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3184 /* If window appears above or below another,
3185 even out their heights. */
3186 other = upper = lower = Qnil;
3187 if (!NILP (XWINDOW (window)->prev))
3188 other = upper = XWINDOW (window)->prev, lower = window;
3189 if (!NILP (XWINDOW (window)->next))
3190 other = lower = XWINDOW (window)->next, upper = window;
3191 if (!NILP (other)
3192 && !NILP (Veven_window_heights)
3193 /* Check that OTHER and WINDOW are vertically arrayed. */
3194 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3195 && (XFASTINT (XWINDOW (other)->total_lines)
3196 > XFASTINT (XWINDOW (window)->total_lines)))
3197 {
3198 int total = (XFASTINT (XWINDOW (other)->total_lines)
3199 + XFASTINT (XWINDOW (window)->total_lines));
3200 enlarge_window (upper,
3201 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3202 0, 0);
3203 }
3204 }
3205 }
3206 else
3207 window = Fget_lru_window (Qnil);
3208
3209 Fset_window_buffer (window, buffer, Qnil);
3210 return display_buffer_1 (window);
3211 }
3212
3213 void
3214 temp_output_buffer_show (buf)
3215 register Lisp_Object buf;
3216 {
3217 register struct buffer *old = current_buffer;
3218 register Lisp_Object window;
3219 register struct window *w;
3220
3221 XBUFFER (buf)->directory = current_buffer->directory;
3222
3223 Fset_buffer (buf);
3224 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3225 BEGV = BEG;
3226 ZV = Z;
3227 SET_PT (BEG);
3228 #if 0 /* rms: there should be no reason for this. */
3229 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3230 #endif
3231 set_buffer_internal (old);
3232
3233 if (!EQ (Vtemp_buffer_show_function, Qnil))
3234 call1 (Vtemp_buffer_show_function, buf);
3235 else
3236 {
3237 window = Fdisplay_buffer (buf, Qnil, Qnil);
3238
3239 if (!EQ (XWINDOW (window)->frame, selected_frame))
3240 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3241 Vminibuf_scroll_window = window;
3242 w = XWINDOW (window);
3243 XSETFASTINT (w->hscroll, 0);
3244 XSETFASTINT (w->min_hscroll, 0);
3245 set_marker_restricted_both (w->start, buf, 1, 1);
3246 set_marker_restricted_both (w->pointm, buf, 1, 1);
3247
3248 /* Run temp-buffer-show-hook, with the chosen window selected
3249 and its buffer current. */
3250 if (!NILP (Vrun_hooks))
3251 {
3252 Lisp_Object tem;
3253 tem = Fboundp (Qtemp_buffer_show_hook);
3254 if (!NILP (tem))
3255 {
3256 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3257 if (!NILP (tem))
3258 {
3259 int count = SPECPDL_INDEX ();
3260 Lisp_Object prev_window, prev_buffer;
3261 prev_window = selected_window;
3262 XSETBUFFER (prev_buffer, old);
3263
3264 /* Select the window that was chosen, for running the hook.
3265 Note: Both Fselect_window and select_window_norecord may
3266 set-buffer to the buffer displayed in the window,
3267 so we need to save the current buffer. --stef */
3268 record_unwind_protect (Fset_buffer, prev_buffer);
3269 record_unwind_protect (select_window_norecord, prev_window);
3270 Fselect_window (window, Qt);
3271 Fset_buffer (w->buffer);
3272 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3273 unbind_to (count, Qnil);
3274 }
3275 }
3276 }
3277 }
3278 }
3279 \f
3280 static void
3281 make_dummy_parent (window)
3282 Lisp_Object window;
3283 {
3284 Lisp_Object new;
3285 register struct window *o, *p;
3286 int i;
3287
3288 o = XWINDOW (window);
3289 p = allocate_window ();
3290 for (i = 0; i < VECSIZE (struct window); ++i)
3291 ((struct Lisp_Vector *) p)->contents[i]
3292 = ((struct Lisp_Vector *)o)->contents[i];
3293 XSETWINDOW (new, p);
3294
3295 XSETFASTINT (p->sequence_number, ++sequence_number);
3296
3297 /* Put new into window structure in place of window */
3298 replace_window (window, new);
3299
3300 o->next = Qnil;
3301 o->prev = Qnil;
3302 o->vchild = Qnil;
3303 o->hchild = Qnil;
3304 o->parent = new;
3305
3306 p->start = Qnil;
3307 p->pointm = Qnil;
3308 p->buffer = Qnil;
3309 }
3310
3311 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3312 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3313 WINDOW defaults to selected one and SIZE to half its size.
3314 If optional third arg HORFLAG is non-nil, split side by side
3315 and put SIZE columns in the first of the pair. In that case,
3316 SIZE includes that window's scroll bar, or the divider column to its right. */)
3317 (window, size, horflag)
3318 Lisp_Object window, size, horflag;
3319 {
3320 register Lisp_Object new;
3321 register struct window *o, *p;
3322 FRAME_PTR fo;
3323 register int size_int;
3324
3325 if (NILP (window))
3326 window = selected_window;
3327 else
3328 CHECK_LIVE_WINDOW (window);
3329
3330 o = XWINDOW (window);
3331 fo = XFRAME (WINDOW_FRAME (o));
3332
3333 if (NILP (size))
3334 {
3335 if (!NILP (horflag))
3336 /* Calculate the size of the left-hand window, by dividing
3337 the usable space in columns by two.
3338 We round up, since the left-hand window may include
3339 a dividing line, while the right-hand may not. */
3340 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3341 else
3342 size_int = XFASTINT (o->total_lines) >> 1;
3343 }
3344 else
3345 {
3346 CHECK_NUMBER (size);
3347 size_int = XINT (size);
3348 }
3349
3350 if (MINI_WINDOW_P (o))
3351 error ("Attempt to split minibuffer window");
3352 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3353 error ("Attempt to split fixed-size window");
3354
3355 check_min_window_sizes ();
3356
3357 if (NILP (horflag))
3358 {
3359 if (size_int < window_min_height)
3360 error ("Window height %d too small (after splitting)", size_int);
3361 if (size_int + window_min_height > XFASTINT (o->total_lines))
3362 error ("Window height %d too small (after splitting)",
3363 XFASTINT (o->total_lines) - size_int);
3364 if (NILP (o->parent)
3365 || NILP (XWINDOW (o->parent)->vchild))
3366 {
3367 make_dummy_parent (window);
3368 new = o->parent;
3369 XWINDOW (new)->vchild = window;
3370 }
3371 }
3372 else
3373 {
3374 if (size_int < window_min_width)
3375 error ("Window width %d too small (after splitting)", size_int);
3376
3377 if (size_int + window_min_width > XFASTINT (o->total_cols))
3378 error ("Window width %d too small (after splitting)",
3379 XFASTINT (o->total_cols) - size_int);
3380 if (NILP (o->parent)
3381 || NILP (XWINDOW (o->parent)->hchild))
3382 {
3383 make_dummy_parent (window);
3384 new = o->parent;
3385 XWINDOW (new)->hchild = window;
3386 }
3387 }
3388
3389 /* Now we know that window's parent is a vertical combination
3390 if we are dividing vertically, or a horizontal combination
3391 if we are making side-by-side windows */
3392
3393 windows_or_buffers_changed++;
3394 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3395 new = make_window ();
3396 p = XWINDOW (new);
3397
3398 p->frame = o->frame;
3399 p->next = o->next;
3400 if (!NILP (p->next))
3401 XWINDOW (p->next)->prev = new;
3402 p->prev = window;
3403 o->next = new;
3404 p->parent = o->parent;
3405 p->buffer = Qt;
3406 p->window_end_valid = Qnil;
3407 bzero (&p->last_cursor, sizeof p->last_cursor);
3408
3409 /* Duplicate special geometry settings. */
3410
3411 p->left_margin_cols = o->left_margin_cols;
3412 p->right_margin_cols = o->right_margin_cols;
3413 p->left_fringe_width = o->left_fringe_width;
3414 p->right_fringe_width = o->right_fringe_width;
3415 p->fringes_outside_margins = o->fringes_outside_margins;
3416 p->scroll_bar_width = o->scroll_bar_width;
3417 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3418
3419 /* Apportion the available frame space among the two new windows */
3420
3421 if (!NILP (horflag))
3422 {
3423 p->total_lines = o->total_lines;
3424 p->top_line = o->top_line;
3425 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3426 XSETFASTINT (o->total_cols, size_int);
3427 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3428 adjust_window_margins (p);
3429 adjust_window_margins (o);
3430 }
3431 else
3432 {
3433 p->left_col = o->left_col;
3434 p->total_cols = o->total_cols;
3435 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3436 XSETFASTINT (o->total_lines, size_int);
3437 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3438 }
3439
3440 /* Adjust glyph matrices. */
3441 adjust_glyphs (fo);
3442
3443 Fset_window_buffer (new, o->buffer, Qt);
3444 return new;
3445 }
3446 \f
3447 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
3448 doc: /* Make current window ARG lines bigger.
3449 From program, optional second arg non-nil means grow sideways ARG columns.
3450 Interactively, if an argument is not given, make the window one line bigger.
3451
3452 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3453 of the siblings above or to the left of the selected window. Only
3454 siblings to the right or below are changed. */)
3455 (arg, side, preserve_before)
3456 register Lisp_Object arg, side, preserve_before;
3457 {
3458 CHECK_NUMBER (arg);
3459 enlarge_window (selected_window, XINT (arg), !NILP (side),
3460 !NILP (preserve_before));
3461
3462 if (! NILP (Vwindow_configuration_change_hook))
3463 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3464
3465 return Qnil;
3466 }
3467
3468 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
3469 doc: /* Make current window ARG lines smaller.
3470 From program, optional second arg non-nil means shrink sideways arg columns.
3471 Interactively, if an argument is not given, make the window one line smaller.
3472
3473 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3474 of the siblings above or to the left of the selected window. Only
3475 siblings to the right or below are changed. */)
3476 (arg, side, preserve_before)
3477 register Lisp_Object arg, side, preserve_before;
3478 {
3479 CHECK_NUMBER (arg);
3480 enlarge_window (selected_window, -XINT (arg), !NILP (side),
3481 !NILP (preserve_before));
3482
3483 if (! NILP (Vwindow_configuration_change_hook))
3484 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3485
3486 return Qnil;
3487 }
3488
3489 int
3490 window_height (window)
3491 Lisp_Object window;
3492 {
3493 register struct window *p = XWINDOW (window);
3494 return WINDOW_TOTAL_LINES (p);
3495 }
3496
3497 int
3498 window_width (window)
3499 Lisp_Object window;
3500 {
3501 register struct window *p = XWINDOW (window);
3502 return WINDOW_TOTAL_COLS (p);
3503 }
3504
3505
3506 #define CURBEG(w) \
3507 *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3508
3509 #define CURSIZE(w) \
3510 *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3511
3512
3513 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3514 increase its width. Siblings of the selected window are resized to
3515 fulfill the size request. If they become too small in the process,
3516 they will be deleted.
3517
3518 If PRESERVE_BEFORE is nonzero, that means don't alter
3519 the siblings to the left or above WINDOW. */
3520
3521 static void
3522 enlarge_window (window, delta, widthflag, preserve_before)
3523 Lisp_Object window;
3524 int delta, widthflag, preserve_before;
3525 {
3526 Lisp_Object parent, next, prev;
3527 struct window *p;
3528 Lisp_Object *sizep;
3529 int maximum;
3530 int (*sizefun) P_ ((Lisp_Object))
3531 = widthflag ? window_width : window_height;
3532 void (*setsizefun) P_ ((Lisp_Object, int, int))
3533 = (widthflag ? set_window_width : set_window_height);
3534
3535 /* Check values of window_min_width and window_min_height for
3536 validity. */
3537 check_min_window_sizes ();
3538
3539 /* Give up if this window cannot be resized. */
3540 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3541 error ("Window is not resizable");
3542
3543 /* Find the parent of the selected window. */
3544 while (1)
3545 {
3546 p = XWINDOW (window);
3547 parent = p->parent;
3548
3549 if (NILP (parent))
3550 {
3551 if (widthflag)
3552 error ("No other window to side of this one");
3553 break;
3554 }
3555
3556 if (widthflag
3557 ? !NILP (XWINDOW (parent)->hchild)
3558 : !NILP (XWINDOW (parent)->vchild))
3559 break;
3560
3561 window = parent;
3562 }
3563
3564 sizep = &CURSIZE (window);
3565
3566 {
3567 register int maxdelta;
3568
3569 /* Compute the maximum size increment this window can have. */
3570
3571 if (preserve_before)
3572 {
3573 if (!NILP (parent))
3574 {
3575 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3576 /* Subtract size of siblings before, since we can't take that. */
3577 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
3578 }
3579 else
3580 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3581 - window_min_size (XWINDOW (p->next),
3582 widthflag, 0, 0))
3583 : (delta = 0));
3584 }
3585 else
3586 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3587 /* This is a main window followed by a minibuffer. */
3588 : !NILP (p->next) ? ((*sizefun) (p->next)
3589 - window_min_size (XWINDOW (p->next),
3590 widthflag, 0, 0))
3591 /* This is a minibuffer following a main window. */
3592 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3593 - window_min_size (XWINDOW (p->prev),
3594 widthflag, 0, 0))
3595 /* This is a frame with only one window, a minibuffer-only
3596 or a minibufferless frame. */
3597 : (delta = 0));
3598
3599 if (delta > maxdelta)
3600 /* This case traps trying to make the minibuffer
3601 the full frame, or make the only window aside from the
3602 minibuffer the full frame. */
3603 delta = maxdelta;
3604 }
3605
3606 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3607 {
3608 delete_window (window);
3609 return;
3610 }
3611
3612 if (delta == 0)
3613 return;
3614
3615 /* Find the total we can get from other siblings without deleting them. */
3616 maximum = 0;
3617 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3618 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3619 widthflag, 0, 0);
3620 if (! preserve_before)
3621 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3622 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3623 widthflag, 0, 0);
3624
3625 /* If we can get it all from them without deleting them, do so. */
3626 if (delta <= maximum)
3627 {
3628 Lisp_Object first_unaffected;
3629 Lisp_Object first_affected;
3630 int fixed_p;
3631
3632 next = p->next;
3633 prev = p->prev;
3634 first_affected = window;
3635 /* Look at one sibling at a time,
3636 moving away from this window in both directions alternately,
3637 and take as much as we can get without deleting that sibling. */
3638 while (delta != 0
3639 && (!NILP (next) || (!preserve_before && !NILP (prev))))
3640 {
3641 if (! NILP (next))
3642 {
3643 int this_one = ((*sizefun) (next)
3644 - window_min_size (XWINDOW (next),
3645 widthflag, 0, &fixed_p));
3646 if (!fixed_p)
3647 {
3648 if (this_one > delta)
3649 this_one = delta;
3650
3651 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3652 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3653
3654 delta -= this_one;
3655 }
3656
3657 next = XWINDOW (next)->next;
3658 }
3659
3660 if (delta == 0)
3661 break;
3662
3663 if (!preserve_before && ! NILP (prev))
3664 {
3665 int this_one = ((*sizefun) (prev)
3666 - window_min_size (XWINDOW (prev),
3667 widthflag, 0, &fixed_p));
3668 if (!fixed_p)
3669 {
3670 if (this_one > delta)
3671 this_one = delta;
3672
3673 first_affected = prev;
3674
3675 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3676 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3677
3678 delta -= this_one;
3679 }
3680
3681 prev = XWINDOW (prev)->prev;
3682 }
3683 }
3684
3685 xassert (delta == 0);
3686
3687 /* Now recalculate the edge positions of all the windows affected,
3688 based on the new sizes. */
3689 first_unaffected = next;
3690 prev = first_affected;
3691 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3692 prev = next, next = XWINDOW (next)->next)
3693 {
3694 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3695 /* This does not change size of NEXT,
3696 but it propagates the new top edge to its children */
3697 (*setsizefun) (next, (*sizefun) (next), 0);
3698 }
3699 }
3700 else
3701 {
3702 register int delta1;
3703 register int opht = (*sizefun) (parent);
3704
3705 if (opht <= XINT (*sizep) + delta)
3706 {
3707 /* If trying to grow this window to or beyond size of the parent,
3708 just delete all the sibling windows. */
3709 Lisp_Object start, tem, next;
3710
3711 start = XWINDOW (parent)->vchild;
3712 if (NILP (start))
3713 start = XWINDOW (parent)->hchild;
3714
3715 /* Delete any siblings that come after WINDOW. */
3716 tem = XWINDOW (window)->next;
3717 while (! NILP (tem))
3718 {
3719 next = XWINDOW (tem)->next;
3720 delete_window (tem);
3721 tem = next;
3722 }
3723
3724 /* Delete any siblings that come after WINDOW.
3725 Note that if START is not WINDOW, then WINDOW still
3726 Fhas siblings, so WINDOW has not yet replaced its parent. */
3727 tem = start;
3728 while (! EQ (tem, window))
3729 {
3730 next = XWINDOW (tem)->next;
3731 delete_window (tem);
3732 tem = next;
3733 }
3734 }
3735 else
3736 {
3737 /* Otherwise, make delta1 just right so that if we add
3738 delta1 lines to this window and to the parent, and then
3739 shrink the parent back to its original size, the new
3740 proportional size of this window will increase by delta.
3741
3742 The function size_window will compute the new height h'
3743 of the window from delta1 as:
3744
3745 e = delta1/n
3746 x = delta1 - delta1/n * n for the 1st resizable child
3747 h' = h + e + x
3748
3749 where n is the number of children that can be resized.
3750 We can ignore x by choosing a delta1 that is a multiple of
3751 n. We want the height of this window to come out as
3752
3753 h' = h + delta
3754
3755 So, delta1 must be
3756
3757 h + e = h + delta
3758 delta1/n = delta
3759 delta1 = n * delta.
3760
3761 The number of children n equals the number of resizable
3762 children of this window + 1 because we know window itself
3763 is resizable (otherwise we would have signalled an error. */
3764
3765 struct window *w = XWINDOW (window);
3766 Lisp_Object s;
3767 int n = 1;
3768
3769 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3770 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3771 ++n;
3772 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3773 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3774 ++n;
3775
3776 delta1 = n * delta;
3777
3778 /* Add delta1 lines or columns to this window, and to the parent,
3779 keeping things consistent while not affecting siblings. */
3780 XSETINT (CURSIZE (parent), opht + delta1);
3781 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3782
3783 /* Squeeze out delta1 lines or columns from our parent,
3784 shriking this window and siblings proportionately.
3785 This brings parent back to correct size.
3786 Delta1 was calculated so this makes this window the desired size,
3787 taking it all out of the siblings. */
3788 (*setsizefun) (parent, opht, 0);
3789
3790 }
3791 }
3792
3793 XSETFASTINT (p->last_modified, 0);
3794 XSETFASTINT (p->last_overlay_modified, 0);
3795
3796 /* Adjust glyph matrices. */
3797 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3798 }
3799
3800 #undef CURBEG
3801 #undef CURSIZE
3802
3803
3804 \f
3805 /***********************************************************************
3806 Resizing Mini-Windows
3807 ***********************************************************************/
3808
3809 static void shrink_window_lowest_first P_ ((struct window *, int));
3810
3811 enum save_restore_action
3812 {
3813 CHECK_ORIG_SIZES,
3814 SAVE_ORIG_SIZES,
3815 RESTORE_ORIG_SIZES
3816 };
3817
3818 static int save_restore_orig_size P_ ((struct window *,
3819 enum save_restore_action));
3820
3821 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3822 from lowest windows first. */
3823
3824 static void
3825 shrink_window_lowest_first (w, height)
3826 struct window *w;
3827 int height;
3828 {
3829 struct window *c;
3830 Lisp_Object child;
3831 int old_height;
3832
3833 xassert (!MINI_WINDOW_P (w));
3834
3835 /* Set redisplay hints. */
3836 XSETFASTINT (w->last_modified, 0);
3837 XSETFASTINT (w->last_overlay_modified, 0);
3838 windows_or_buffers_changed++;
3839 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3840
3841 old_height = XFASTINT (w->total_lines);
3842 XSETFASTINT (w->total_lines, height);
3843
3844 if (!NILP (w->hchild))
3845 {
3846 for (child = w->hchild; !NILP (child); child = c->next)
3847 {
3848 c = XWINDOW (child);
3849 c->top_line = w->top_line;
3850 shrink_window_lowest_first (c, height);
3851 }
3852 }
3853 else if (!NILP (w->vchild))
3854 {
3855 Lisp_Object last_child;
3856 int delta = old_height - height;
3857 int last_top;
3858
3859 last_child = Qnil;
3860
3861 /* Find the last child. We are taking space from lowest windows
3862 first, so we iterate over children from the last child
3863 backwards. */
3864 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3865 last_child = child;
3866
3867 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3868 for (child = last_child; delta && !NILP (child); child = c->prev)
3869 {
3870 int this_one;
3871
3872 c = XWINDOW (child);
3873 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
3874
3875 if (this_one > delta)
3876 this_one = delta;
3877
3878 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
3879 delta -= this_one;
3880 }
3881
3882 /* Compute new positions. */
3883 last_top = XINT (w->top_line);
3884 for (child = w->vchild; !NILP (child); child = c->next)
3885 {
3886 c = XWINDOW (child);
3887 c->top_line = make_number (last_top);
3888 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
3889 last_top += XFASTINT (c->total_lines);
3890 }
3891 }
3892 }
3893
3894
3895 /* Save, restore, or check positions and sizes in the window tree
3896 rooted at W. ACTION says what to do.
3897
3898 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
3899 orig_total_lines members are valid for all windows in the window
3900 tree. Value is non-zero if they are valid.
3901
3902 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3903 orig_top_line and orig_total_lines for all windows in the tree.
3904
3905 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
3906 stored in orig_top_line and orig_total_lines for all windows. */
3907
3908 static int
3909 save_restore_orig_size (w, action)
3910 struct window *w;
3911 enum save_restore_action action;
3912 {
3913 int success_p = 1;
3914
3915 while (w)
3916 {
3917 if (!NILP (w->hchild))
3918 {
3919 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
3920 success_p = 0;
3921 }
3922 else if (!NILP (w->vchild))
3923 {
3924 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
3925 success_p = 0;
3926 }
3927
3928 switch (action)
3929 {
3930 case CHECK_ORIG_SIZES:
3931 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
3932 return 0;
3933 break;
3934
3935 case SAVE_ORIG_SIZES:
3936 w->orig_top_line = w->top_line;
3937 w->orig_total_lines = w->total_lines;
3938 XSETFASTINT (w->last_modified, 0);
3939 XSETFASTINT (w->last_overlay_modified, 0);
3940 break;
3941
3942 case RESTORE_ORIG_SIZES:
3943 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
3944 w->top_line = w->orig_top_line;
3945 w->total_lines = w->orig_total_lines;
3946 w->orig_total_lines = w->orig_top_line = Qnil;
3947 XSETFASTINT (w->last_modified, 0);
3948 XSETFASTINT (w->last_overlay_modified, 0);
3949 break;
3950
3951 default:
3952 abort ();
3953 }
3954
3955 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3956 }
3957
3958 return success_p;
3959 }
3960
3961
3962 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3963 without deleting other windows. */
3964
3965 void
3966 grow_mini_window (w, delta)
3967 struct window *w;
3968 int delta;
3969 {
3970 struct frame *f = XFRAME (w->frame);
3971 struct window *root;
3972
3973 xassert (MINI_WINDOW_P (w));
3974 xassert (delta >= 0);
3975
3976 /* Check values of window_min_width and window_min_height for
3977 validity. */
3978 check_min_window_sizes ();
3979
3980 /* Compute how much we can enlarge the mini-window without deleting
3981 other windows. */
3982 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3983 if (delta)
3984 {
3985 int min_height = window_min_size (root, 0, 0, 0);
3986 if (XFASTINT (root->total_lines) - delta < min_height)
3987 /* Note that the root window may already be smaller than
3988 min_height. */
3989 delta = max (0, XFASTINT (root->total_lines) - min_height);
3990 }
3991
3992 if (delta)
3993 {
3994 /* Save original window sizes and positions, if not already done. */
3995 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
3996 save_restore_orig_size (root, SAVE_ORIG_SIZES);
3997
3998 /* Shrink other windows. */
3999 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4000
4001 /* Grow the mini-window. */
4002 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4003 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4004 XSETFASTINT (w->last_modified, 0);
4005 XSETFASTINT (w->last_overlay_modified, 0);
4006
4007 adjust_glyphs (f);
4008 }
4009 }
4010
4011
4012 /* Shrink mini-window W. If there is recorded info about window sizes
4013 before a call to grow_mini_window, restore recorded window sizes.
4014 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4015 line. */
4016
4017 void
4018 shrink_mini_window (w)
4019 struct window *w;
4020 {
4021 struct frame *f = XFRAME (w->frame);
4022 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4023
4024 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4025 {
4026 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4027 adjust_glyphs (f);
4028 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4029 windows_or_buffers_changed = 1;
4030 }
4031 else if (XFASTINT (w->total_lines) > 1)
4032 {
4033 /* Distribute the additional lines of the mini-window
4034 among the other windows. */
4035 Lisp_Object window;
4036 XSETWINDOW (window, w);
4037 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0);
4038 }
4039 }
4040
4041
4042 \f
4043 /* Mark window cursors off for all windows in the window tree rooted
4044 at W by setting their phys_cursor_on_p flag to zero. Called from
4045 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4046 the frame are cleared. */
4047
4048 void
4049 mark_window_cursors_off (w)
4050 struct window *w;
4051 {
4052 while (w)
4053 {
4054 if (!NILP (w->hchild))
4055 mark_window_cursors_off (XWINDOW (w->hchild));
4056 else if (!NILP (w->vchild))
4057 mark_window_cursors_off (XWINDOW (w->vchild));
4058 else
4059 w->phys_cursor_on_p = 0;
4060
4061 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4062 }
4063 }
4064
4065
4066 /* Return number of lines of text (not counting mode lines) in W. */
4067
4068 int
4069 window_internal_height (w)
4070 struct window *w;
4071 {
4072 int ht = XFASTINT (w->total_lines);
4073
4074 if (!MINI_WINDOW_P (w))
4075 {
4076 if (!NILP (w->parent)
4077 || !NILP (w->vchild)
4078 || !NILP (w->hchild)
4079 || !NILP (w->next)
4080 || !NILP (w->prev)
4081 || WINDOW_WANTS_MODELINE_P (w))
4082 --ht;
4083
4084 if (WINDOW_WANTS_HEADER_LINE_P (w))
4085 --ht;
4086 }
4087
4088 return ht;
4089 }
4090
4091
4092 /* Return the number of columns in W.
4093 Don't count columns occupied by scroll bars or the vertical bar
4094 separating W from the sibling to its right. */
4095
4096 int
4097 window_box_text_cols (w)
4098 struct window *w;
4099 {
4100 struct frame *f = XFRAME (WINDOW_FRAME (w));
4101 int width = XINT (w->total_cols);
4102
4103 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4104 /* Scroll bars occupy a few columns. */
4105 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4106 else if (!FRAME_WINDOW_P (f)
4107 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4108 /* The column of `|' characters separating side-by-side windows
4109 occupies one column only. */
4110 width -= 1;
4111
4112 if (FRAME_WINDOW_P (f))
4113 /* On window-systems, fringes and display margins cannot be
4114 used for normal text. */
4115 width -= (WINDOW_FRINGE_COLS (w)
4116 + WINDOW_LEFT_MARGIN_COLS (w)
4117 + WINDOW_RIGHT_MARGIN_COLS (w));
4118
4119 return width;
4120 }
4121
4122 \f
4123 /************************************************************************
4124 Window Scrolling
4125 ***********************************************************************/
4126
4127 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4128 N screen-fulls, which is defined as the height of the window minus
4129 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4130 instead. Negative values of N mean scroll down. NOERROR non-zero
4131 means don't signal an error if we try to move over BEGV or ZV,
4132 respectively. */
4133
4134 static void
4135 window_scroll (window, n, whole, noerror)
4136 Lisp_Object window;
4137 int n;
4138 int whole;
4139 int noerror;
4140 {
4141 immediate_quit = 1;
4142
4143 /* If we must, use the pixel-based version which is much slower than
4144 the line-based one but can handle varying line heights. */
4145 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4146 window_scroll_pixel_based (window, n, whole, noerror);
4147 else
4148 window_scroll_line_based (window, n, whole, noerror);
4149
4150 immediate_quit = 0;
4151 }
4152
4153
4154 /* Implementation of window_scroll that works based on pixel line
4155 heights. See the comment of window_scroll for parameter
4156 descriptions. */
4157
4158 static void
4159 window_scroll_pixel_based (window, n, whole, noerror)
4160 Lisp_Object window;
4161 int n;
4162 int whole;
4163 int noerror;
4164 {
4165 struct it it;
4166 struct window *w = XWINDOW (window);
4167 struct text_pos start;
4168 Lisp_Object tem;
4169 int this_scroll_margin;
4170 int preserve_y;
4171 /* True if we fiddled the window vscroll field without really scrolling. */
4172 int vscrolled = 0;
4173
4174 SET_TEXT_POS_FROM_MARKER (start, w->start);
4175
4176 /* If PT is not visible in WINDOW, move back one half of
4177 the screen. Allow PT to be partially visible, otherwise
4178 something like (scroll-down 1) with PT in the line before
4179 the partially visible one would recenter. */
4180 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4181 if (NILP (tem))
4182 {
4183 /* Move backward half the height of the window. Performance note:
4184 vmotion used here is about 10% faster, but would give wrong
4185 results for variable height lines. */
4186 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4187 it.current_y = it.last_visible_y;
4188 move_it_vertically (&it, - window_box_height (w) / 2);
4189
4190 /* The function move_iterator_vertically may move over more than
4191 the specified y-distance. If it->w is small, e.g. a
4192 mini-buffer window, we may end up in front of the window's
4193 display area. This is the case when Start displaying at the
4194 start of the line containing PT in this case. */
4195 if (it.current_y <= 0)
4196 {
4197 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4198 move_it_vertically (&it, 0);
4199 it.current_y = 0;
4200 }
4201
4202 start = it.current.pos;
4203 }
4204
4205 /* If scroll_preserve_screen_position is non-zero, we try to set
4206 point in the same window line as it is now, so get that line. */
4207 if (!NILP (Vscroll_preserve_screen_position))
4208 {
4209 start_display (&it, w, start);
4210 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4211 preserve_y = it.current_y;
4212 }
4213 else
4214 preserve_y = -1;
4215
4216 /* Move iterator it from start the specified distance forward or
4217 backward. The result is the new window start. */
4218 start_display (&it, w, start);
4219 if (whole)
4220 {
4221 int screen_full = (window_box_height (w)
4222 - next_screen_context_lines * FRAME_LINE_HEIGHT (it.f));
4223 int dy = n * screen_full;
4224
4225 /* Note that move_it_vertically always moves the iterator to the
4226 start of a line. So, if the last line doesn't have a newline,
4227 we would end up at the start of the line ending at ZV. */
4228 if (dy <= 0)
4229 move_it_vertically_backward (&it, -dy);
4230 else if (dy > 0)
4231 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4232 MOVE_TO_POS | MOVE_TO_Y);
4233 }
4234 else
4235 move_it_by_lines (&it, n, 1);
4236
4237 /* We failed if we find ZV is already on the screen (scrolling up,
4238 means there's nothing past the end), or if we can't start any
4239 earlier (scrolling down, means there's nothing past the top). */
4240 if ((n > 0 && IT_CHARPOS (it) == ZV)
4241 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4242 {
4243 if (IT_CHARPOS (it) == ZV)
4244 {
4245 if (it.current_y < it.last_visible_y
4246 && (it.current_y + it.max_ascent + it.max_descent
4247 >= it.last_visible_y))
4248 {
4249 /* The last line was only partially visible, make it fully
4250 visible. */
4251 w->vscroll = (it.last_visible_y
4252 - it.current_y + it.max_ascent + it.max_descent);
4253 adjust_glyphs (it.f);
4254 }
4255 else if (noerror)
4256 return;
4257 else
4258 Fsignal (Qend_of_buffer, Qnil);
4259 }
4260 else
4261 {
4262 if (w->vscroll != 0)
4263 /* The first line was only partially visible, make it fully
4264 visible. */
4265 w->vscroll = 0;
4266 else if (noerror)
4267 return;
4268 else
4269 Fsignal (Qbeginning_of_buffer, Qnil);
4270 }
4271
4272 /* If control gets here, then we vscrolled. */
4273
4274 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4275
4276 /* Don't try to change the window start below. */
4277 vscrolled = 1;
4278 }
4279
4280 if (! vscrolled)
4281 {
4282 int pos = IT_CHARPOS (it);
4283 int bytepos;
4284
4285 /* If in the middle of a multi-glyph character move forward to
4286 the next character. */
4287 if (in_display_vector_p (&it))
4288 {
4289 ++pos;
4290 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4291 }
4292
4293 /* Set the window start, and set up the window for redisplay. */
4294 set_marker_restricted (w->start, make_number (pos),
4295 w->buffer);
4296 bytepos = XMARKER (w->start)->bytepos;
4297 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4298 ? Qt : Qnil);
4299 w->update_mode_line = Qt;
4300 XSETFASTINT (w->last_modified, 0);
4301 XSETFASTINT (w->last_overlay_modified, 0);
4302 /* Set force_start so that redisplay_window will run the
4303 window-scroll-functions. */
4304 w->force_start = Qt;
4305 }
4306
4307 it.current_y = it.vpos = 0;
4308
4309 /* Preserve the screen position if we must. */
4310 if (preserve_y >= 0)
4311 {
4312 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4313 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4314 }
4315 else
4316 {
4317 /* Move PT out of scroll margins. */
4318 this_scroll_margin = max (0, scroll_margin);
4319 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4320 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4321
4322 if (n > 0)
4323 {
4324 /* We moved the window start towards ZV, so PT may be now
4325 in the scroll margin at the top. */
4326 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4327 while (it.current_y < this_scroll_margin)
4328 {
4329 int prev = it.current_y;
4330 move_it_by_lines (&it, 1, 1);
4331 if (prev == it.current_y)
4332 break;
4333 }
4334 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4335 }
4336 else if (n < 0)
4337 {
4338 int charpos, bytepos;
4339
4340 /* We moved the window start towards BEGV, so PT may be now
4341 in the scroll margin at the bottom. */
4342 move_it_to (&it, PT, -1,
4343 it.last_visible_y - this_scroll_margin - 1, -1,
4344 MOVE_TO_POS | MOVE_TO_Y);
4345
4346 /* Save our position, in case it's correct. */
4347 charpos = IT_CHARPOS (it);
4348 bytepos = IT_BYTEPOS (it);
4349
4350 /* See if point is on a partially visible line at the end. */
4351 move_it_by_lines (&it, 1, 1);
4352 if (it.current_y > it.last_visible_y)
4353 /* The last line was only partially visible, so back up two
4354 lines to make sure we're on a fully visible line. */
4355 {
4356 move_it_by_lines (&it, -2, 0);
4357 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4358 }
4359 else
4360 /* No, the position we saved is OK, so use it. */
4361 SET_PT_BOTH (charpos, bytepos);
4362 }
4363 }
4364 }
4365
4366
4367 /* Implementation of window_scroll that works based on screen lines.
4368 See the comment of window_scroll for parameter descriptions. */
4369
4370 static void
4371 window_scroll_line_based (window, n, whole, noerror)
4372 Lisp_Object window;
4373 int n;
4374 int whole;
4375 int noerror;
4376 {
4377 register struct window *w = XWINDOW (window);
4378 register int opoint = PT, opoint_byte = PT_BYTE;
4379 register int pos, pos_byte;
4380 register int ht = window_internal_height (w);
4381 register Lisp_Object tem;
4382 int lose;
4383 Lisp_Object bolp;
4384 int startpos;
4385 struct position posit;
4386 int original_vpos;
4387
4388 /* If scrolling screen-fulls, compute the number of lines to
4389 scroll from the window's height. */
4390 if (whole)
4391 n *= max (1, ht - next_screen_context_lines);
4392
4393 startpos = marker_position (w->start);
4394
4395 posit = *compute_motion (startpos, 0, 0, 0,
4396 PT, ht, 0,
4397 window_box_text_cols (w), XINT (w->hscroll),
4398 0, w);
4399 original_vpos = posit.vpos;
4400
4401 XSETFASTINT (tem, PT);
4402 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4403
4404 if (NILP (tem))
4405 {
4406 Fvertical_motion (make_number (- (ht / 2)), window);
4407 startpos = PT;
4408 }
4409
4410 SET_PT (startpos);
4411 lose = n < 0 && PT == BEGV;
4412 Fvertical_motion (make_number (n), window);
4413 pos = PT;
4414 pos_byte = PT_BYTE;
4415 bolp = Fbolp ();
4416 SET_PT_BOTH (opoint, opoint_byte);
4417
4418 if (lose)
4419 {
4420 if (noerror)
4421 return;
4422 else
4423 Fsignal (Qbeginning_of_buffer, Qnil);
4424 }
4425
4426 if (pos < ZV)
4427 {
4428 int this_scroll_margin = scroll_margin;
4429
4430 /* Don't use a scroll margin that is negative or too large. */
4431 if (this_scroll_margin < 0)
4432 this_scroll_margin = 0;
4433
4434 if (XINT (w->total_lines) < 4 * scroll_margin)
4435 this_scroll_margin = XINT (w->total_lines) / 4;
4436
4437 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4438 w->start_at_line_beg = bolp;
4439 w->update_mode_line = Qt;
4440 XSETFASTINT (w->last_modified, 0);
4441 XSETFASTINT (w->last_overlay_modified, 0);
4442 /* Set force_start so that redisplay_window will run
4443 the window-scroll-functions. */
4444 w->force_start = Qt;
4445
4446 if (whole && !NILP (Vscroll_preserve_screen_position))
4447 {
4448 SET_PT_BOTH (pos, pos_byte);
4449 Fvertical_motion (make_number (original_vpos), window);
4450 }
4451 /* If we scrolled forward, put point enough lines down
4452 that it is outside the scroll margin. */
4453 else if (n > 0)
4454 {
4455 int top_margin;
4456
4457 if (this_scroll_margin > 0)
4458 {
4459 SET_PT_BOTH (pos, pos_byte);
4460 Fvertical_motion (make_number (this_scroll_margin), window);
4461 top_margin = PT;
4462 }
4463 else
4464 top_margin = pos;
4465
4466 if (top_margin <= opoint)
4467 SET_PT_BOTH (opoint, opoint_byte);
4468 else if (!NILP (Vscroll_preserve_screen_position))
4469 {
4470 SET_PT_BOTH (pos, pos_byte);
4471 Fvertical_motion (make_number (original_vpos), window);
4472 }
4473 else
4474 SET_PT (top_margin);
4475 }
4476 else if (n < 0)
4477 {
4478 int bottom_margin;
4479
4480 /* If we scrolled backward, put point near the end of the window
4481 but not within the scroll margin. */
4482 SET_PT_BOTH (pos, pos_byte);
4483 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4484 if (XFASTINT (tem) == ht - this_scroll_margin)
4485 bottom_margin = PT;
4486 else
4487 bottom_margin = PT + 1;
4488
4489 if (bottom_margin > opoint)
4490 SET_PT_BOTH (opoint, opoint_byte);
4491 else
4492 {
4493 if (!NILP (Vscroll_preserve_screen_position))
4494 {
4495 SET_PT_BOTH (pos, pos_byte);
4496 Fvertical_motion (make_number (original_vpos), window);
4497 }
4498 else
4499 Fvertical_motion (make_number (-1), window);
4500 }
4501 }
4502 }
4503 else
4504 {
4505 if (noerror)
4506 return;
4507 else
4508 Fsignal (Qend_of_buffer, Qnil);
4509 }
4510 }
4511
4512
4513 /* Scroll selected_window up or down. If N is nil, scroll a
4514 screen-full which is defined as the height of the window minus
4515 next_screen_context_lines. If N is the symbol `-', scroll.
4516 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4517 up. This is the guts of Fscroll_up and Fscroll_down. */
4518
4519 static void
4520 scroll_command (n, direction)
4521 Lisp_Object n;
4522 int direction;
4523 {
4524 int count = SPECPDL_INDEX ();
4525
4526 xassert (abs (direction) == 1);
4527
4528 /* If selected window's buffer isn't current, make it current for
4529 the moment. But don't screw up if window_scroll gets an error. */
4530 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4531 {
4532 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4533 Fset_buffer (XWINDOW (selected_window)->buffer);
4534
4535 /* Make redisplay consider other windows than just selected_window. */
4536 ++windows_or_buffers_changed;
4537 }
4538
4539 if (NILP (n))
4540 window_scroll (selected_window, direction, 1, 0);
4541 else if (EQ (n, Qminus))
4542 window_scroll (selected_window, -direction, 1, 0);
4543 else
4544 {
4545 n = Fprefix_numeric_value (n);
4546 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4547 }
4548
4549 unbind_to (count, Qnil);
4550 }
4551
4552 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4553 doc: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4554 A near full screen is `next-screen-context-lines' less than a full screen.
4555 Negative ARG means scroll downward.
4556 If ARG is the atom `-', scroll downward by nearly full screen.
4557 When calling from a program, supply as argument a number, nil, or `-'. */)
4558 (arg)
4559 Lisp_Object arg;
4560 {
4561 scroll_command (arg, 1);
4562 return Qnil;
4563 }
4564
4565 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4566 doc: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4567 A near full screen is `next-screen-context-lines' less than a full screen.
4568 Negative ARG means scroll upward.
4569 If ARG is the atom `-', scroll upward by nearly full screen.
4570 When calling from a program, supply as argument a number, nil, or `-'. */)
4571 (arg)
4572 Lisp_Object arg;
4573 {
4574 scroll_command (arg, -1);
4575 return Qnil;
4576 }
4577 \f
4578 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4579 doc: /* Return the other window for \"other window scroll\" commands.
4580 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4581 specifies the window.
4582 If `other-window-scroll-buffer' is non-nil, a window
4583 showing that buffer is used. */)
4584 ()
4585 {
4586 Lisp_Object window;
4587
4588 if (MINI_WINDOW_P (XWINDOW (selected_window))
4589 && !NILP (Vminibuf_scroll_window))
4590 window = Vminibuf_scroll_window;
4591 /* If buffer is specified, scroll that buffer. */
4592 else if (!NILP (Vother_window_scroll_buffer))
4593 {
4594 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4595 if (NILP (window))
4596 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4597 }
4598 else
4599 {
4600 /* Nothing specified; look for a neighboring window on the same
4601 frame. */
4602 window = Fnext_window (selected_window, Qnil, Qnil);
4603
4604 if (EQ (window, selected_window))
4605 /* That didn't get us anywhere; look for a window on another
4606 visible frame. */
4607 do
4608 window = Fnext_window (window, Qnil, Qt);
4609 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4610 && ! EQ (window, selected_window));
4611 }
4612
4613 CHECK_LIVE_WINDOW (window);
4614
4615 if (EQ (window, selected_window))
4616 error ("There is no other window");
4617
4618 return window;
4619 }
4620
4621 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4622 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4623 A near full screen is `next-screen-context-lines' less than a full screen.
4624 The next window is the one below the current one; or the one at the top
4625 if the current one is at the bottom. Negative ARG means scroll downward.
4626 If ARG is the atom `-', scroll downward by nearly full screen.
4627 When calling from a program, supply as argument a number, nil, or `-'.
4628
4629 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4630 specifies the window to scroll.
4631 If `other-window-scroll-buffer' is non-nil, scroll the window
4632 showing that buffer, popping the buffer up if necessary. */)
4633 (arg)
4634 Lisp_Object arg;
4635 {
4636 Lisp_Object window;
4637 struct window *w;
4638 int count = SPECPDL_INDEX ();
4639
4640 window = Fother_window_for_scrolling ();
4641 w = XWINDOW (window);
4642
4643 /* Don't screw up if window_scroll gets an error. */
4644 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4645 ++windows_or_buffers_changed;
4646
4647 Fset_buffer (w->buffer);
4648 SET_PT (marker_position (w->pointm));
4649
4650 if (NILP (arg))
4651 window_scroll (window, 1, 1, 1);
4652 else if (EQ (arg, Qminus))
4653 window_scroll (window, -1, 1, 1);
4654 else
4655 {
4656 if (CONSP (arg))
4657 arg = Fcar (arg);
4658 CHECK_NUMBER (arg);
4659 window_scroll (window, XINT (arg), 0, 1);
4660 }
4661
4662 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4663 unbind_to (count, Qnil);
4664
4665 return Qnil;
4666 }
4667 \f
4668 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4669 doc: /* Scroll selected window display ARG columns left.
4670 Default for ARG is window width minus 2.
4671 Value is the total amount of leftward horizontal scrolling in
4672 effect after the change.
4673 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4674 a lower bound for automatic scrolling, i.e. automatic scrolling
4675 will not scroll a window to a column less than the value returned
4676 by this function. */)
4677 (arg)
4678 register Lisp_Object arg;
4679 {
4680 Lisp_Object result;
4681 int hscroll;
4682 struct window *w = XWINDOW (selected_window);
4683
4684 if (NILP (arg))
4685 XSETFASTINT (arg, window_box_text_cols (w) - 2);
4686 else
4687 arg = Fprefix_numeric_value (arg);
4688
4689 hscroll = XINT (w->hscroll) + XINT (arg);
4690 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4691
4692 if (interactive_p (0))
4693 w->min_hscroll = w->hscroll;
4694
4695 return result;
4696 }
4697
4698 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4699 doc: /* Scroll selected window display ARG columns right.
4700 Default for ARG is window width minus 2.
4701 Value is the total amount of leftward horizontal scrolling in
4702 effect after the change.
4703 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4704 a lower bound for automatic scrolling, i.e. automatic scrolling
4705 will not scroll a window to a column less than the value returned
4706 by this function. */)
4707 (arg)
4708 register Lisp_Object arg;
4709 {
4710 Lisp_Object result;
4711 int hscroll;
4712 struct window *w = XWINDOW (selected_window);
4713
4714 if (NILP (arg))
4715 XSETFASTINT (arg, window_box_text_cols (w) - 2);
4716 else
4717 arg = Fprefix_numeric_value (arg);
4718
4719 hscroll = XINT (w->hscroll) - XINT (arg);
4720 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4721
4722 if (interactive_p (0))
4723 w->min_hscroll = w->hscroll;
4724
4725 return result;
4726 }
4727
4728 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
4729 doc: /* Return the window which was selected when entering the minibuffer.
4730 Returns nil, if current window is not a minibuffer window. */)
4731 ()
4732 {
4733 if (minibuf_level > 0
4734 && MINI_WINDOW_P (XWINDOW (selected_window))
4735 && !NILP (minibuf_selected_window)
4736 && WINDOW_LIVE_P (minibuf_selected_window))
4737 return minibuf_selected_window;
4738
4739 return Qnil;
4740 }
4741
4742 /* Value is the number of lines actually displayed in window W,
4743 as opposed to its height. */
4744
4745 static int
4746 displayed_window_lines (w)
4747 struct window *w;
4748 {
4749 struct it it;
4750 struct text_pos start;
4751 int height = window_box_height (w);
4752 struct buffer *old_buffer;
4753 int bottom_y;
4754
4755 if (XBUFFER (w->buffer) != current_buffer)
4756 {
4757 old_buffer = current_buffer;
4758 set_buffer_internal (XBUFFER (w->buffer));
4759 }
4760 else
4761 old_buffer = NULL;
4762
4763 /* In case W->start is out of the accessible range, do something
4764 reasonable. This happens in Info mode when Info-scroll-down
4765 calls (recenter -1) while W->start is 1. */
4766 if (XMARKER (w->start)->charpos < BEGV)
4767 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4768 else if (XMARKER (w->start)->charpos > ZV)
4769 SET_TEXT_POS (start, ZV, ZV_BYTE);
4770 else
4771 SET_TEXT_POS_FROM_MARKER (start, w->start);
4772
4773 start_display (&it, w, start);
4774 move_it_vertically (&it, height);
4775 bottom_y = line_bottom_y (&it);
4776
4777 /* rms: On a non-window display,
4778 the value of it.vpos at the bottom of the screen
4779 seems to be 1 larger than window_box_height (w).
4780 This kludge fixes a bug whereby (move-to-window-line -1)
4781 when ZV is on the last screen line
4782 moves to the previous screen line instead of the last one. */
4783 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
4784 height++;
4785
4786 /* Add in empty lines at the bottom of the window. */
4787 if (bottom_y < height)
4788 {
4789 int uy = FRAME_LINE_HEIGHT (it.f);
4790 it.vpos += (height - bottom_y + uy - 1) / uy;
4791 }
4792
4793 if (old_buffer)
4794 set_buffer_internal (old_buffer);
4795
4796 return it.vpos;
4797 }
4798
4799
4800 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4801 doc: /* Center point in window and redisplay frame.
4802 With prefix argument ARG, recenter putting point on screen line ARG
4803 relative to the current window. If ARG is negative, it counts up from the
4804 bottom of the window. (ARG should be less than the height of the window.)
4805
4806 If ARG is omitted or nil, erase the entire frame and then
4807 redraw with point in the center of the current window.
4808 Just C-u as prefix means put point in the center of the window
4809 and redisplay normally--don't erase and redraw the frame. */)
4810 (arg)
4811 register Lisp_Object arg;
4812 {
4813 struct window *w = XWINDOW (selected_window);
4814 struct buffer *buf = XBUFFER (w->buffer);
4815 struct buffer *obuf = current_buffer;
4816 int center_p = 0;
4817 int charpos, bytepos;
4818
4819 /* If redisplay is suppressed due to an error, try again. */
4820 obuf->display_error_modiff = 0;
4821
4822 if (NILP (arg))
4823 {
4824 int i;
4825
4826 /* Invalidate pixel data calculated for all compositions. */
4827 for (i = 0; i < n_compositions; i++)
4828 composition_table[i]->font = NULL;
4829
4830 Fredraw_frame (w->frame);
4831 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4832 center_p = 1;
4833 }
4834 else if (CONSP (arg)) /* Just C-u. */
4835 center_p = 1;
4836 else
4837 {
4838 arg = Fprefix_numeric_value (arg);
4839 CHECK_NUMBER (arg);
4840 }
4841
4842 set_buffer_internal (buf);
4843
4844 /* Handle centering on a graphical frame specially. Such frames can
4845 have variable-height lines and centering point on the basis of
4846 line counts would lead to strange effects. */
4847 if (FRAME_WINDOW_P (XFRAME (w->frame)))
4848 {
4849 if (center_p)
4850 {
4851 struct it it;
4852 struct text_pos pt;
4853
4854 SET_TEXT_POS (pt, PT, PT_BYTE);
4855 start_display (&it, w, pt);
4856 move_it_vertically (&it, - window_box_height (w) / 2);
4857 charpos = IT_CHARPOS (it);
4858 bytepos = IT_BYTEPOS (it);
4859 }
4860 else if (XINT (arg) < 0)
4861 {
4862 struct it it;
4863 struct text_pos pt;
4864 int y0, y1, h, nlines;
4865
4866 SET_TEXT_POS (pt, PT, PT_BYTE);
4867 start_display (&it, w, pt);
4868 y0 = it.current_y;
4869
4870 /* The amount of pixels we have to move back is the window
4871 height minus what's displayed in the line containing PT,
4872 and the lines below. */
4873 nlines = - XINT (arg) - 1;
4874 move_it_by_lines (&it, nlines, 1);
4875
4876 y1 = line_bottom_y (&it);
4877
4878 /* If we can't move down NLINES lines because we hit
4879 the end of the buffer, count in some empty lines. */
4880 if (it.vpos < nlines)
4881 y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
4882
4883 h = window_box_height (w) - (y1 - y0);
4884
4885 start_display (&it, w, pt);
4886 move_it_vertically (&it, - h);
4887 charpos = IT_CHARPOS (it);
4888 bytepos = IT_BYTEPOS (it);
4889 }
4890 else
4891 {
4892 struct position pos;
4893 pos = *vmotion (PT, - XINT (arg), w);
4894 charpos = pos.bufpos;
4895 bytepos = pos.bytepos;
4896 }
4897 }
4898 else
4899 {
4900 struct position pos;
4901 int ht = window_internal_height (w);
4902
4903 if (center_p)
4904 arg = make_number (ht / 2);
4905 else if (XINT (arg) < 0)
4906 arg = make_number (XINT (arg) + ht);
4907
4908 pos = *vmotion (PT, - XINT (arg), w);
4909 charpos = pos.bufpos;
4910 bytepos = pos.bytepos;
4911 }
4912
4913 /* Set the new window start. */
4914 set_marker_both (w->start, w->buffer, charpos, bytepos);
4915 w->window_end_valid = Qnil;
4916
4917 w->optional_new_start = Qt;
4918
4919 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
4920 w->start_at_line_beg = Qt;
4921 else
4922 w->start_at_line_beg = Qnil;
4923
4924 set_buffer_internal (obuf);
4925 return Qnil;
4926 }
4927
4928
4929 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
4930 0, 1, 0,
4931 doc: /* Return the height in lines of the text display area of WINDOW.
4932 This doesn't include the mode-line (or header-line if any) or any
4933 partial-height lines in the text display area. */)
4934 (window)
4935 Lisp_Object window;
4936 {
4937 struct window *w = decode_window (window);
4938 int pixel_height = window_box_height (w);
4939 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
4940 return make_number (line_height);
4941 }
4942
4943
4944 \f
4945 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4946 1, 1, "P",
4947 doc: /* Position point relative to window.
4948 With no argument, position point at center of window.
4949 An argument specifies vertical position within the window;
4950 zero means top of window, negative means relative to bottom of window. */)
4951 (arg)
4952 Lisp_Object arg;
4953 {
4954 struct window *w = XWINDOW (selected_window);
4955 int lines, start;
4956 Lisp_Object window;
4957
4958 window = selected_window;
4959 start = marker_position (w->start);
4960 if (start < BEGV || start > ZV)
4961 {
4962 int height = window_internal_height (w);
4963 Fvertical_motion (make_number (- (height / 2)), window);
4964 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4965 w->start_at_line_beg = Fbolp ();
4966 w->force_start = Qt;
4967 }
4968 else
4969 Fgoto_char (w->start);
4970
4971 lines = displayed_window_lines (w);
4972 if (NILP (arg))
4973 XSETFASTINT (arg, lines / 2);
4974 else
4975 {
4976 arg = Fprefix_numeric_value (arg);
4977 if (XINT (arg) < 0)
4978 XSETINT (arg, XINT (arg) + lines);
4979 }
4980
4981 /* Skip past a partially visible first line. */
4982 if (w->vscroll)
4983 XSETINT (arg, XINT (arg) + 1);
4984
4985 return Fvertical_motion (arg, window);
4986 }
4987
4988
4989 \f
4990 /***********************************************************************
4991 Window Configuration
4992 ***********************************************************************/
4993
4994 struct save_window_data
4995 {
4996 EMACS_INT size_from_Lisp_Vector_struct;
4997 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4998 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
4999 Lisp_Object frame_tool_bar_lines;
5000 Lisp_Object selected_frame;
5001 Lisp_Object current_window;
5002 Lisp_Object current_buffer;
5003 Lisp_Object minibuf_scroll_window;
5004 Lisp_Object minibuf_selected_window;
5005 Lisp_Object root_window;
5006 Lisp_Object focus_frame;
5007 /* Record the values of window-min-width and window-min-height
5008 so that window sizes remain consistent with them. */
5009 Lisp_Object min_width, min_height;
5010 /* A vector, each of whose elements is a struct saved_window
5011 for one window. */
5012 Lisp_Object saved_windows;
5013 };
5014
5015 /* This is saved as a Lisp_Vector */
5016 struct saved_window
5017 {
5018 /* these first two must agree with struct Lisp_Vector in lisp.h */
5019 EMACS_INT size_from_Lisp_Vector_struct;
5020 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5021
5022 Lisp_Object window;
5023 Lisp_Object buffer, start, pointm, mark;
5024 Lisp_Object left_col, top_line, total_cols, total_lines;
5025 Lisp_Object hscroll, min_hscroll;
5026 Lisp_Object parent, prev;
5027 Lisp_Object start_at_line_beg;
5028 Lisp_Object display_table;
5029 Lisp_Object orig_top_line, orig_total_lines;
5030 Lisp_Object left_margin_cols, right_margin_cols;
5031 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5032 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5033 };
5034
5035 #define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
5036
5037 #define SAVED_WINDOW_N(swv,n) \
5038 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5039
5040 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5041 doc: /* Return t if OBJECT is a window-configuration object. */)
5042 (object)
5043 Lisp_Object object;
5044 {
5045 if (WINDOW_CONFIGURATIONP (object))
5046 return Qt;
5047 return Qnil;
5048 }
5049
5050 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5051 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5052 (config)
5053 Lisp_Object config;
5054 {
5055 register struct save_window_data *data;
5056 struct Lisp_Vector *saved_windows;
5057
5058 if (! WINDOW_CONFIGURATIONP (config))
5059 wrong_type_argument (Qwindow_configuration_p, config);
5060
5061 data = (struct save_window_data *) XVECTOR (config);
5062 saved_windows = XVECTOR (data->saved_windows);
5063 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5064 }
5065
5066 DEFUN ("set-window-configuration", Fset_window_configuration,
5067 Sset_window_configuration, 1, 1, 0,
5068 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5069 CONFIGURATION must be a value previously returned
5070 by `current-window-configuration' (which see).
5071 If CONFIGURATION was made from a frame that is now deleted,
5072 only frame-independent values can be restored. In this case,
5073 the return value is nil. Otherwise the value is t. */)
5074 (configuration)
5075 Lisp_Object configuration;
5076 {
5077 register struct save_window_data *data;
5078 struct Lisp_Vector *saved_windows;
5079 Lisp_Object new_current_buffer;
5080 Lisp_Object frame;
5081 FRAME_PTR f;
5082 int old_point = -1;
5083
5084 while (!WINDOW_CONFIGURATIONP (configuration))
5085 wrong_type_argument (Qwindow_configuration_p, configuration);
5086
5087 data = (struct save_window_data *) XVECTOR (configuration);
5088 saved_windows = XVECTOR (data->saved_windows);
5089
5090 new_current_buffer = data->current_buffer;
5091 if (NILP (XBUFFER (new_current_buffer)->name))
5092 new_current_buffer = Qnil;
5093 else
5094 {
5095 if (XBUFFER (new_current_buffer) == current_buffer)
5096 old_point = PT;
5097 else
5098 old_point = BUF_PT (XBUFFER (new_current_buffer));
5099 }
5100
5101 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5102 f = XFRAME (frame);
5103
5104 /* If f is a dead frame, don't bother rebuilding its window tree.
5105 However, there is other stuff we should still try to do below. */
5106 if (FRAME_LIVE_P (f))
5107 {
5108 register struct window *w;
5109 register struct saved_window *p;
5110 struct window *root_window;
5111 struct window **leaf_windows;
5112 int n_leaf_windows;
5113 int k, i, n;
5114
5115 /* If the frame has been resized since this window configuration was
5116 made, we change the frame to the size specified in the
5117 configuration, restore the configuration, and then resize it
5118 back. We keep track of the prevailing height in these variables. */
5119 int previous_frame_lines = FRAME_LINES (f);
5120 int previous_frame_cols = FRAME_COLS (f);
5121 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5122 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5123
5124 /* The mouse highlighting code could get screwed up
5125 if it runs during this. */
5126 BLOCK_INPUT;
5127
5128 if (XFASTINT (data->frame_lines) != previous_frame_lines
5129 || XFASTINT (data->frame_cols) != previous_frame_cols)
5130 change_frame_size (f, XFASTINT (data->frame_lines),
5131 XFASTINT (data->frame_cols), 0, 0, 0);
5132 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5133 if (XFASTINT (data->frame_menu_bar_lines)
5134 != previous_frame_menu_bar_lines)
5135 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5136 #ifdef HAVE_WINDOW_SYSTEM
5137 if (XFASTINT (data->frame_tool_bar_lines)
5138 != previous_frame_tool_bar_lines)
5139 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5140 #endif
5141 #endif
5142
5143 /* "Swap out" point from the selected window
5144 into its buffer. We do this now, before
5145 restoring the window contents, and prevent it from
5146 being done later on when we select a new window. */
5147 if (! NILP (XWINDOW (selected_window)->buffer))
5148 {
5149 w = XWINDOW (selected_window);
5150 set_marker_both (w->pointm,
5151 w->buffer,
5152 BUF_PT (XBUFFER (w->buffer)),
5153 BUF_PT_BYTE (XBUFFER (w->buffer)));
5154 }
5155
5156 windows_or_buffers_changed++;
5157 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5158
5159 /* Problem: Freeing all matrices and later allocating them again
5160 is a serious redisplay flickering problem. What we would
5161 really like to do is to free only those matrices not reused
5162 below. */
5163 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5164 leaf_windows
5165 = (struct window **) alloca (count_windows (root_window)
5166 * sizeof (struct window *));
5167 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5168
5169 /* Temporarily avoid any problems with windows that are smaller
5170 than they are supposed to be. */
5171 window_min_height = 1;
5172 window_min_width = 1;
5173
5174 /* Kludge Alert!
5175 Mark all windows now on frame as "deleted".
5176 Restoring the new configuration "undeletes" any that are in it.
5177
5178 Save their current buffers in their height fields, since we may
5179 need it later, if a buffer saved in the configuration is now
5180 dead. */
5181 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5182
5183 for (k = 0; k < saved_windows->size; k++)
5184 {
5185 p = SAVED_WINDOW_N (saved_windows, k);
5186 w = XWINDOW (p->window);
5187 w->next = Qnil;
5188
5189 if (!NILP (p->parent))
5190 w->parent = SAVED_WINDOW_N (saved_windows,
5191 XFASTINT (p->parent))->window;
5192 else
5193 w->parent = Qnil;
5194
5195 if (!NILP (p->prev))
5196 {
5197 w->prev = SAVED_WINDOW_N (saved_windows,
5198 XFASTINT (p->prev))->window;
5199 XWINDOW (w->prev)->next = p->window;
5200 }
5201 else
5202 {
5203 w->prev = Qnil;
5204 if (!NILP (w->parent))
5205 {
5206 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5207 {
5208 XWINDOW (w->parent)->vchild = p->window;
5209 XWINDOW (w->parent)->hchild = Qnil;
5210 }
5211 else
5212 {
5213 XWINDOW (w->parent)->hchild = p->window;
5214 XWINDOW (w->parent)->vchild = Qnil;
5215 }
5216 }
5217 }
5218
5219 /* If we squirreled away the buffer in the window's height,
5220 restore it now. */
5221 if (BUFFERP (w->total_lines))
5222 w->buffer = w->total_lines;
5223 w->left_col = p->left_col;
5224 w->top_line = p->top_line;
5225 w->total_cols = p->total_cols;
5226 w->total_lines = p->total_lines;
5227 w->hscroll = p->hscroll;
5228 w->min_hscroll = p->min_hscroll;
5229 w->display_table = p->display_table;
5230 w->orig_top_line = p->orig_top_line;
5231 w->orig_total_lines = p->orig_total_lines;
5232 w->left_margin_cols = p->left_margin_cols;
5233 w->right_margin_cols = p->right_margin_cols;
5234 w->left_fringe_width = p->left_fringe_width;
5235 w->right_fringe_width = p->right_fringe_width;
5236 w->fringes_outside_margins = p->fringes_outside_margins;
5237 w->scroll_bar_width = p->scroll_bar_width;
5238 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5239 XSETFASTINT (w->last_modified, 0);
5240 XSETFASTINT (w->last_overlay_modified, 0);
5241
5242 /* Reinstall the saved buffer and pointers into it. */
5243 if (NILP (p->buffer))
5244 w->buffer = p->buffer;
5245 else
5246 {
5247 if (!NILP (XBUFFER (p->buffer)->name))
5248 /* If saved buffer is alive, install it. */
5249 {
5250 w->buffer = p->buffer;
5251 w->start_at_line_beg = p->start_at_line_beg;
5252 set_marker_restricted (w->start, p->start, w->buffer);
5253 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5254 Fset_marker (XBUFFER (w->buffer)->mark,
5255 p->mark, w->buffer);
5256
5257 /* As documented in Fcurrent_window_configuration, don't
5258 restore the location of point in the buffer which was
5259 current when the window configuration was recorded. */
5260 if (!EQ (p->buffer, new_current_buffer)
5261 && XBUFFER (p->buffer) == current_buffer)
5262 Fgoto_char (w->pointm);
5263 }
5264 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5265 /* Else unless window has a live buffer, get one. */
5266 {
5267 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5268 /* This will set the markers to beginning of visible
5269 range. */
5270 set_marker_restricted (w->start, make_number (0), w->buffer);
5271 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5272 w->start_at_line_beg = Qt;
5273 }
5274 else
5275 /* Keeping window's old buffer; make sure the markers
5276 are real. */
5277 {
5278 /* Set window markers at start of visible range. */
5279 if (XMARKER (w->start)->buffer == 0)
5280 set_marker_restricted (w->start, make_number (0),
5281 w->buffer);
5282 if (XMARKER (w->pointm)->buffer == 0)
5283 set_marker_restricted_both (w->pointm, w->buffer,
5284 BUF_PT (XBUFFER (w->buffer)),
5285 BUF_PT_BYTE (XBUFFER (w->buffer)));
5286 w->start_at_line_beg = Qt;
5287 }
5288 }
5289 }
5290
5291 FRAME_ROOT_WINDOW (f) = data->root_window;
5292 /* Prevent "swapping out point" in the old selected window
5293 using the buffer that has been restored into it.
5294 Use the point value from the beginning of this function
5295 since unshow_buffer (called from delete_all_subwindows)
5296 could have altered it. */
5297 selected_window = Qnil;
5298 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5299 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5300 make_number (old_point),
5301 XWINDOW (data->current_window)->buffer);
5302
5303 Fselect_window (data->current_window, Qnil);
5304 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5305 = selected_window;
5306
5307 if (NILP (data->focus_frame)
5308 || (FRAMEP (data->focus_frame)
5309 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5310 Fredirect_frame_focus (frame, data->focus_frame);
5311
5312 #if 0 /* I don't understand why this is needed, and it causes problems
5313 when the frame's old selected window has been deleted. */
5314 if (f != selected_frame && FRAME_WINDOW_P (f))
5315 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5316 0, 0);
5317 #endif
5318
5319 /* Set the screen height to the value it had before this function. */
5320 if (previous_frame_lines != FRAME_LINES (f)
5321 || previous_frame_cols != FRAME_COLS (f))
5322 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5323 0, 0, 0);
5324 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5325 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5326 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5327 make_number (0));
5328 #ifdef HAVE_WINDOW_SYSTEM
5329 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5330 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5331 make_number (0));
5332 #endif
5333 #endif
5334
5335 /* Now, free glyph matrices in windows that were not reused. */
5336 for (i = n = 0; i < n_leaf_windows; ++i)
5337 {
5338 if (NILP (leaf_windows[i]->buffer))
5339 {
5340 /* Assert it's not reused as a combination. */
5341 xassert (NILP (leaf_windows[i]->hchild)
5342 && NILP (leaf_windows[i]->vchild));
5343 free_window_matrices (leaf_windows[i]);
5344 }
5345 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5346 ++n;
5347 }
5348
5349 adjust_glyphs (f);
5350
5351 UNBLOCK_INPUT;
5352
5353 /* Fselect_window will have made f the selected frame, so we
5354 reselect the proper frame here. Fhandle_switch_frame will change the
5355 selected window too, but that doesn't make the call to
5356 Fselect_window above totally superfluous; it still sets f's
5357 selected window. */
5358 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5359 do_switch_frame (data->selected_frame, 0, 0);
5360
5361 if (! NILP (Vwindow_configuration_change_hook)
5362 && ! NILP (Vrun_hooks))
5363 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5364 }
5365
5366 if (!NILP (new_current_buffer))
5367 Fset_buffer (new_current_buffer);
5368
5369 /* Restore the minimum heights recorded in the configuration. */
5370 window_min_height = XINT (data->min_height);
5371 window_min_width = XINT (data->min_width);
5372
5373 Vminibuf_scroll_window = data->minibuf_scroll_window;
5374 minibuf_selected_window = data->minibuf_selected_window;
5375
5376 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5377 }
5378
5379 /* Mark all windows now on frame as deleted
5380 by setting their buffers to nil. */
5381
5382 void
5383 delete_all_subwindows (w)
5384 register struct window *w;
5385 {
5386 if (!NILP (w->next))
5387 delete_all_subwindows (XWINDOW (w->next));
5388 if (!NILP (w->vchild))
5389 delete_all_subwindows (XWINDOW (w->vchild));
5390 if (!NILP (w->hchild))
5391 delete_all_subwindows (XWINDOW (w->hchild));
5392
5393 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
5394
5395 if (!NILP (w->buffer))
5396 unshow_buffer (w);
5397
5398 /* We set all three of these fields to nil, to make sure that we can
5399 distinguish this dead window from any live window. Live leaf
5400 windows will have buffer set, and combination windows will have
5401 vchild or hchild set. */
5402 w->buffer = Qnil;
5403 w->vchild = Qnil;
5404 w->hchild = Qnil;
5405
5406 Vwindow_list = Qnil;
5407 }
5408 \f
5409 static int
5410 count_windows (window)
5411 register struct window *window;
5412 {
5413 register int count = 1;
5414 if (!NILP (window->next))
5415 count += count_windows (XWINDOW (window->next));
5416 if (!NILP (window->vchild))
5417 count += count_windows (XWINDOW (window->vchild));
5418 if (!NILP (window->hchild))
5419 count += count_windows (XWINDOW (window->hchild));
5420 return count;
5421 }
5422
5423
5424 /* Fill vector FLAT with leaf windows under W, starting at index I.
5425 Value is last index + 1. */
5426
5427 static int
5428 get_leaf_windows (w, flat, i)
5429 struct window *w;
5430 struct window **flat;
5431 int i;
5432 {
5433 while (w)
5434 {
5435 if (!NILP (w->hchild))
5436 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5437 else if (!NILP (w->vchild))
5438 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5439 else
5440 flat[i++] = w;
5441
5442 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5443 }
5444
5445 return i;
5446 }
5447
5448
5449 /* Return a pointer to the glyph W's physical cursor is on. Value is
5450 null if W's current matrix is invalid, so that no meaningfull glyph
5451 can be returned. */
5452
5453 struct glyph *
5454 get_phys_cursor_glyph (w)
5455 struct window *w;
5456 {
5457 struct glyph_row *row;
5458 struct glyph *glyph;
5459
5460 if (w->phys_cursor.vpos >= 0
5461 && w->phys_cursor.vpos < w->current_matrix->nrows
5462 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5463 row->enabled_p)
5464 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5465 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5466 else
5467 glyph = NULL;
5468
5469 return glyph;
5470 }
5471
5472
5473 static int
5474 save_window_save (window, vector, i)
5475 Lisp_Object window;
5476 struct Lisp_Vector *vector;
5477 int i;
5478 {
5479 register struct saved_window *p;
5480 register struct window *w;
5481 register Lisp_Object tem;
5482
5483 for (;!NILP (window); window = w->next)
5484 {
5485 p = SAVED_WINDOW_N (vector, i);
5486 w = XWINDOW (window);
5487
5488 XSETFASTINT (w->temslot, i++);
5489 p->window = window;
5490 p->buffer = w->buffer;
5491 p->left_col = w->left_col;
5492 p->top_line = w->top_line;
5493 p->total_cols = w->total_cols;
5494 p->total_lines = w->total_lines;
5495 p->hscroll = w->hscroll;
5496 p->min_hscroll = w->min_hscroll;
5497 p->display_table = w->display_table;
5498 p->orig_top_line = w->orig_top_line;
5499 p->orig_total_lines = w->orig_total_lines;
5500 p->left_margin_cols = w->left_margin_cols;
5501 p->right_margin_cols = w->right_margin_cols;
5502 p->left_fringe_width = w->left_fringe_width;
5503 p->right_fringe_width = w->right_fringe_width;
5504 p->fringes_outside_margins = w->fringes_outside_margins;
5505 p->scroll_bar_width = w->scroll_bar_width;
5506 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
5507 if (!NILP (w->buffer))
5508 {
5509 /* Save w's value of point in the window configuration.
5510 If w is the selected window, then get the value of point
5511 from the buffer; pointm is garbage in the selected window. */
5512 if (EQ (window, selected_window))
5513 {
5514 p->pointm = Fmake_marker ();
5515 set_marker_both (p->pointm, w->buffer,
5516 BUF_PT (XBUFFER (w->buffer)),
5517 BUF_PT_BYTE (XBUFFER (w->buffer)));
5518 }
5519 else
5520 p->pointm = Fcopy_marker (w->pointm, Qnil);
5521
5522 p->start = Fcopy_marker (w->start, Qnil);
5523 p->start_at_line_beg = w->start_at_line_beg;
5524
5525 tem = XBUFFER (w->buffer)->mark;
5526 p->mark = Fcopy_marker (tem, Qnil);
5527 }
5528 else
5529 {
5530 p->pointm = Qnil;
5531 p->start = Qnil;
5532 p->mark = Qnil;
5533 p->start_at_line_beg = Qnil;
5534 }
5535
5536 if (NILP (w->parent))
5537 p->parent = Qnil;
5538 else
5539 p->parent = XWINDOW (w->parent)->temslot;
5540
5541 if (NILP (w->prev))
5542 p->prev = Qnil;
5543 else
5544 p->prev = XWINDOW (w->prev)->temslot;
5545
5546 if (!NILP (w->vchild))
5547 i = save_window_save (w->vchild, vector, i);
5548 if (!NILP (w->hchild))
5549 i = save_window_save (w->hchild, vector, i);
5550 }
5551
5552 return i;
5553 }
5554
5555 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5556 Scurrent_window_configuration, 0, 1, 0,
5557 doc: /* Return an object representing the current window configuration of FRAME.
5558 If FRAME is nil or omitted, use the selected frame.
5559 This describes the number of windows, their sizes and current buffers,
5560 and for each displayed buffer, where display starts, and the positions of
5561 point and mark. An exception is made for point in the current buffer:
5562 its value is -not- saved.
5563 This also records the currently selected frame, and FRAME's focus
5564 redirection (see `redirect-frame-focus'). */)
5565 (frame)
5566 Lisp_Object frame;
5567 {
5568 register Lisp_Object tem;
5569 register int n_windows;
5570 register struct save_window_data *data;
5571 register struct Lisp_Vector *vec;
5572 register int i;
5573 FRAME_PTR f;
5574
5575 if (NILP (frame))
5576 frame = selected_frame;
5577 CHECK_LIVE_FRAME (frame);
5578 f = XFRAME (frame);
5579
5580 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5581 vec = allocate_other_vector (VECSIZE (struct save_window_data));
5582 data = (struct save_window_data *)vec;
5583
5584 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
5585 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
5586 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5587 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5588 data->selected_frame = selected_frame;
5589 data->current_window = FRAME_SELECTED_WINDOW (f);
5590 XSETBUFFER (data->current_buffer, current_buffer);
5591 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5592 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5593 data->root_window = FRAME_ROOT_WINDOW (f);
5594 data->focus_frame = FRAME_FOCUS_FRAME (f);
5595 XSETINT (data->min_height, window_min_height);
5596 XSETINT (data->min_width, window_min_width);
5597 tem = Fmake_vector (make_number (n_windows), Qnil);
5598 data->saved_windows = tem;
5599 for (i = 0; i < n_windows; i++)
5600 XVECTOR (tem)->contents[i]
5601 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5602 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5603 XSETWINDOW_CONFIGURATION (tem, data);
5604 return (tem);
5605 }
5606
5607 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5608 0, UNEVALLED, 0,
5609 doc: /* Execute body, preserving window sizes and contents.
5610 Restore which buffer appears in which window, where display starts,
5611 and the value of point and mark for each window.
5612 Also restore the choice of selected window.
5613 Also restore which buffer is current.
5614 Does not restore the value of point in current buffer.
5615 usage: (save-window-excursion BODY ...) */)
5616 (args)
5617 Lisp_Object args;
5618 {
5619 register Lisp_Object val;
5620 register int count = SPECPDL_INDEX ();
5621
5622 record_unwind_protect (Fset_window_configuration,
5623 Fcurrent_window_configuration (Qnil));
5624 val = Fprogn (args);
5625 return unbind_to (count, val);
5626 }
5627
5628 \f
5629 /***********************************************************************
5630 Marginal Areas
5631 ***********************************************************************/
5632
5633 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5634 2, 3, 0,
5635 doc: /* Set width of marginal areas of window WINDOW.
5636 If window is nil, set margins of the currently selected window.
5637 First parameter LEFT-WIDTH specifies the number of character
5638 cells to reserve for the left marginal area. Second parameter
5639 RIGHT-WIDTH does the same for the right marginal area.
5640 A nil width parameter means no margin. */)
5641 (window, left, right)
5642 Lisp_Object window, left, right;
5643 {
5644 struct window *w = decode_window (window);
5645
5646 /* TODO: It doesn't make sense to use FLOATs here, since
5647 the rest of the code assumes they are integers.
5648 So don't allow floats! ++KFS */
5649
5650 if (!NILP (left))
5651 CHECK_NUMBER_OR_FLOAT (left);
5652 if (!NILP (right))
5653 CHECK_NUMBER_OR_FLOAT (right);
5654
5655 /* Check widths < 0 and translate a zero width to nil.
5656 Margins that are too wide have to be checked elsewhere. */
5657 if ((INTEGERP (left) && XINT (left) < 0)
5658 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
5659 XSETFASTINT (left, 0);
5660 if (INTEGERP (left) && XFASTINT (left) == 0)
5661 left = Qnil;
5662
5663 if ((INTEGERP (right) && XINT (right) < 0)
5664 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5665 XSETFASTINT (right, 0);
5666 if (INTEGERP (right) && XFASTINT (right) == 0)
5667 right = Qnil;
5668
5669 if (!EQ (w->left_margin_cols, left)
5670 || !EQ (w->right_margin_cols, right))
5671 {
5672 w->left_margin_cols = left;
5673 w->right_margin_cols = right;
5674
5675 adjust_window_margins (w);
5676
5677 ++windows_or_buffers_changed;
5678 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5679 }
5680
5681 return Qnil;
5682 }
5683
5684
5685 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5686 0, 1, 0,
5687 doc: /* Get width of marginal areas of window WINDOW.
5688 If WINDOW is omitted or nil, use the currently selected window.
5689 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5690 If a marginal area does not exist, its width will be returned
5691 as nil. */)
5692 (window)
5693 Lisp_Object window;
5694 {
5695 struct window *w = decode_window (window);
5696 return Fcons (w->left_margin_cols, w->right_margin_cols);
5697 }
5698
5699
5700 \f
5701 /***********************************************************************
5702 Fringes
5703 ***********************************************************************/
5704
5705 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
5706 2, 4, 0,
5707 doc: /* Set width of fringes of window WINDOW.
5708
5709 If window is nil, set fringes of the currently selected window.
5710 Second parameter LEFT-WIDTH specifies the number of pixels to reserve
5711 for the left fringe. Third parameter RIGHT-WIDTH does the same for
5712 the right fringe. Fourth parameter OUTSIDE-MARGINS non-nil specifies
5713 that fringes are drawn outside of the display margins; by default, fringes
5714 are drawn between display marginal areas and the text area.
5715 A nil width parameter means to use the frame's corresponding fringe width. */)
5716 (window, left, right, outside_margins)
5717 Lisp_Object window, left, right, outside_margins;
5718 {
5719 struct window *w = decode_window (window);
5720
5721 if (!NILP (left))
5722 CHECK_NUMBER (left);
5723 if (!NILP (right))
5724 CHECK_NUMBER (right);
5725
5726 if (!EQ (w->left_fringe_width, left)
5727 || !EQ (w->right_fringe_width, right)
5728 || !EQ (w->fringes_outside_margins, outside_margins))
5729 {
5730 w->left_fringe_width = left;
5731 w->right_fringe_width = right;
5732 w->fringes_outside_margins = outside_margins;
5733
5734 adjust_window_margins (w);
5735
5736 clear_glyph_matrix (w->current_matrix);
5737 w->window_end_valid = Qnil;
5738
5739 ++windows_or_buffers_changed;
5740 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5741 }
5742
5743 return Qnil;
5744 }
5745
5746
5747 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
5748 0, 1, 0,
5749 doc: /* Get width of fringes of window WINDOW.
5750 If WINDOW is omitted or nil, use the currently selected window.
5751 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).
5752 If a window specific fringe width is not set, its width will be returned
5753 as nil. */)
5754 (window)
5755 Lisp_Object window;
5756 {
5757 struct window *w = decode_window (window);
5758 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
5759 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
5760 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
5761 Qt : Qnil), Qnil)));
5762 }
5763
5764
5765 \f
5766 /***********************************************************************
5767 Scroll bars
5768 ***********************************************************************/
5769
5770 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
5771 2, 4, 0,
5772 doc: /* Set width and type of scroll bars of window WINDOW.
5773 If window is nil, set scroll bars of the currently selected window.
5774 Second parameter WIDTH specifies the pixel width for the scroll bar;
5775 this is automatically adjusted to a multiple of the frame column width.
5776 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
5777 bar: left, right, or nil.
5778 A width of nil and type of t means to use the frame's corresponding value. */)
5779 (window, width, vertical_type, horizontal_type)
5780 Lisp_Object window, width, vertical_type, horizontal_type;
5781 {
5782 struct window *w = decode_window (window);
5783
5784 if (!NILP (width))
5785 CHECK_NUMBER (width);
5786
5787 if (XINT (width) == 0)
5788 vertical_type = Qnil;
5789
5790 if (!EQ (w->scroll_bar_width, width)
5791 || !EQ (w->vertical_scroll_bar_type, vertical_type))
5792 {
5793 w->scroll_bar_width = width;
5794 w->vertical_scroll_bar_type = vertical_type;
5795
5796 adjust_window_margins (w);
5797
5798 clear_glyph_matrix (w->current_matrix);
5799 w->window_end_valid = Qnil;
5800
5801 ++windows_or_buffers_changed;
5802 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5803 }
5804
5805 return Qnil;
5806 }
5807
5808
5809 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
5810 0, 1, 0,
5811 doc: /* Get width and type of scroll bars of window WINDOW.
5812 If WINDOW is omitted or nil, use the currently selected window.
5813 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE). */)
5814 (window)
5815 Lisp_Object window;
5816 {
5817 struct window *w = decode_window (window);
5818 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
5819 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
5820 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
5821 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
5822 Fcons (w->vertical_scroll_bar_type,
5823 Fcons (Qnil, Qnil))));
5824 }
5825
5826
5827 \f
5828 /***********************************************************************
5829 Smooth scrolling
5830 ***********************************************************************/
5831
5832 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
5833 doc: /* Return the amount by which WINDOW is scrolled vertically.
5834 Use the selected window if WINDOW is nil or omitted.
5835 Value is a multiple of the canonical character height of WINDOW. */)
5836 (window)
5837 Lisp_Object window;
5838 {
5839 Lisp_Object result;
5840 struct frame *f;
5841 struct window *w;
5842
5843 if (NILP (window))
5844 window = selected_window;
5845 else
5846 CHECK_WINDOW (window);
5847 w = XWINDOW (window);
5848 f = XFRAME (w->frame);
5849
5850 if (FRAME_WINDOW_P (f))
5851 result = FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5852 else
5853 result = make_number (0);
5854 return result;
5855 }
5856
5857
5858 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
5859 2, 2, 0,
5860 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
5861 WINDOW nil means use the selected window. VSCROLL is a non-negative
5862 multiple of the canonical character height of WINDOW. */)
5863 (window, vscroll)
5864 Lisp_Object window, vscroll;
5865 {
5866 struct window *w;
5867 struct frame *f;
5868
5869 if (NILP (window))
5870 window = selected_window;
5871 else
5872 CHECK_WINDOW (window);
5873 CHECK_NUMBER_OR_FLOAT (vscroll);
5874
5875 w = XWINDOW (window);
5876 f = XFRAME (w->frame);
5877
5878 if (FRAME_WINDOW_P (f))
5879 {
5880 int old_dy = w->vscroll;
5881
5882 w->vscroll = - FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll);
5883 w->vscroll = min (w->vscroll, 0);
5884
5885 /* Adjust glyph matrix of the frame if the virtual display
5886 area becomes larger than before. */
5887 if (w->vscroll < 0 && w->vscroll < old_dy)
5888 adjust_glyphs (f);
5889
5890 /* Prevent redisplay shortcuts. */
5891 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5892 }
5893
5894 return Fwindow_vscroll (window);
5895 }
5896
5897 \f
5898 /* Call FN for all leaf windows on frame F. FN is called with the
5899 first argument being a pointer to the leaf window, and with
5900 additional argument USER_DATA. Stops when FN returns 0. */
5901
5902 void
5903 foreach_window (f, fn, user_data)
5904 struct frame *f;
5905 int (* fn) P_ ((struct window *, void *));
5906 void *user_data;
5907 {
5908 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
5909 }
5910
5911
5912 /* Helper function for foreach_window. Call FN for all leaf windows
5913 reachable from W. FN is called with the first argument being a
5914 pointer to the leaf window, and with additional argument USER_DATA.
5915 Stop when FN returns 0. Value is 0 if stopped by FN. */
5916
5917 static int
5918 foreach_window_1 (w, fn, user_data)
5919 struct window *w;
5920 int (* fn) P_ ((struct window *, void *));
5921 void *user_data;
5922 {
5923 int cont;
5924
5925 for (cont = 1; w && cont;)
5926 {
5927 if (!NILP (w->hchild))
5928 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
5929 else if (!NILP (w->vchild))
5930 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
5931 else
5932 cont = fn (w, user_data);
5933
5934 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5935 }
5936
5937 return cont;
5938 }
5939
5940
5941 /* Freeze or unfreeze the window start of W unless it is a
5942 mini-window or the selected window. FREEZE_P non-null means freeze
5943 the window start. */
5944
5945 static int
5946 freeze_window_start (w, freeze_p)
5947 struct window *w;
5948 void *freeze_p;
5949 {
5950 if (w == XWINDOW (selected_window)
5951 || MINI_WINDOW_P (w)
5952 || (MINI_WINDOW_P (XWINDOW (selected_window))
5953 && ! NILP (Vminibuf_scroll_window)
5954 && w == XWINDOW (Vminibuf_scroll_window)))
5955 freeze_p = NULL;
5956
5957 w->frozen_window_start_p = freeze_p != NULL;
5958 return 1;
5959 }
5960
5961
5962 /* Freeze or unfreeze the window starts of all leaf windows on frame
5963 F, except the selected window and a mini-window. FREEZE_P non-zero
5964 means freeze the window start. */
5965
5966 void
5967 freeze_window_starts (f, freeze_p)
5968 struct frame *f;
5969 int freeze_p;
5970 {
5971 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
5972 }
5973
5974 \f
5975 /***********************************************************************
5976 Initialization
5977 ***********************************************************************/
5978
5979 /* Return 1 if window configurations C1 and C2
5980 describe the same state of affairs. This is used by Fequal. */
5981
5982 int
5983 compare_window_configurations (c1, c2, ignore_positions)
5984 Lisp_Object c1, c2;
5985 int ignore_positions;
5986 {
5987 register struct save_window_data *d1, *d2;
5988 struct Lisp_Vector *sw1, *sw2;
5989 int i;
5990
5991 if (!WINDOW_CONFIGURATIONP (c1))
5992 wrong_type_argument (Qwindow_configuration_p, c1);
5993 if (!WINDOW_CONFIGURATIONP (c2))
5994 wrong_type_argument (Qwindow_configuration_p, c2);
5995
5996 d1 = (struct save_window_data *) XVECTOR (c1);
5997 d2 = (struct save_window_data *) XVECTOR (c2);
5998 sw1 = XVECTOR (d1->saved_windows);
5999 sw2 = XVECTOR (d2->saved_windows);
6000
6001 if (! EQ (d1->frame_cols, d2->frame_cols))
6002 return 0;
6003 if (! EQ (d1->frame_lines, d2->frame_lines))
6004 return 0;
6005 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6006 return 0;
6007 if (! EQ (d1->selected_frame, d2->selected_frame))
6008 return 0;
6009 /* Don't compare the current_window field directly.
6010 Instead see w1_is_current and w2_is_current, below. */
6011 if (! EQ (d1->current_buffer, d2->current_buffer))
6012 return 0;
6013 if (! ignore_positions)
6014 {
6015 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6016 return 0;
6017 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6018 return 0;
6019 }
6020 /* Don't compare the root_window field.
6021 We don't require the two configurations
6022 to use the same window object,
6023 and the two root windows must be equivalent
6024 if everything else compares equal. */
6025 if (! EQ (d1->focus_frame, d2->focus_frame))
6026 return 0;
6027 if (! EQ (d1->min_width, d2->min_width))
6028 return 0;
6029 if (! EQ (d1->min_height, d2->min_height))
6030 return 0;
6031
6032 /* Verify that the two confis have the same number of windows. */
6033 if (sw1->size != sw2->size)
6034 return 0;
6035
6036 for (i = 0; i < sw1->size; i++)
6037 {
6038 struct saved_window *p1, *p2;
6039 int w1_is_current, w2_is_current;
6040
6041 p1 = SAVED_WINDOW_N (sw1, i);
6042 p2 = SAVED_WINDOW_N (sw2, i);
6043
6044 /* Verify that the current windows in the two
6045 configurations correspond to each other. */
6046 w1_is_current = EQ (d1->current_window, p1->window);
6047 w2_is_current = EQ (d2->current_window, p2->window);
6048
6049 if (w1_is_current != w2_is_current)
6050 return 0;
6051
6052 /* Verify that the corresponding windows do match. */
6053 if (! EQ (p1->buffer, p2->buffer))
6054 return 0;
6055 if (! EQ (p1->left_col, p2->left_col))
6056 return 0;
6057 if (! EQ (p1->top_line, p2->top_line))
6058 return 0;
6059 if (! EQ (p1->total_cols, p2->total_cols))
6060 return 0;
6061 if (! EQ (p1->total_lines, p2->total_lines))
6062 return 0;
6063 if (! EQ (p1->display_table, p2->display_table))
6064 return 0;
6065 if (! EQ (p1->parent, p2->parent))
6066 return 0;
6067 if (! EQ (p1->prev, p2->prev))
6068 return 0;
6069 if (! ignore_positions)
6070 {
6071 if (! EQ (p1->hscroll, p2->hscroll))
6072 return 0;
6073 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6074 return 0;
6075 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6076 return 0;
6077 if (NILP (Fequal (p1->start, p2->start)))
6078 return 0;
6079 if (NILP (Fequal (p1->pointm, p2->pointm)))
6080 return 0;
6081 if (NILP (Fequal (p1->mark, p2->mark)))
6082 return 0;
6083 }
6084 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6085 return 0;
6086 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6087 return 0;
6088 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6089 return 0;
6090 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6091 return 0;
6092 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6093 return 0;
6094 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6095 return 0;
6096 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6097 return 0;
6098 }
6099
6100 return 1;
6101 }
6102
6103 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6104 Scompare_window_configurations, 2, 2, 0,
6105 doc: /* Compare two window configurations as regards the structure of windows.
6106 This function ignores details such as the values of point and mark
6107 and scrolling positions. */)
6108 (x, y)
6109 Lisp_Object x, y;
6110 {
6111 if (compare_window_configurations (x, y, 1))
6112 return Qt;
6113 return Qnil;
6114 }
6115 \f
6116 void
6117 init_window_once ()
6118 {
6119 struct frame *f = make_terminal_frame ();
6120 XSETFRAME (selected_frame, f);
6121 Vterminal_frame = selected_frame;
6122 minibuf_window = f->minibuffer_window;
6123 selected_window = f->selected_window;
6124 last_nonminibuf_frame = f;
6125
6126 window_initialized = 1;
6127 }
6128
6129 void
6130 init_window ()
6131 {
6132 Vwindow_list = Qnil;
6133 }
6134
6135 void
6136 syms_of_window ()
6137 {
6138 Qwindow_size_fixed = intern ("window-size-fixed");
6139 staticpro (&Qwindow_size_fixed);
6140
6141 staticpro (&Qwindow_configuration_change_hook);
6142 Qwindow_configuration_change_hook
6143 = intern ("window-configuration-change-hook");
6144
6145 Qwindowp = intern ("windowp");
6146 staticpro (&Qwindowp);
6147
6148 Qwindow_configuration_p = intern ("window-configuration-p");
6149 staticpro (&Qwindow_configuration_p);
6150
6151 Qwindow_live_p = intern ("window-live-p");
6152 staticpro (&Qwindow_live_p);
6153
6154 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
6155 staticpro (&Qtemp_buffer_show_hook);
6156
6157 staticpro (&Vwindow_list);
6158
6159 minibuf_selected_window = Qnil;
6160 staticpro (&minibuf_selected_window);
6161
6162 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
6163 doc: /* Non-nil means call as function to display a help buffer.
6164 The function is called with one argument, the buffer to be displayed.
6165 Used by `with-output-to-temp-buffer'.
6166 If this function is used, then it must do the entire job of showing
6167 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6168 Vtemp_buffer_show_function = Qnil;
6169
6170 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
6171 doc: /* If non-nil, function to call to handle `display-buffer'.
6172 It will receive two args, the buffer and a flag which if non-nil means
6173 that the currently selected window is not acceptable.
6174 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
6175 work using this function. */);
6176 Vdisplay_buffer_function = Qnil;
6177
6178 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
6179 doc: /* *If non-nil, `display-buffer' should even the window heights.
6180 If nil, `display-buffer' will leave the window configuration alone. */);
6181 Veven_window_heights = Qt;
6182
6183 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
6184 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6185 Vminibuf_scroll_window = Qnil;
6186
6187 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
6188 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6189 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6190 is displayed in the `mode-line' face. */);
6191 mode_line_in_non_selected_windows = 1;
6192
6193 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
6194 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6195 Vother_window_scroll_buffer = Qnil;
6196
6197 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
6198 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
6199 pop_up_frames = 0;
6200
6201 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
6202 doc: /* *Non-nil means `display-buffer' should reuse frames.
6203 If the buffer in question is already displayed in a frame, raise that frame. */);
6204 display_buffer_reuse_frames = 0;
6205
6206 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
6207 doc: /* Function to call to handle automatic new frame creation.
6208 It is called with no arguments and should return a newly created frame.
6209
6210 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
6211 where `pop-up-frame-alist' would hold the default frame parameters. */);
6212 Vpop_up_frame_function = Qnil;
6213
6214 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
6215 doc: /* *List of buffer names that should have their own special frames.
6216 Displaying a buffer whose name is in this list makes a special frame for it
6217 using `special-display-function'. See also `special-display-regexps'.
6218
6219 An element of the list can be a list instead of just a string.
6220 There are two ways to use a list as an element:
6221 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
6222 In the first case, FRAME-PARAMETERS are used to create the frame.
6223 In the latter case, FUNCTION is called with BUFFER as the first argument,
6224 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
6225 All this is done by the function found in `special-display-function'.
6226
6227 If this variable appears \"not to work\", because you add a name to it
6228 but that buffer still appears in the selected window, look at the
6229 values of `same-window-buffer-names' and `same-window-regexps'.
6230 Those variables take precedence over this one. */);
6231 Vspecial_display_buffer_names = Qnil;
6232
6233 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
6234 doc: /* *List of regexps saying which buffers should have their own special frames.
6235 If a buffer name matches one of these regexps, it gets its own frame.
6236 Displaying a buffer whose name is in this list makes a special frame for it
6237 using `special-display-function'.
6238
6239 An element of the list can be a list instead of just a string.
6240 There are two ways to use a list as an element:
6241 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6242 In the first case, FRAME-PARAMETERS are used to create the frame.
6243 In the latter case, FUNCTION is called with the buffer as first argument,
6244 followed by OTHER-ARGS--it can display the buffer in any way it likes.
6245 All this is done by the function found in `special-display-function'.
6246
6247 If this variable appears \"not to work\", because you add a regexp to it
6248 but the matching buffers still appear in the selected window, look at the
6249 values of `same-window-buffer-names' and `same-window-regexps'.
6250 Those variables take precedence over this one. */);
6251 Vspecial_display_regexps = Qnil;
6252
6253 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
6254 doc: /* Function to call to make a new frame for a special buffer.
6255 It is called with two arguments, the buffer and optional buffer specific
6256 data, and should return a window displaying that buffer.
6257 The default value normally makes a separate frame for the buffer,
6258 using `special-display-frame-alist' to specify the frame parameters.
6259 But if the buffer specific data includes (same-buffer . t) then the
6260 buffer is displayed in the current selected window.
6261 Otherwise if it includes (same-frame . t) then the buffer is displayed in
6262 a new window in the currently selected frame.
6263
6264 A buffer is special if it is listed in `special-display-buffer-names'
6265 or matches a regexp in `special-display-regexps'. */);
6266 Vspecial_display_function = Qnil;
6267
6268 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
6269 doc: /* *List of buffer names that should appear in the selected window.
6270 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6271 switches to it in the selected window, rather than making it appear
6272 in some other window.
6273
6274 An element of the list can be a cons cell instead of just a string.
6275 Then the car must be a string, which specifies the buffer name.
6276 This is for compatibility with `special-display-buffer-names';
6277 the cdr of the cons cell is ignored.
6278
6279 See also `same-window-regexps'. */);
6280 Vsame_window_buffer_names = Qnil;
6281
6282 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
6283 doc: /* *List of regexps saying which buffers should appear in the selected window.
6284 If a buffer name matches one of these regexps, then displaying it
6285 using `display-buffer' or `pop-to-buffer' switches to it
6286 in the selected window, rather than making it appear in some other window.
6287
6288 An element of the list can be a cons cell instead of just a string.
6289 Then the car must be a string, which specifies the buffer name.
6290 This is for compatibility with `special-display-buffer-names';
6291 the cdr of the cons cell is ignored.
6292
6293 See also `same-window-buffer-names'. */);
6294 Vsame_window_regexps = Qnil;
6295
6296 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
6297 doc: /* *Non-nil means display-buffer should make new windows. */);
6298 pop_up_windows = 1;
6299
6300 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
6301 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
6302 next_screen_context_lines = 2;
6303
6304 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
6305 doc: /* *display-buffer would prefer to split the largest window if this large.
6306 If there is only one window, it is split regardless of this value. */);
6307 split_height_threshold = 500;
6308
6309 DEFVAR_INT ("window-min-height", &window_min_height,
6310 doc: /* *Delete any window less than this tall (including its mode line). */);
6311 window_min_height = 4;
6312
6313 DEFVAR_INT ("window-min-width", &window_min_width,
6314 doc: /* *Delete any window less than this wide. */);
6315 window_min_width = 10;
6316
6317 DEFVAR_LISP ("scroll-preserve-screen-position",
6318 &Vscroll_preserve_screen_position,
6319 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
6320 Vscroll_preserve_screen_position = Qnil;
6321
6322 DEFVAR_LISP ("window-configuration-change-hook",
6323 &Vwindow_configuration_change_hook,
6324 doc: /* Functions to call when window configuration changes.
6325 The selected frame is the one whose configuration has changed. */);
6326 Vwindow_configuration_change_hook = Qnil;
6327
6328 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6329 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6330 Emacs won't change the size of any window displaying that buffer,
6331 unless you explicitly change the size, or Emacs has no other choice.
6332 This variable automatically becomes buffer-local when set. */);
6333 Fmake_variable_buffer_local (Qwindow_size_fixed);
6334 window_size_fixed = 0;
6335
6336 defsubr (&Sselected_window);
6337 defsubr (&Sminibuffer_window);
6338 defsubr (&Swindow_minibuffer_p);
6339 defsubr (&Swindowp);
6340 defsubr (&Swindow_live_p);
6341 defsubr (&Spos_visible_in_window_p);
6342 defsubr (&Swindow_buffer);
6343 defsubr (&Swindow_height);
6344 defsubr (&Swindow_width);
6345 defsubr (&Swindow_hscroll);
6346 defsubr (&Sset_window_hscroll);
6347 defsubr (&Swindow_redisplay_end_trigger);
6348 defsubr (&Sset_window_redisplay_end_trigger);
6349 defsubr (&Swindow_edges);
6350 defsubr (&Scoordinates_in_window_p);
6351 defsubr (&Swindow_at);
6352 defsubr (&Swindow_point);
6353 defsubr (&Swindow_start);
6354 defsubr (&Swindow_end);
6355 defsubr (&Sset_window_point);
6356 defsubr (&Sset_window_start);
6357 defsubr (&Swindow_dedicated_p);
6358 defsubr (&Sset_window_dedicated_p);
6359 defsubr (&Swindow_display_table);
6360 defsubr (&Sset_window_display_table);
6361 defsubr (&Snext_window);
6362 defsubr (&Sprevious_window);
6363 defsubr (&Sother_window);
6364 defsubr (&Sget_lru_window);
6365 defsubr (&Sget_largest_window);
6366 defsubr (&Sget_buffer_window);
6367 defsubr (&Sdelete_other_windows);
6368 defsubr (&Sdelete_windows_on);
6369 defsubr (&Sreplace_buffer_in_windows);
6370 defsubr (&Sdelete_window);
6371 defsubr (&Sset_window_buffer);
6372 defsubr (&Sselect_window);
6373 defsubr (&Sspecial_display_p);
6374 defsubr (&Ssame_window_p);
6375 defsubr (&Sdisplay_buffer);
6376 defsubr (&Ssplit_window);
6377 defsubr (&Senlarge_window);
6378 defsubr (&Sshrink_window);
6379 defsubr (&Sscroll_up);
6380 defsubr (&Sscroll_down);
6381 defsubr (&Sscroll_left);
6382 defsubr (&Sscroll_right);
6383 defsubr (&Sother_window_for_scrolling);
6384 defsubr (&Sscroll_other_window);
6385 defsubr (&Sminibuffer_selected_window);
6386 defsubr (&Srecenter);
6387 defsubr (&Swindow_text_height);
6388 defsubr (&Smove_to_window_line);
6389 defsubr (&Swindow_configuration_p);
6390 defsubr (&Swindow_configuration_frame);
6391 defsubr (&Sset_window_configuration);
6392 defsubr (&Scurrent_window_configuration);
6393 defsubr (&Ssave_window_excursion);
6394 defsubr (&Sset_window_margins);
6395 defsubr (&Swindow_margins);
6396 defsubr (&Sset_window_fringes);
6397 defsubr (&Swindow_fringes);
6398 defsubr (&Sset_window_scroll_bars);
6399 defsubr (&Swindow_scroll_bars);
6400 defsubr (&Swindow_vscroll);
6401 defsubr (&Sset_window_vscroll);
6402 defsubr (&Scompare_window_configurations);
6403 defsubr (&Swindow_list);
6404 }
6405
6406 void
6407 keys_of_window ()
6408 {
6409 initial_define_key (control_x_map, '1', "delete-other-windows");
6410 initial_define_key (control_x_map, '2', "split-window");
6411 initial_define_key (control_x_map, '0', "delete-window");
6412 initial_define_key (control_x_map, 'o', "other-window");
6413 initial_define_key (control_x_map, '^', "enlarge-window");
6414 initial_define_key (control_x_map, '<', "scroll-left");
6415 initial_define_key (control_x_map, '>', "scroll-right");
6416
6417 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6418 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6419 initial_define_key (meta_map, 'v', "scroll-down");
6420
6421 initial_define_key (global_map, Ctl('L'), "recenter");
6422 initial_define_key (meta_map, 'r', "move-to-window-line");
6423 }