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