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