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