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