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