]> code.delx.au - gnu-emacs/blob - src/window.c
(sxhash): As far as possible, merge calculation of
[gnu-emacs] / src / window.c
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985,86,87, 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 /* The rest of this function uses current_y in a nonstandard way,
4629 not including the height of the header line if any. */
4630 it.current_y = it.vpos = 0;
4631
4632 /* Preserve the screen position if we should. */
4633 if (preserve_y >= 0)
4634 {
4635 /* If we have a header line, take account of it. */
4636 if (WINDOW_WANTS_HEADER_LINE_P (w))
4637 preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
4638
4639 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4640 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4641 }
4642 else
4643 {
4644 /* Move PT out of scroll margins.
4645 This code wants current_y to be zero at the window start position
4646 even if there is a header line. */
4647 this_scroll_margin = max (0, scroll_margin);
4648 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4649 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4650
4651 if (n > 0)
4652 {
4653 /* We moved the window start towards ZV, so PT may be now
4654 in the scroll margin at the top. */
4655 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4656 while (it.current_y < this_scroll_margin)
4657 {
4658 int prev = it.current_y;
4659 move_it_by_lines (&it, 1, 1);
4660 if (prev == it.current_y)
4661 break;
4662 }
4663 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4664 }
4665 else if (n < 0)
4666 {
4667 int charpos, bytepos;
4668
4669 /* We moved the window start towards BEGV, so PT may be now
4670 in the scroll margin at the bottom. */
4671 move_it_to (&it, PT, -1,
4672 it.last_visible_y - this_scroll_margin - 1, -1,
4673 MOVE_TO_POS | MOVE_TO_Y);
4674
4675 /* Save our position, in case it's correct. */
4676 charpos = IT_CHARPOS (it);
4677 bytepos = IT_BYTEPOS (it);
4678
4679 /* See if point is on a partially visible line at the end. */
4680 move_it_by_lines (&it, 1, 1);
4681 if (it.current_y > it.last_visible_y)
4682 /* The last line was only partially visible, so back up two
4683 lines to make sure we're on a fully visible line. */
4684 {
4685 move_it_by_lines (&it, -2, 0);
4686 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4687 }
4688 else
4689 /* No, the position we saved is OK, so use it. */
4690 SET_PT_BOTH (charpos, bytepos);
4691 }
4692 }
4693 }
4694
4695
4696 /* Implementation of window_scroll that works based on screen lines.
4697 See the comment of window_scroll for parameter descriptions. */
4698
4699 static void
4700 window_scroll_line_based (window, n, whole, noerror)
4701 Lisp_Object window;
4702 int n;
4703 int whole;
4704 int noerror;
4705 {
4706 register struct window *w = XWINDOW (window);
4707 register int opoint = PT, opoint_byte = PT_BYTE;
4708 register int pos, pos_byte;
4709 register int ht = window_internal_height (w);
4710 register Lisp_Object tem;
4711 int lose;
4712 Lisp_Object bolp;
4713 int startpos;
4714 struct position posit;
4715 int original_vpos;
4716
4717 /* If scrolling screen-fulls, compute the number of lines to
4718 scroll from the window's height. */
4719 if (whole)
4720 n *= max (1, ht - next_screen_context_lines);
4721
4722 startpos = marker_position (w->start);
4723
4724 posit = *compute_motion (startpos, 0, 0, 0,
4725 PT, ht, 0,
4726 -1, XINT (w->hscroll),
4727 0, w);
4728 original_vpos = posit.vpos;
4729
4730 XSETFASTINT (tem, PT);
4731 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4732
4733 if (NILP (tem))
4734 {
4735 Fvertical_motion (make_number (- (ht / 2)), window);
4736 startpos = PT;
4737 }
4738
4739 SET_PT (startpos);
4740 lose = n < 0 && PT == BEGV;
4741 Fvertical_motion (make_number (n), window);
4742 pos = PT;
4743 pos_byte = PT_BYTE;
4744 bolp = Fbolp ();
4745 SET_PT_BOTH (opoint, opoint_byte);
4746
4747 if (lose)
4748 {
4749 if (noerror)
4750 return;
4751 else
4752 Fsignal (Qbeginning_of_buffer, Qnil);
4753 }
4754
4755 if (pos < ZV)
4756 {
4757 int this_scroll_margin = scroll_margin;
4758
4759 /* Don't use a scroll margin that is negative or too large. */
4760 if (this_scroll_margin < 0)
4761 this_scroll_margin = 0;
4762
4763 if (XINT (w->total_lines) < 4 * scroll_margin)
4764 this_scroll_margin = XINT (w->total_lines) / 4;
4765
4766 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4767 w->start_at_line_beg = bolp;
4768 w->update_mode_line = Qt;
4769 XSETFASTINT (w->last_modified, 0);
4770 XSETFASTINT (w->last_overlay_modified, 0);
4771 /* Set force_start so that redisplay_window will run
4772 the window-scroll-functions. */
4773 w->force_start = Qt;
4774
4775 if (whole && !NILP (Vscroll_preserve_screen_position))
4776 {
4777 SET_PT_BOTH (pos, pos_byte);
4778 Fvertical_motion (make_number (original_vpos), window);
4779 }
4780 /* If we scrolled forward, put point enough lines down
4781 that it is outside the scroll margin. */
4782 else if (n > 0)
4783 {
4784 int top_margin;
4785
4786 if (this_scroll_margin > 0)
4787 {
4788 SET_PT_BOTH (pos, pos_byte);
4789 Fvertical_motion (make_number (this_scroll_margin), window);
4790 top_margin = PT;
4791 }
4792 else
4793 top_margin = pos;
4794
4795 if (top_margin <= opoint)
4796 SET_PT_BOTH (opoint, opoint_byte);
4797 else if (!NILP (Vscroll_preserve_screen_position))
4798 {
4799 SET_PT_BOTH (pos, pos_byte);
4800 Fvertical_motion (make_number (original_vpos), window);
4801 }
4802 else
4803 SET_PT (top_margin);
4804 }
4805 else if (n < 0)
4806 {
4807 int bottom_margin;
4808
4809 /* If we scrolled backward, put point near the end of the window
4810 but not within the scroll margin. */
4811 SET_PT_BOTH (pos, pos_byte);
4812 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4813 if (XFASTINT (tem) == ht - this_scroll_margin)
4814 bottom_margin = PT;
4815 else
4816 bottom_margin = PT + 1;
4817
4818 if (bottom_margin > opoint)
4819 SET_PT_BOTH (opoint, opoint_byte);
4820 else
4821 {
4822 if (!NILP (Vscroll_preserve_screen_position))
4823 {
4824 SET_PT_BOTH (pos, pos_byte);
4825 Fvertical_motion (make_number (original_vpos), window);
4826 }
4827 else
4828 Fvertical_motion (make_number (-1), window);
4829 }
4830 }
4831 }
4832 else
4833 {
4834 if (noerror)
4835 return;
4836 else
4837 Fsignal (Qend_of_buffer, Qnil);
4838 }
4839 }
4840
4841
4842 /* Scroll selected_window up or down. If N is nil, scroll a
4843 screen-full which is defined as the height of the window minus
4844 next_screen_context_lines. If N is the symbol `-', scroll.
4845 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4846 up. This is the guts of Fscroll_up and Fscroll_down. */
4847
4848 static void
4849 scroll_command (n, direction)
4850 Lisp_Object n;
4851 int direction;
4852 {
4853 int count = SPECPDL_INDEX ();
4854
4855 xassert (abs (direction) == 1);
4856
4857 /* If selected window's buffer isn't current, make it current for
4858 the moment. But don't screw up if window_scroll gets an error. */
4859 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4860 {
4861 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4862 Fset_buffer (XWINDOW (selected_window)->buffer);
4863
4864 /* Make redisplay consider other windows than just selected_window. */
4865 ++windows_or_buffers_changed;
4866 }
4867
4868 if (NILP (n))
4869 window_scroll (selected_window, direction, 1, 0);
4870 else if (EQ (n, Qminus))
4871 window_scroll (selected_window, -direction, 1, 0);
4872 else
4873 {
4874 n = Fprefix_numeric_value (n);
4875 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4876 }
4877
4878 unbind_to (count, Qnil);
4879 }
4880
4881 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4882 doc: /* Scroll text of current window upward ARG lines.
4883 If ARG is omitted or nil, scroll upward by a near full screen.
4884 A near full screen is `next-screen-context-lines' less than a full screen.
4885 Negative ARG means scroll downward.
4886 If ARG is the atom `-', scroll downward by nearly full screen.
4887 When calling from a program, supply as argument a number, nil, or `-'. */)
4888 (arg)
4889 Lisp_Object arg;
4890 {
4891 scroll_command (arg, 1);
4892 return Qnil;
4893 }
4894
4895 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4896 doc: /* Scroll text of current window down ARG lines.
4897 If ARG is omitted or nil, scroll down by a near full screen.
4898 A near full screen is `next-screen-context-lines' less than a full screen.
4899 Negative ARG means scroll upward.
4900 If ARG is the atom `-', scroll upward by nearly full screen.
4901 When calling from a program, supply as argument a number, nil, or `-'. */)
4902 (arg)
4903 Lisp_Object arg;
4904 {
4905 scroll_command (arg, -1);
4906 return Qnil;
4907 }
4908 \f
4909 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4910 doc: /* Return the other window for \"other window scroll\" commands.
4911 If `other-window-scroll-buffer' is non-nil, a window
4912 showing that buffer is used.
4913 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4914 specifies the window. This takes precedence over
4915 `other-window-scroll-buffer'. */)
4916 ()
4917 {
4918 Lisp_Object window;
4919
4920 if (MINI_WINDOW_P (XWINDOW (selected_window))
4921 && !NILP (Vminibuf_scroll_window))
4922 window = Vminibuf_scroll_window;
4923 /* If buffer is specified, scroll that buffer. */
4924 else if (!NILP (Vother_window_scroll_buffer))
4925 {
4926 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4927 if (NILP (window))
4928 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4929 }
4930 else
4931 {
4932 /* Nothing specified; look for a neighboring window on the same
4933 frame. */
4934 window = Fnext_window (selected_window, Qnil, Qnil);
4935
4936 if (EQ (window, selected_window))
4937 /* That didn't get us anywhere; look for a window on another
4938 visible frame. */
4939 do
4940 window = Fnext_window (window, Qnil, Qt);
4941 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4942 && ! EQ (window, selected_window));
4943 }
4944
4945 CHECK_LIVE_WINDOW (window);
4946
4947 if (EQ (window, selected_window))
4948 error ("There is no other window");
4949
4950 return window;
4951 }
4952
4953 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4954 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4955 A near full screen is `next-screen-context-lines' less than a full screen.
4956 The next window is the one below the current one; or the one at the top
4957 if the current one is at the bottom. Negative ARG means scroll downward.
4958 If ARG is the atom `-', scroll downward by nearly full screen.
4959 When calling from a program, supply as argument a number, nil, or `-'.
4960
4961 If `other-window-scroll-buffer' is non-nil, scroll the window
4962 showing that buffer, popping the buffer up if necessary.
4963 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4964 specifies the window to scroll. This takes precedence over
4965 `other-window-scroll-buffer'. */)
4966 (arg)
4967 Lisp_Object arg;
4968 {
4969 Lisp_Object window;
4970 struct window *w;
4971 int count = SPECPDL_INDEX ();
4972
4973 window = Fother_window_for_scrolling ();
4974 w = XWINDOW (window);
4975
4976 /* Don't screw up if window_scroll gets an error. */
4977 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4978 ++windows_or_buffers_changed;
4979
4980 Fset_buffer (w->buffer);
4981 SET_PT (marker_position (w->pointm));
4982
4983 if (NILP (arg))
4984 window_scroll (window, 1, 1, 1);
4985 else if (EQ (arg, Qminus))
4986 window_scroll (window, -1, 1, 1);
4987 else
4988 {
4989 if (CONSP (arg))
4990 arg = Fcar (arg);
4991 CHECK_NUMBER (arg);
4992 window_scroll (window, XINT (arg), 0, 1);
4993 }
4994
4995 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4996 unbind_to (count, Qnil);
4997
4998 return Qnil;
4999 }
5000 \f
5001 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
5002 doc: /* Scroll selected window display ARG columns left.
5003 Default for ARG is window width minus 2.
5004 Value is the total amount of leftward horizontal scrolling in
5005 effect after the change.
5006 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5007 lower bound for automatic scrolling, i.e. automatic scrolling
5008 will not scroll a window to a column less than the value returned
5009 by this function. This happens in an interactive call. */)
5010 (arg, set_minimum)
5011 register Lisp_Object arg, set_minimum;
5012 {
5013 Lisp_Object result;
5014 int hscroll;
5015 struct window *w = XWINDOW (selected_window);
5016
5017 if (NILP (arg))
5018 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5019 else
5020 arg = Fprefix_numeric_value (arg);
5021
5022 hscroll = XINT (w->hscroll) + XINT (arg);
5023 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5024
5025 if (!NILP (set_minimum))
5026 w->min_hscroll = w->hscroll;
5027
5028 return result;
5029 }
5030
5031 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
5032 doc: /* Scroll selected window display ARG columns right.
5033 Default for ARG is window width minus 2.
5034 Value is the total amount of leftward horizontal scrolling in
5035 effect after the change.
5036 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5037 lower bound for automatic scrolling, i.e. automatic scrolling
5038 will not scroll a window to a column less than the value returned
5039 by this function. This happens in an interactive call. */)
5040 (arg, set_minimum)
5041 register Lisp_Object arg, set_minimum;
5042 {
5043 Lisp_Object result;
5044 int hscroll;
5045 struct window *w = XWINDOW (selected_window);
5046
5047 if (NILP (arg))
5048 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5049 else
5050 arg = Fprefix_numeric_value (arg);
5051
5052 hscroll = XINT (w->hscroll) - XINT (arg);
5053 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5054
5055 if (!NILP (set_minimum))
5056 w->min_hscroll = w->hscroll;
5057
5058 return result;
5059 }
5060
5061 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5062 doc: /* Return the window which was selected when entering the minibuffer.
5063 Returns nil, if current window is not a minibuffer window. */)
5064 ()
5065 {
5066 if (minibuf_level > 0
5067 && MINI_WINDOW_P (XWINDOW (selected_window))
5068 && WINDOW_LIVE_P (minibuf_selected_window))
5069 return minibuf_selected_window;
5070
5071 return Qnil;
5072 }
5073
5074 /* Value is the number of lines actually displayed in window W,
5075 as opposed to its height. */
5076
5077 static int
5078 displayed_window_lines (w)
5079 struct window *w;
5080 {
5081 struct it it;
5082 struct text_pos start;
5083 int height = window_box_height (w);
5084 struct buffer *old_buffer;
5085 int bottom_y;
5086
5087 if (XBUFFER (w->buffer) != current_buffer)
5088 {
5089 old_buffer = current_buffer;
5090 set_buffer_internal (XBUFFER (w->buffer));
5091 }
5092 else
5093 old_buffer = NULL;
5094
5095 /* In case W->start is out of the accessible range, do something
5096 reasonable. This happens in Info mode when Info-scroll-down
5097 calls (recenter -1) while W->start is 1. */
5098 if (XMARKER (w->start)->charpos < BEGV)
5099 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5100 else if (XMARKER (w->start)->charpos > ZV)
5101 SET_TEXT_POS (start, ZV, ZV_BYTE);
5102 else
5103 SET_TEXT_POS_FROM_MARKER (start, w->start);
5104
5105 start_display (&it, w, start);
5106 move_it_vertically (&it, height);
5107 bottom_y = line_bottom_y (&it);
5108
5109 /* rms: On a non-window display,
5110 the value of it.vpos at the bottom of the screen
5111 seems to be 1 larger than window_box_height (w).
5112 This kludge fixes a bug whereby (move-to-window-line -1)
5113 when ZV is on the last screen line
5114 moves to the previous screen line instead of the last one. */
5115 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5116 height++;
5117
5118 /* Add in empty lines at the bottom of the window. */
5119 if (bottom_y < height)
5120 {
5121 int uy = FRAME_LINE_HEIGHT (it.f);
5122 it.vpos += (height - bottom_y + uy - 1) / uy;
5123 }
5124
5125 if (old_buffer)
5126 set_buffer_internal (old_buffer);
5127
5128 return it.vpos;
5129 }
5130
5131
5132 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5133 doc: /* Center point in window and redisplay frame.
5134 With prefix argument ARG, recenter putting point on screen line ARG
5135 relative to the current window. If ARG is negative, it counts up from the
5136 bottom of the window. (ARG should be less than the height of the window.)
5137
5138 If ARG is omitted or nil, erase the entire frame and then
5139 redraw with point in the center of the current window.
5140 Just C-u as prefix means put point in the center of the window
5141 and redisplay normally--don't erase and redraw the frame. */)
5142 (arg)
5143 register Lisp_Object arg;
5144 {
5145 struct window *w = XWINDOW (selected_window);
5146 struct buffer *buf = XBUFFER (w->buffer);
5147 struct buffer *obuf = current_buffer;
5148 int center_p = 0;
5149 int charpos, bytepos;
5150
5151 /* If redisplay is suppressed due to an error, try again. */
5152 obuf->display_error_modiff = 0;
5153
5154 if (NILP (arg))
5155 {
5156 int i;
5157
5158 /* Invalidate pixel data calculated for all compositions. */
5159 for (i = 0; i < n_compositions; i++)
5160 composition_table[i]->font = NULL;
5161
5162 Fredraw_frame (w->frame);
5163 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
5164 center_p = 1;
5165 }
5166 else if (CONSP (arg)) /* Just C-u. */
5167 center_p = 1;
5168 else
5169 {
5170 arg = Fprefix_numeric_value (arg);
5171 CHECK_NUMBER (arg);
5172 }
5173
5174 set_buffer_internal (buf);
5175
5176 /* Handle centering on a graphical frame specially. Such frames can
5177 have variable-height lines and centering point on the basis of
5178 line counts would lead to strange effects. */
5179 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5180 {
5181 if (center_p)
5182 {
5183 struct it it;
5184 struct text_pos pt;
5185
5186 SET_TEXT_POS (pt, PT, PT_BYTE);
5187 start_display (&it, w, pt);
5188 move_it_vertically (&it, - window_box_height (w) / 2);
5189 charpos = IT_CHARPOS (it);
5190 bytepos = IT_BYTEPOS (it);
5191 }
5192 else if (XINT (arg) < 0)
5193 {
5194 struct it it;
5195 struct text_pos pt;
5196 int y0, y1, h, nlines;
5197
5198 SET_TEXT_POS (pt, PT, PT_BYTE);
5199 start_display (&it, w, pt);
5200 y0 = it.current_y;
5201
5202 /* The amount of pixels we have to move back is the window
5203 height minus what's displayed in the line containing PT,
5204 and the lines below. */
5205 nlines = - XINT (arg) - 1;
5206 move_it_by_lines (&it, nlines, 1);
5207
5208 y1 = line_bottom_y (&it);
5209
5210 /* If we can't move down NLINES lines because we hit
5211 the end of the buffer, count in some empty lines. */
5212 if (it.vpos < nlines)
5213 y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
5214
5215 h = window_box_height (w) - (y1 - y0);
5216
5217 start_display (&it, w, pt);
5218 move_it_vertically (&it, - h);
5219 charpos = IT_CHARPOS (it);
5220 bytepos = IT_BYTEPOS (it);
5221 }
5222 else
5223 {
5224 struct position pos;
5225 pos = *vmotion (PT, - XINT (arg), w);
5226 charpos = pos.bufpos;
5227 bytepos = pos.bytepos;
5228 }
5229 }
5230 else
5231 {
5232 struct position pos;
5233 int ht = window_internal_height (w);
5234
5235 if (center_p)
5236 arg = make_number (ht / 2);
5237 else if (XINT (arg) < 0)
5238 arg = make_number (XINT (arg) + ht);
5239
5240 pos = *vmotion (PT, - XINT (arg), w);
5241 charpos = pos.bufpos;
5242 bytepos = pos.bytepos;
5243 }
5244
5245 /* Set the new window start. */
5246 set_marker_both (w->start, w->buffer, charpos, bytepos);
5247 w->window_end_valid = Qnil;
5248
5249 w->optional_new_start = Qt;
5250
5251 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5252 w->start_at_line_beg = Qt;
5253 else
5254 w->start_at_line_beg = Qnil;
5255
5256 set_buffer_internal (obuf);
5257 return Qnil;
5258 }
5259
5260
5261 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5262 0, 1, 0,
5263 doc: /* Return the height in lines of the text display area of WINDOW.
5264 This doesn't include the mode-line (or header-line if any) or any
5265 partial-height lines in the text display area. */)
5266 (window)
5267 Lisp_Object window;
5268 {
5269 struct window *w = decode_window (window);
5270 int pixel_height = window_box_height (w);
5271 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5272 return make_number (line_height);
5273 }
5274
5275
5276 \f
5277 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5278 1, 1, "P",
5279 doc: /* Position point relative to window.
5280 With no argument, position point at center of window.
5281 An argument specifies vertical position within the window;
5282 zero means top of window, negative means relative to bottom of window. */)
5283 (arg)
5284 Lisp_Object arg;
5285 {
5286 struct window *w = XWINDOW (selected_window);
5287 int lines, start;
5288 Lisp_Object window;
5289
5290 window = selected_window;
5291 start = marker_position (w->start);
5292 if (start < BEGV || start > ZV)
5293 {
5294 int height = window_internal_height (w);
5295 Fvertical_motion (make_number (- (height / 2)), window);
5296 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5297 w->start_at_line_beg = Fbolp ();
5298 w->force_start = Qt;
5299 }
5300 else
5301 Fgoto_char (w->start);
5302
5303 lines = displayed_window_lines (w);
5304 if (NILP (arg))
5305 XSETFASTINT (arg, lines / 2);
5306 else
5307 {
5308 arg = Fprefix_numeric_value (arg);
5309 if (XINT (arg) < 0)
5310 XSETINT (arg, XINT (arg) + lines);
5311 }
5312
5313 /* Skip past a partially visible first line. */
5314 if (w->vscroll)
5315 XSETINT (arg, XINT (arg) + 1);
5316
5317 return Fvertical_motion (arg, window);
5318 }
5319
5320
5321 \f
5322 /***********************************************************************
5323 Window Configuration
5324 ***********************************************************************/
5325
5326 struct save_window_data
5327 {
5328 EMACS_INT size_from_Lisp_Vector_struct;
5329 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5330 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
5331 Lisp_Object frame_tool_bar_lines;
5332 Lisp_Object selected_frame;
5333 Lisp_Object current_window;
5334 Lisp_Object current_buffer;
5335 Lisp_Object minibuf_scroll_window;
5336 Lisp_Object minibuf_selected_window;
5337 Lisp_Object root_window;
5338 Lisp_Object focus_frame;
5339 /* Record the values of window-min-width and window-min-height
5340 so that window sizes remain consistent with them. */
5341 Lisp_Object min_width, min_height;
5342 /* A vector, each of whose elements is a struct saved_window
5343 for one window. */
5344 Lisp_Object saved_windows;
5345 };
5346
5347 /* This is saved as a Lisp_Vector */
5348 struct saved_window
5349 {
5350 /* these first two must agree with struct Lisp_Vector in lisp.h */
5351 EMACS_INT size_from_Lisp_Vector_struct;
5352 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5353
5354 Lisp_Object window;
5355 Lisp_Object buffer, start, pointm, mark;
5356 Lisp_Object left_col, top_line, total_cols, total_lines;
5357 Lisp_Object hscroll, min_hscroll;
5358 Lisp_Object parent, prev;
5359 Lisp_Object start_at_line_beg;
5360 Lisp_Object display_table;
5361 Lisp_Object orig_top_line, orig_total_lines;
5362 Lisp_Object left_margin_cols, right_margin_cols;
5363 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5364 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5365 };
5366
5367 #define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
5368
5369 #define SAVED_WINDOW_N(swv,n) \
5370 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5371
5372 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5373 doc: /* Return t if OBJECT is a window-configuration object. */)
5374 (object)
5375 Lisp_Object object;
5376 {
5377 if (WINDOW_CONFIGURATIONP (object))
5378 return Qt;
5379 return Qnil;
5380 }
5381
5382 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5383 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5384 (config)
5385 Lisp_Object config;
5386 {
5387 register struct save_window_data *data;
5388 struct Lisp_Vector *saved_windows;
5389
5390 if (! WINDOW_CONFIGURATIONP (config))
5391 wrong_type_argument (Qwindow_configuration_p, config);
5392
5393 data = (struct save_window_data *) XVECTOR (config);
5394 saved_windows = XVECTOR (data->saved_windows);
5395 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5396 }
5397
5398 DEFUN ("set-window-configuration", Fset_window_configuration,
5399 Sset_window_configuration, 1, 1, 0,
5400 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5401 CONFIGURATION must be a value previously returned
5402 by `current-window-configuration' (which see).
5403 If CONFIGURATION was made from a frame that is now deleted,
5404 only frame-independent values can be restored. In this case,
5405 the return value is nil. Otherwise the value is t. */)
5406 (configuration)
5407 Lisp_Object configuration;
5408 {
5409 register struct save_window_data *data;
5410 struct Lisp_Vector *saved_windows;
5411 Lisp_Object new_current_buffer;
5412 Lisp_Object frame;
5413 FRAME_PTR f;
5414 int old_point = -1;
5415
5416 while (!WINDOW_CONFIGURATIONP (configuration))
5417 wrong_type_argument (Qwindow_configuration_p, configuration);
5418
5419 data = (struct save_window_data *) XVECTOR (configuration);
5420 saved_windows = XVECTOR (data->saved_windows);
5421
5422 new_current_buffer = data->current_buffer;
5423 if (NILP (XBUFFER (new_current_buffer)->name))
5424 new_current_buffer = Qnil;
5425 else
5426 {
5427 if (XBUFFER (new_current_buffer) == current_buffer)
5428 old_point = PT;
5429 else
5430 old_point = BUF_PT (XBUFFER (new_current_buffer));
5431 }
5432
5433 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5434 f = XFRAME (frame);
5435
5436 /* If f is a dead frame, don't bother rebuilding its window tree.
5437 However, there is other stuff we should still try to do below. */
5438 if (FRAME_LIVE_P (f))
5439 {
5440 register struct window *w;
5441 register struct saved_window *p;
5442 struct window *root_window;
5443 struct window **leaf_windows;
5444 int n_leaf_windows;
5445 int k, i, n;
5446
5447 /* If the frame has been resized since this window configuration was
5448 made, we change the frame to the size specified in the
5449 configuration, restore the configuration, and then resize it
5450 back. We keep track of the prevailing height in these variables. */
5451 int previous_frame_lines = FRAME_LINES (f);
5452 int previous_frame_cols = FRAME_COLS (f);
5453 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5454 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5455
5456 /* The mouse highlighting code could get screwed up
5457 if it runs during this. */
5458 BLOCK_INPUT;
5459
5460 if (XFASTINT (data->frame_lines) != previous_frame_lines
5461 || XFASTINT (data->frame_cols) != previous_frame_cols)
5462 change_frame_size (f, XFASTINT (data->frame_lines),
5463 XFASTINT (data->frame_cols), 0, 0, 0);
5464 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5465 if (XFASTINT (data->frame_menu_bar_lines)
5466 != previous_frame_menu_bar_lines)
5467 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5468 #ifdef HAVE_WINDOW_SYSTEM
5469 if (XFASTINT (data->frame_tool_bar_lines)
5470 != previous_frame_tool_bar_lines)
5471 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5472 #endif
5473 #endif
5474
5475 /* "Swap out" point from the selected window
5476 into its buffer. We do this now, before
5477 restoring the window contents, and prevent it from
5478 being done later on when we select a new window. */
5479 if (! NILP (XWINDOW (selected_window)->buffer))
5480 {
5481 w = XWINDOW (selected_window);
5482 set_marker_both (w->pointm,
5483 w->buffer,
5484 BUF_PT (XBUFFER (w->buffer)),
5485 BUF_PT_BYTE (XBUFFER (w->buffer)));
5486 }
5487
5488 windows_or_buffers_changed++;
5489 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5490
5491 /* Problem: Freeing all matrices and later allocating them again
5492 is a serious redisplay flickering problem. What we would
5493 really like to do is to free only those matrices not reused
5494 below. */
5495 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5496 leaf_windows
5497 = (struct window **) alloca (count_windows (root_window)
5498 * sizeof (struct window *));
5499 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5500
5501 /* Temporarily avoid any problems with windows that are smaller
5502 than they are supposed to be. */
5503 window_min_height = 1;
5504 window_min_width = 1;
5505
5506 /* Kludge Alert!
5507 Mark all windows now on frame as "deleted".
5508 Restoring the new configuration "undeletes" any that are in it.
5509
5510 Save their current buffers in their height fields, since we may
5511 need it later, if a buffer saved in the configuration is now
5512 dead. */
5513 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5514
5515 for (k = 0; k < saved_windows->size; k++)
5516 {
5517 p = SAVED_WINDOW_N (saved_windows, k);
5518 w = XWINDOW (p->window);
5519 w->next = Qnil;
5520
5521 if (!NILP (p->parent))
5522 w->parent = SAVED_WINDOW_N (saved_windows,
5523 XFASTINT (p->parent))->window;
5524 else
5525 w->parent = Qnil;
5526
5527 if (!NILP (p->prev))
5528 {
5529 w->prev = SAVED_WINDOW_N (saved_windows,
5530 XFASTINT (p->prev))->window;
5531 XWINDOW (w->prev)->next = p->window;
5532 }
5533 else
5534 {
5535 w->prev = Qnil;
5536 if (!NILP (w->parent))
5537 {
5538 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5539 {
5540 XWINDOW (w->parent)->vchild = p->window;
5541 XWINDOW (w->parent)->hchild = Qnil;
5542 }
5543 else
5544 {
5545 XWINDOW (w->parent)->hchild = p->window;
5546 XWINDOW (w->parent)->vchild = Qnil;
5547 }
5548 }
5549 }
5550
5551 /* If we squirreled away the buffer in the window's height,
5552 restore it now. */
5553 if (BUFFERP (w->total_lines))
5554 w->buffer = w->total_lines;
5555 w->left_col = p->left_col;
5556 w->top_line = p->top_line;
5557 w->total_cols = p->total_cols;
5558 w->total_lines = p->total_lines;
5559 w->hscroll = p->hscroll;
5560 w->min_hscroll = p->min_hscroll;
5561 w->display_table = p->display_table;
5562 w->orig_top_line = p->orig_top_line;
5563 w->orig_total_lines = p->orig_total_lines;
5564 w->left_margin_cols = p->left_margin_cols;
5565 w->right_margin_cols = p->right_margin_cols;
5566 w->left_fringe_width = p->left_fringe_width;
5567 w->right_fringe_width = p->right_fringe_width;
5568 w->fringes_outside_margins = p->fringes_outside_margins;
5569 w->scroll_bar_width = p->scroll_bar_width;
5570 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5571 XSETFASTINT (w->last_modified, 0);
5572 XSETFASTINT (w->last_overlay_modified, 0);
5573
5574 /* Reinstall the saved buffer and pointers into it. */
5575 if (NILP (p->buffer))
5576 w->buffer = p->buffer;
5577 else
5578 {
5579 if (!NILP (XBUFFER (p->buffer)->name))
5580 /* If saved buffer is alive, install it. */
5581 {
5582 w->buffer = p->buffer;
5583 w->start_at_line_beg = p->start_at_line_beg;
5584 set_marker_restricted (w->start, p->start, w->buffer);
5585 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5586 Fset_marker (XBUFFER (w->buffer)->mark,
5587 p->mark, w->buffer);
5588
5589 /* As documented in Fcurrent_window_configuration, don't
5590 restore the location of point in the buffer which was
5591 current when the window configuration was recorded. */
5592 if (!EQ (p->buffer, new_current_buffer)
5593 && XBUFFER (p->buffer) == current_buffer)
5594 Fgoto_char (w->pointm);
5595 }
5596 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5597 /* Else unless window has a live buffer, get one. */
5598 {
5599 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5600 /* This will set the markers to beginning of visible
5601 range. */
5602 set_marker_restricted (w->start, make_number (0), w->buffer);
5603 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5604 w->start_at_line_beg = Qt;
5605 }
5606 else
5607 /* Keeping window's old buffer; make sure the markers
5608 are real. */
5609 {
5610 /* Set window markers at start of visible range. */
5611 if (XMARKER (w->start)->buffer == 0)
5612 set_marker_restricted (w->start, make_number (0),
5613 w->buffer);
5614 if (XMARKER (w->pointm)->buffer == 0)
5615 set_marker_restricted_both (w->pointm, w->buffer,
5616 BUF_PT (XBUFFER (w->buffer)),
5617 BUF_PT_BYTE (XBUFFER (w->buffer)));
5618 w->start_at_line_beg = Qt;
5619 }
5620 }
5621 }
5622
5623 FRAME_ROOT_WINDOW (f) = data->root_window;
5624 /* Prevent "swapping out point" in the old selected window
5625 using the buffer that has been restored into it.
5626 Use the point value from the beginning of this function
5627 since unshow_buffer (called from delete_all_subwindows)
5628 could have altered it. */
5629 selected_window = Qnil;
5630 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5631 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5632 make_number (old_point),
5633 XWINDOW (data->current_window)->buffer);
5634
5635 Fselect_window (data->current_window, Qnil);
5636 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5637 = selected_window;
5638
5639 if (NILP (data->focus_frame)
5640 || (FRAMEP (data->focus_frame)
5641 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5642 Fredirect_frame_focus (frame, data->focus_frame);
5643
5644 #if 0 /* I don't understand why this is needed, and it causes problems
5645 when the frame's old selected window has been deleted. */
5646 if (f != selected_frame && FRAME_WINDOW_P (f))
5647 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5648 0, 0);
5649 #endif
5650
5651 /* Set the screen height to the value it had before this function. */
5652 if (previous_frame_lines != FRAME_LINES (f)
5653 || previous_frame_cols != FRAME_COLS (f))
5654 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5655 0, 0, 0);
5656 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5657 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5658 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5659 make_number (0));
5660 #ifdef HAVE_WINDOW_SYSTEM
5661 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5662 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5663 make_number (0));
5664 #endif
5665 #endif
5666
5667 /* Now, free glyph matrices in windows that were not reused. */
5668 for (i = n = 0; i < n_leaf_windows; ++i)
5669 {
5670 if (NILP (leaf_windows[i]->buffer))
5671 {
5672 /* Assert it's not reused as a combination. */
5673 xassert (NILP (leaf_windows[i]->hchild)
5674 && NILP (leaf_windows[i]->vchild));
5675 free_window_matrices (leaf_windows[i]);
5676 }
5677 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5678 ++n;
5679 }
5680
5681 adjust_glyphs (f);
5682
5683 UNBLOCK_INPUT;
5684
5685 /* Fselect_window will have made f the selected frame, so we
5686 reselect the proper frame here. Fhandle_switch_frame will change the
5687 selected window too, but that doesn't make the call to
5688 Fselect_window above totally superfluous; it still sets f's
5689 selected window. */
5690 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5691 do_switch_frame (data->selected_frame, 0, 0);
5692
5693 if (! NILP (Vwindow_configuration_change_hook)
5694 && ! NILP (Vrun_hooks))
5695 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5696 }
5697
5698 if (!NILP (new_current_buffer))
5699 Fset_buffer (new_current_buffer);
5700
5701 /* Restore the minimum heights recorded in the configuration. */
5702 window_min_height = XINT (data->min_height);
5703 window_min_width = XINT (data->min_width);
5704
5705 Vminibuf_scroll_window = data->minibuf_scroll_window;
5706 minibuf_selected_window = data->minibuf_selected_window;
5707
5708 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5709 }
5710
5711 /* Mark all windows now on frame as deleted
5712 by setting their buffers to nil. */
5713
5714 void
5715 delete_all_subwindows (w)
5716 register struct window *w;
5717 {
5718 if (!NILP (w->next))
5719 delete_all_subwindows (XWINDOW (w->next));
5720 if (!NILP (w->vchild))
5721 delete_all_subwindows (XWINDOW (w->vchild));
5722 if (!NILP (w->hchild))
5723 delete_all_subwindows (XWINDOW (w->hchild));
5724
5725 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
5726
5727 if (!NILP (w->buffer))
5728 unshow_buffer (w);
5729
5730 /* We set all three of these fields to nil, to make sure that we can
5731 distinguish this dead window from any live window. Live leaf
5732 windows will have buffer set, and combination windows will have
5733 vchild or hchild set. */
5734 w->buffer = Qnil;
5735 w->vchild = Qnil;
5736 w->hchild = Qnil;
5737
5738 Vwindow_list = Qnil;
5739 }
5740 \f
5741 static int
5742 count_windows (window)
5743 register struct window *window;
5744 {
5745 register int count = 1;
5746 if (!NILP (window->next))
5747 count += count_windows (XWINDOW (window->next));
5748 if (!NILP (window->vchild))
5749 count += count_windows (XWINDOW (window->vchild));
5750 if (!NILP (window->hchild))
5751 count += count_windows (XWINDOW (window->hchild));
5752 return count;
5753 }
5754
5755
5756 /* Fill vector FLAT with leaf windows under W, starting at index I.
5757 Value is last index + 1. */
5758
5759 static int
5760 get_leaf_windows (w, flat, i)
5761 struct window *w;
5762 struct window **flat;
5763 int i;
5764 {
5765 while (w)
5766 {
5767 if (!NILP (w->hchild))
5768 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5769 else if (!NILP (w->vchild))
5770 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5771 else
5772 flat[i++] = w;
5773
5774 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5775 }
5776
5777 return i;
5778 }
5779
5780
5781 /* Return a pointer to the glyph W's physical cursor is on. Value is
5782 null if W's current matrix is invalid, so that no meaningfull glyph
5783 can be returned. */
5784
5785 struct glyph *
5786 get_phys_cursor_glyph (w)
5787 struct window *w;
5788 {
5789 struct glyph_row *row;
5790 struct glyph *glyph;
5791
5792 if (w->phys_cursor.vpos >= 0
5793 && w->phys_cursor.vpos < w->current_matrix->nrows
5794 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5795 row->enabled_p)
5796 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5797 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5798 else
5799 glyph = NULL;
5800
5801 return glyph;
5802 }
5803
5804
5805 static int
5806 save_window_save (window, vector, i)
5807 Lisp_Object window;
5808 struct Lisp_Vector *vector;
5809 int i;
5810 {
5811 register struct saved_window *p;
5812 register struct window *w;
5813 register Lisp_Object tem;
5814
5815 for (;!NILP (window); window = w->next)
5816 {
5817 p = SAVED_WINDOW_N (vector, i);
5818 w = XWINDOW (window);
5819
5820 XSETFASTINT (w->temslot, i++);
5821 p->window = window;
5822 p->buffer = w->buffer;
5823 p->left_col = w->left_col;
5824 p->top_line = w->top_line;
5825 p->total_cols = w->total_cols;
5826 p->total_lines = w->total_lines;
5827 p->hscroll = w->hscroll;
5828 p->min_hscroll = w->min_hscroll;
5829 p->display_table = w->display_table;
5830 p->orig_top_line = w->orig_top_line;
5831 p->orig_total_lines = w->orig_total_lines;
5832 p->left_margin_cols = w->left_margin_cols;
5833 p->right_margin_cols = w->right_margin_cols;
5834 p->left_fringe_width = w->left_fringe_width;
5835 p->right_fringe_width = w->right_fringe_width;
5836 p->fringes_outside_margins = w->fringes_outside_margins;
5837 p->scroll_bar_width = w->scroll_bar_width;
5838 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
5839 if (!NILP (w->buffer))
5840 {
5841 /* Save w's value of point in the window configuration.
5842 If w is the selected window, then get the value of point
5843 from the buffer; pointm is garbage in the selected window. */
5844 if (EQ (window, selected_window))
5845 {
5846 p->pointm = Fmake_marker ();
5847 set_marker_both (p->pointm, w->buffer,
5848 BUF_PT (XBUFFER (w->buffer)),
5849 BUF_PT_BYTE (XBUFFER (w->buffer)));
5850 }
5851 else
5852 p->pointm = Fcopy_marker (w->pointm, Qnil);
5853
5854 p->start = Fcopy_marker (w->start, Qnil);
5855 p->start_at_line_beg = w->start_at_line_beg;
5856
5857 tem = XBUFFER (w->buffer)->mark;
5858 p->mark = Fcopy_marker (tem, Qnil);
5859 }
5860 else
5861 {
5862 p->pointm = Qnil;
5863 p->start = Qnil;
5864 p->mark = Qnil;
5865 p->start_at_line_beg = Qnil;
5866 }
5867
5868 if (NILP (w->parent))
5869 p->parent = Qnil;
5870 else
5871 p->parent = XWINDOW (w->parent)->temslot;
5872
5873 if (NILP (w->prev))
5874 p->prev = Qnil;
5875 else
5876 p->prev = XWINDOW (w->prev)->temslot;
5877
5878 if (!NILP (w->vchild))
5879 i = save_window_save (w->vchild, vector, i);
5880 if (!NILP (w->hchild))
5881 i = save_window_save (w->hchild, vector, i);
5882 }
5883
5884 return i;
5885 }
5886
5887 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5888 Scurrent_window_configuration, 0, 1, 0,
5889 doc: /* Return an object representing the current window configuration of FRAME.
5890 If FRAME is nil or omitted, use the selected frame.
5891 This describes the number of windows, their sizes and current buffers,
5892 and for each displayed buffer, where display starts, and the positions of
5893 point and mark. An exception is made for point in the current buffer:
5894 its value is -not- saved.
5895 This also records the currently selected frame, and FRAME's focus
5896 redirection (see `redirect-frame-focus'). */)
5897 (frame)
5898 Lisp_Object frame;
5899 {
5900 register Lisp_Object tem;
5901 register int n_windows;
5902 register struct save_window_data *data;
5903 register struct Lisp_Vector *vec;
5904 register int i;
5905 FRAME_PTR f;
5906
5907 if (NILP (frame))
5908 frame = selected_frame;
5909 CHECK_LIVE_FRAME (frame);
5910 f = XFRAME (frame);
5911
5912 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5913 vec = allocate_other_vector (VECSIZE (struct save_window_data));
5914 data = (struct save_window_data *)vec;
5915
5916 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
5917 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
5918 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5919 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5920 data->selected_frame = selected_frame;
5921 data->current_window = FRAME_SELECTED_WINDOW (f);
5922 XSETBUFFER (data->current_buffer, current_buffer);
5923 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5924 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5925 data->root_window = FRAME_ROOT_WINDOW (f);
5926 data->focus_frame = FRAME_FOCUS_FRAME (f);
5927 XSETINT (data->min_height, window_min_height);
5928 XSETINT (data->min_width, window_min_width);
5929 tem = Fmake_vector (make_number (n_windows), Qnil);
5930 data->saved_windows = tem;
5931 for (i = 0; i < n_windows; i++)
5932 XVECTOR (tem)->contents[i]
5933 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5934 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5935 XSETWINDOW_CONFIGURATION (tem, data);
5936 return (tem);
5937 }
5938
5939 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5940 0, UNEVALLED, 0,
5941 doc: /* Execute BODY, preserving window sizes and contents.
5942 Return the value of the last form in BODY.
5943 Restore which buffer appears in which window, where display starts,
5944 and the value of point and mark for each window.
5945 Also restore the choice of selected window.
5946 Also restore which buffer is current.
5947 Does not restore the value of point in current buffer.
5948 usage: (save-window-excursion BODY ...) */)
5949 (args)
5950 Lisp_Object args;
5951 {
5952 register Lisp_Object val;
5953 register int count = SPECPDL_INDEX ();
5954
5955 record_unwind_protect (Fset_window_configuration,
5956 Fcurrent_window_configuration (Qnil));
5957 val = Fprogn (args);
5958 return unbind_to (count, val);
5959 }
5960
5961 \f
5962 /***********************************************************************
5963 Marginal Areas
5964 ***********************************************************************/
5965
5966 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5967 2, 3, 0,
5968 doc: /* Set width of marginal areas of window WINDOW.
5969 If WINDOW is nil, set margins of the currently selected window.
5970 Second arg LEFT-WIDTH specifies the number of character cells to
5971 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
5972 does the same for the right marginal area. A nil width parameter
5973 means no margin. */)
5974 (window, left, right)
5975 Lisp_Object window, left, right;
5976 {
5977 struct window *w = decode_window (window);
5978
5979 /* Translate negative or zero widths to nil.
5980 Margins that are too wide have to be checked elsewhere. */
5981
5982 if (!NILP (left))
5983 {
5984 CHECK_NUMBER (left);
5985 if (XINT (left) <= 0)
5986 left = Qnil;
5987 }
5988
5989 if (!NILP (right))
5990 {
5991 CHECK_NUMBER (right);
5992 if (XINT (right) <= 0)
5993 right = Qnil;
5994 }
5995
5996 if (!EQ (w->left_margin_cols, left)
5997 || !EQ (w->right_margin_cols, right))
5998 {
5999 w->left_margin_cols = left;
6000 w->right_margin_cols = right;
6001
6002 adjust_window_margins (w);
6003
6004 ++windows_or_buffers_changed;
6005 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6006 }
6007
6008 return Qnil;
6009 }
6010
6011
6012 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6013 0, 1, 0,
6014 doc: /* Get width of marginal areas of window WINDOW.
6015 If WINDOW is omitted or nil, use the currently selected window.
6016 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6017 If a marginal area does not exist, its width will be returned
6018 as nil. */)
6019 (window)
6020 Lisp_Object window;
6021 {
6022 struct window *w = decode_window (window);
6023 return Fcons (w->left_margin_cols, w->right_margin_cols);
6024 }
6025
6026
6027 \f
6028 /***********************************************************************
6029 Fringes
6030 ***********************************************************************/
6031
6032 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6033 2, 4, 0,
6034 doc: /* Set the fringe widths of window WINDOW.
6035 If WINDOW is nil, set the fringe widths of the currently selected
6036 window.
6037 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6038 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6039 fringe width. If a fringe width arg is nil, that means to use the
6040 frame's default fringe width. Default fringe widths can be set with
6041 the command `set-fringe-style'.
6042 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6043 outside of the display margins. By default, fringes are drawn between
6044 display marginal areas and the text area. */)
6045 (window, left, right, outside_margins)
6046 Lisp_Object window, left, right, outside_margins;
6047 {
6048 struct window *w = decode_window (window);
6049
6050 if (!NILP (left))
6051 CHECK_NATNUM (left);
6052 if (!NILP (right))
6053 CHECK_NATNUM (right);
6054
6055 if (!EQ (w->left_fringe_width, left)
6056 || !EQ (w->right_fringe_width, right)
6057 || !EQ (w->fringes_outside_margins, outside_margins))
6058 {
6059 w->left_fringe_width = left;
6060 w->right_fringe_width = right;
6061 w->fringes_outside_margins = outside_margins;
6062
6063 adjust_window_margins (w);
6064
6065 clear_glyph_matrix (w->current_matrix);
6066 w->window_end_valid = Qnil;
6067
6068 ++windows_or_buffers_changed;
6069 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6070 }
6071
6072 return Qnil;
6073 }
6074
6075
6076 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6077 0, 1, 0,
6078 doc: /* Get width of fringes of window WINDOW.
6079 If WINDOW is omitted or nil, use the currently selected window.
6080 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6081 (window)
6082 Lisp_Object window;
6083 {
6084 struct window *w = decode_window (window);
6085 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6086 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6087 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
6088 Qt : Qnil), Qnil)));
6089 }
6090
6091
6092 \f
6093 /***********************************************************************
6094 Scroll bars
6095 ***********************************************************************/
6096
6097 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6098 2, 4, 0,
6099 doc: /* Set width and type of scroll bars of window WINDOW.
6100 If window is nil, set scroll bars of the currently selected window.
6101 Second parameter WIDTH specifies the pixel width for the scroll bar;
6102 this is automatically adjusted to a multiple of the frame column width.
6103 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6104 bar: left, right, or nil.
6105 If WIDTH is nil, use the frame's scroll-bar width.
6106 If TYPE is t, use the frame's scroll-bar type. */)
6107 (window, width, vertical_type, horizontal_type)
6108 Lisp_Object window, width, vertical_type, horizontal_type;
6109 {
6110 struct window *w = decode_window (window);
6111
6112 if (!NILP (width))
6113 CHECK_NATNUM (width);
6114
6115 if (XINT (width) == 0)
6116 vertical_type = Qnil;
6117
6118 if (!(EQ (vertical_type, Qnil)
6119 || EQ (vertical_type, Qleft)
6120 || EQ (vertical_type, Qright)
6121 || EQ (vertical_type, Qt)))
6122 error ("Invalid type of vertical scroll bar");
6123
6124 if (!EQ (w->scroll_bar_width, width)
6125 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6126 {
6127 w->scroll_bar_width = width;
6128 w->vertical_scroll_bar_type = vertical_type;
6129
6130 adjust_window_margins (w);
6131
6132 clear_glyph_matrix (w->current_matrix);
6133 w->window_end_valid = Qnil;
6134
6135 ++windows_or_buffers_changed;
6136 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6137 }
6138
6139 return Qnil;
6140 }
6141
6142
6143 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6144 0, 1, 0,
6145 doc: /* Get width and type of scroll bars of window WINDOW.
6146 If WINDOW is omitted or nil, use the currently selected window.
6147 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6148 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6149 value. */)
6150 (window)
6151 Lisp_Object window;
6152 {
6153 struct window *w = decode_window (window);
6154 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6155 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6156 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6157 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6158 Fcons (w->vertical_scroll_bar_type,
6159 Fcons (Qnil, Qnil))));
6160 }
6161
6162
6163 \f
6164 /***********************************************************************
6165 Smooth scrolling
6166 ***********************************************************************/
6167
6168 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6169 doc: /* Return the amount by which WINDOW is scrolled vertically.
6170 Use the selected window if WINDOW is nil or omitted.
6171 Normally, value is a multiple of the canonical character height of WINDOW;
6172 optional second arg PIXELS_P means value is measured in pixels. */)
6173 (window, pixels_p)
6174 Lisp_Object window, pixels_p;
6175 {
6176 Lisp_Object result;
6177 struct frame *f;
6178 struct window *w;
6179
6180 if (NILP (window))
6181 window = selected_window;
6182 else
6183 CHECK_WINDOW (window);
6184 w = XWINDOW (window);
6185 f = XFRAME (w->frame);
6186
6187 if (FRAME_WINDOW_P (f))
6188 result = (NILP (pixels_p)
6189 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6190 : make_number (-w->vscroll));
6191 else
6192 result = make_number (0);
6193 return result;
6194 }
6195
6196
6197 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6198 2, 3, 0,
6199 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6200 WINDOW nil means use the selected window. Normally, VSCROLL is a
6201 non-negative multiple of the canonical character height of WINDOW;
6202 optional third arg PIXELS_P non-nil means that VSCROLL is in pixels.
6203 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6204 corresponds to an integral number of pixels. The return value is the
6205 result of this rounding.
6206 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6207 (window, vscroll, pixels_p)
6208 Lisp_Object window, vscroll, pixels_p;
6209 {
6210 struct window *w;
6211 struct frame *f;
6212
6213 if (NILP (window))
6214 window = selected_window;
6215 else
6216 CHECK_WINDOW (window);
6217 CHECK_NUMBER_OR_FLOAT (vscroll);
6218
6219 w = XWINDOW (window);
6220 f = XFRAME (w->frame);
6221
6222 if (FRAME_WINDOW_P (f))
6223 {
6224 int old_dy = w->vscroll;
6225
6226 w->vscroll = - (NILP (pixels_p)
6227 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6228 : XFLOATINT (vscroll));
6229 w->vscroll = min (w->vscroll, 0);
6230
6231 /* Adjust glyph matrix of the frame if the virtual display
6232 area becomes larger than before. */
6233 if (w->vscroll < 0 && w->vscroll < old_dy)
6234 adjust_glyphs (f);
6235
6236 /* Prevent redisplay shortcuts. */
6237 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6238 }
6239
6240 return Fwindow_vscroll (window, pixels_p);
6241 }
6242
6243 \f
6244 /* Call FN for all leaf windows on frame F. FN is called with the
6245 first argument being a pointer to the leaf window, and with
6246 additional argument USER_DATA. Stops when FN returns 0. */
6247
6248 void
6249 foreach_window (f, fn, user_data)
6250 struct frame *f;
6251 int (* fn) P_ ((struct window *, void *));
6252 void *user_data;
6253 {
6254 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6255 }
6256
6257
6258 /* Helper function for foreach_window. Call FN for all leaf windows
6259 reachable from W. FN is called with the first argument being a
6260 pointer to the leaf window, and with additional argument USER_DATA.
6261 Stop when FN returns 0. Value is 0 if stopped by FN. */
6262
6263 static int
6264 foreach_window_1 (w, fn, user_data)
6265 struct window *w;
6266 int (* fn) P_ ((struct window *, void *));
6267 void *user_data;
6268 {
6269 int cont;
6270
6271 for (cont = 1; w && cont;)
6272 {
6273 if (!NILP (w->hchild))
6274 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6275 else if (!NILP (w->vchild))
6276 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6277 else
6278 cont = fn (w, user_data);
6279
6280 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6281 }
6282
6283 return cont;
6284 }
6285
6286
6287 /* Freeze or unfreeze the window start of W unless it is a
6288 mini-window or the selected window. FREEZE_P non-null means freeze
6289 the window start. */
6290
6291 static int
6292 freeze_window_start (w, freeze_p)
6293 struct window *w;
6294 void *freeze_p;
6295 {
6296 if (w == XWINDOW (selected_window)
6297 || MINI_WINDOW_P (w)
6298 || (MINI_WINDOW_P (XWINDOW (selected_window))
6299 && ! NILP (Vminibuf_scroll_window)
6300 && w == XWINDOW (Vminibuf_scroll_window)))
6301 freeze_p = NULL;
6302
6303 w->frozen_window_start_p = freeze_p != NULL;
6304 return 1;
6305 }
6306
6307
6308 /* Freeze or unfreeze the window starts of all leaf windows on frame
6309 F, except the selected window and a mini-window. FREEZE_P non-zero
6310 means freeze the window start. */
6311
6312 void
6313 freeze_window_starts (f, freeze_p)
6314 struct frame *f;
6315 int freeze_p;
6316 {
6317 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6318 }
6319
6320 \f
6321 /***********************************************************************
6322 Initialization
6323 ***********************************************************************/
6324
6325 /* Return 1 if window configurations C1 and C2
6326 describe the same state of affairs. This is used by Fequal. */
6327
6328 int
6329 compare_window_configurations (c1, c2, ignore_positions)
6330 Lisp_Object c1, c2;
6331 int ignore_positions;
6332 {
6333 register struct save_window_data *d1, *d2;
6334 struct Lisp_Vector *sw1, *sw2;
6335 int i;
6336
6337 if (!WINDOW_CONFIGURATIONP (c1))
6338 wrong_type_argument (Qwindow_configuration_p, c1);
6339 if (!WINDOW_CONFIGURATIONP (c2))
6340 wrong_type_argument (Qwindow_configuration_p, c2);
6341
6342 d1 = (struct save_window_data *) XVECTOR (c1);
6343 d2 = (struct save_window_data *) XVECTOR (c2);
6344 sw1 = XVECTOR (d1->saved_windows);
6345 sw2 = XVECTOR (d2->saved_windows);
6346
6347 if (! EQ (d1->frame_cols, d2->frame_cols))
6348 return 0;
6349 if (! EQ (d1->frame_lines, d2->frame_lines))
6350 return 0;
6351 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6352 return 0;
6353 if (! EQ (d1->selected_frame, d2->selected_frame))
6354 return 0;
6355 /* Don't compare the current_window field directly.
6356 Instead see w1_is_current and w2_is_current, below. */
6357 if (! EQ (d1->current_buffer, d2->current_buffer))
6358 return 0;
6359 if (! ignore_positions)
6360 {
6361 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6362 return 0;
6363 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6364 return 0;
6365 }
6366 /* Don't compare the root_window field.
6367 We don't require the two configurations
6368 to use the same window object,
6369 and the two root windows must be equivalent
6370 if everything else compares equal. */
6371 if (! EQ (d1->focus_frame, d2->focus_frame))
6372 return 0;
6373 if (! EQ (d1->min_width, d2->min_width))
6374 return 0;
6375 if (! EQ (d1->min_height, d2->min_height))
6376 return 0;
6377
6378 /* Verify that the two confis have the same number of windows. */
6379 if (sw1->size != sw2->size)
6380 return 0;
6381
6382 for (i = 0; i < sw1->size; i++)
6383 {
6384 struct saved_window *p1, *p2;
6385 int w1_is_current, w2_is_current;
6386
6387 p1 = SAVED_WINDOW_N (sw1, i);
6388 p2 = SAVED_WINDOW_N (sw2, i);
6389
6390 /* Verify that the current windows in the two
6391 configurations correspond to each other. */
6392 w1_is_current = EQ (d1->current_window, p1->window);
6393 w2_is_current = EQ (d2->current_window, p2->window);
6394
6395 if (w1_is_current != w2_is_current)
6396 return 0;
6397
6398 /* Verify that the corresponding windows do match. */
6399 if (! EQ (p1->buffer, p2->buffer))
6400 return 0;
6401 if (! EQ (p1->left_col, p2->left_col))
6402 return 0;
6403 if (! EQ (p1->top_line, p2->top_line))
6404 return 0;
6405 if (! EQ (p1->total_cols, p2->total_cols))
6406 return 0;
6407 if (! EQ (p1->total_lines, p2->total_lines))
6408 return 0;
6409 if (! EQ (p1->display_table, p2->display_table))
6410 return 0;
6411 if (! EQ (p1->parent, p2->parent))
6412 return 0;
6413 if (! EQ (p1->prev, p2->prev))
6414 return 0;
6415 if (! ignore_positions)
6416 {
6417 if (! EQ (p1->hscroll, p2->hscroll))
6418 return 0;
6419 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6420 return 0;
6421 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6422 return 0;
6423 if (NILP (Fequal (p1->start, p2->start)))
6424 return 0;
6425 if (NILP (Fequal (p1->pointm, p2->pointm)))
6426 return 0;
6427 if (NILP (Fequal (p1->mark, p2->mark)))
6428 return 0;
6429 }
6430 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6431 return 0;
6432 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6433 return 0;
6434 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6435 return 0;
6436 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6437 return 0;
6438 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6439 return 0;
6440 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6441 return 0;
6442 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6443 return 0;
6444 }
6445
6446 return 1;
6447 }
6448
6449 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6450 Scompare_window_configurations, 2, 2, 0,
6451 doc: /* Compare two window configurations as regards the structure of windows.
6452 This function ignores details such as the values of point and mark
6453 and scrolling positions. */)
6454 (x, y)
6455 Lisp_Object x, y;
6456 {
6457 if (compare_window_configurations (x, y, 1))
6458 return Qt;
6459 return Qnil;
6460 }
6461 \f
6462 void
6463 init_window_once ()
6464 {
6465 struct frame *f = make_terminal_frame ();
6466 XSETFRAME (selected_frame, f);
6467 Vterminal_frame = selected_frame;
6468 minibuf_window = f->minibuffer_window;
6469 selected_window = f->selected_window;
6470 last_nonminibuf_frame = f;
6471
6472 window_initialized = 1;
6473 }
6474
6475 void
6476 init_window ()
6477 {
6478 Vwindow_list = Qnil;
6479 }
6480
6481 void
6482 syms_of_window ()
6483 {
6484 Qwindow_size_fixed = intern ("window-size-fixed");
6485 staticpro (&Qwindow_size_fixed);
6486
6487 staticpro (&Qwindow_configuration_change_hook);
6488 Qwindow_configuration_change_hook
6489 = intern ("window-configuration-change-hook");
6490
6491 Qwindowp = intern ("windowp");
6492 staticpro (&Qwindowp);
6493
6494 Qwindow_configuration_p = intern ("window-configuration-p");
6495 staticpro (&Qwindow_configuration_p);
6496
6497 Qwindow_live_p = intern ("window-live-p");
6498 staticpro (&Qwindow_live_p);
6499
6500 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
6501 staticpro (&Qtemp_buffer_show_hook);
6502
6503 staticpro (&Vwindow_list);
6504
6505 minibuf_selected_window = Qnil;
6506 staticpro (&minibuf_selected_window);
6507
6508 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
6509 doc: /* Non-nil means call as function to display a help buffer.
6510 The function is called with one argument, the buffer to be displayed.
6511 Used by `with-output-to-temp-buffer'.
6512 If this function is used, then it must do the entire job of showing
6513 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6514 Vtemp_buffer_show_function = Qnil;
6515
6516 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
6517 doc: /* If non-nil, function to call to handle `display-buffer'.
6518 It will receive two args, the buffer and a flag which if non-nil means
6519 that the currently selected window is not acceptable.
6520 It should choose or create a window, display the specified buffer in it,
6521 and return the window.
6522 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
6523 work using this function. */);
6524 Vdisplay_buffer_function = Qnil;
6525
6526 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
6527 doc: /* *If non-nil, `display-buffer' should even the window heights.
6528 If nil, `display-buffer' will leave the window configuration alone. */);
6529 Veven_window_heights = Qt;
6530
6531 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
6532 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6533 Vminibuf_scroll_window = Qnil;
6534
6535 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
6536 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6537 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6538 is displayed in the `mode-line' face. */);
6539 mode_line_in_non_selected_windows = 1;
6540
6541 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
6542 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6543 Vother_window_scroll_buffer = Qnil;
6544
6545 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
6546 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
6547 pop_up_frames = 0;
6548
6549 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
6550 doc: /* *Non-nil means `display-buffer' should reuse frames.
6551 If the buffer in question is already displayed in a frame, raise that frame. */);
6552 display_buffer_reuse_frames = 0;
6553
6554 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
6555 doc: /* Function to call to handle automatic new frame creation.
6556 It is called with no arguments and should return a newly created frame.
6557
6558 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
6559 where `pop-up-frame-alist' would hold the default frame parameters. */);
6560 Vpop_up_frame_function = Qnil;
6561
6562 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
6563 doc: /* *List of buffer names that should have their own special frames.
6564 Displaying a buffer whose name is in this list makes a special frame for it
6565 using `special-display-function'. See also `special-display-regexps'.
6566
6567 An element of the list can be a list instead of just a string.
6568 There are two ways to use a list as an element:
6569 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
6570 In the first case, the FRAME-PARAMETERS are pairs of the form
6571 \(PARAMETER . VALUE); these parameter values are used to create the frame.
6572 In the second case, FUNCTION is called with BUFFER as the first argument,
6573 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
6574 All this is done by the function found in `special-display-function'.
6575
6576 If the specified frame parameters include (same-buffer . t), the
6577 buffer is displayed in the currently selected window. Otherwise, if
6578 they include (same-frame . t), the buffer is displayed in a new window
6579 in the currently selected frame.
6580
6581 If this variable appears \"not to work\", because you add a name to it
6582 but that buffer still appears in the selected window, look at the
6583 values of `same-window-buffer-names' and `same-window-regexps'.
6584 Those variables take precedence over this one. */);
6585 Vspecial_display_buffer_names = Qnil;
6586
6587 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
6588 doc: /* *List of regexps saying which buffers should have their own special frames.
6589 If a buffer name matches one of these regexps, it gets its own frame.
6590 Displaying a buffer whose name is in this list makes a special frame for it
6591 using `special-display-function'.
6592
6593 An element of the list can be a list instead of just a string.
6594 There are two ways to use a list as an element:
6595 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6596 In the first case, the FRAME-PARAMETERS are pairs of the form
6597 \(PARAMETER . VALUE); these parameter values are used to create the frame.
6598 In the second case, FUNCTION is called with BUFFER as the first argument,
6599 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
6600 All this is done by the function found in `special-display-function'.
6601
6602 If the specified frame parameters include (same-buffer . t), the
6603 buffer is displayed in the currently selected window. Otherwise, if
6604 they include (same-frame . t), the buffer is displayed in a new window
6605 in the currently selected frame.
6606
6607 If this variable appears \"not to work\", because you add a regexp to it
6608 but the matching buffers still appear in the selected window, look at the
6609 values of `same-window-buffer-names' and `same-window-regexps'.
6610 Those variables take precedence over this one. */);
6611 Vspecial_display_regexps = Qnil;
6612
6613 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
6614 doc: /* Function to call to make a new frame for a special buffer.
6615 It is called with two arguments, the buffer and optional buffer specific
6616 data, and should return a window displaying that buffer.
6617 The default value normally makes a separate frame for the buffer,
6618 using `special-display-frame-alist' to specify the frame parameters.
6619 But if the buffer specific data includes (same-buffer . t) then the
6620 buffer is displayed in the current selected window.
6621 Otherwise if it includes (same-frame . t) then the buffer is displayed in
6622 a new window in the currently selected frame.
6623
6624 A buffer is special if it is listed in `special-display-buffer-names'
6625 or matches a regexp in `special-display-regexps'. */);
6626 Vspecial_display_function = Qnil;
6627
6628 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
6629 doc: /* *List of buffer names that should appear in the selected window.
6630 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6631 switches to it in the selected window, rather than making it appear
6632 in some other window.
6633
6634 An element of the list can be a cons cell instead of just a string.
6635 Then the car must be a string, which specifies the buffer name.
6636 This is for compatibility with `special-display-buffer-names';
6637 the cdr of the cons cell is ignored.
6638
6639 See also `same-window-regexps'. */);
6640 Vsame_window_buffer_names = Qnil;
6641
6642 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
6643 doc: /* *List of regexps saying which buffers should appear in the selected window.
6644 If a buffer name matches one of these regexps, then displaying it
6645 using `display-buffer' or `pop-to-buffer' switches to it
6646 in the selected window, rather than making it appear in some other window.
6647
6648 An element of the list can be a cons cell instead of just a string.
6649 Then the car must be a string, which specifies the buffer name.
6650 This is for compatibility with `special-display-buffer-names';
6651 the cdr of the cons cell is ignored.
6652
6653 See also `same-window-buffer-names'. */);
6654 Vsame_window_regexps = Qnil;
6655
6656 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
6657 doc: /* *Non-nil means display-buffer should make new windows. */);
6658 pop_up_windows = 1;
6659
6660 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
6661 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
6662 next_screen_context_lines = 2;
6663
6664 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
6665 doc: /* *A window must be at least this tall to be eligible for splitting by `display-buffer'.
6666 If there is only one window, it is split regardless of this value. */);
6667 split_height_threshold = 500;
6668
6669 DEFVAR_INT ("window-min-height", &window_min_height,
6670 doc: /* *Delete any window less than this tall (including its mode line). */);
6671 window_min_height = 4;
6672
6673 DEFVAR_INT ("window-min-width", &window_min_width,
6674 doc: /* *Delete any window less than this wide. */);
6675 window_min_width = 10;
6676
6677 DEFVAR_LISP ("scroll-preserve-screen-position",
6678 &Vscroll_preserve_screen_position,
6679 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
6680 Vscroll_preserve_screen_position = Qnil;
6681
6682 DEFVAR_LISP ("window-configuration-change-hook",
6683 &Vwindow_configuration_change_hook,
6684 doc: /* Functions to call when window configuration changes.
6685 The selected frame is the one whose configuration has changed. */);
6686 Vwindow_configuration_change_hook = Qnil;
6687
6688 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6689 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6690 If the value is`height', then only the window's height is fixed.
6691 If the value is `width', then only the window's width is fixed.
6692 Any other non-nil value fixes both the width and the height.
6693 Emacs won't change the size of any window displaying that buffer,
6694 unless you explicitly change the size, or Emacs has no other choice. */);
6695 Fmake_variable_buffer_local (Qwindow_size_fixed);
6696 window_size_fixed = 0;
6697
6698 defsubr (&Sselected_window);
6699 defsubr (&Sminibuffer_window);
6700 defsubr (&Swindow_minibuffer_p);
6701 defsubr (&Swindowp);
6702 defsubr (&Swindow_live_p);
6703 defsubr (&Spos_visible_in_window_p);
6704 defsubr (&Swindow_buffer);
6705 defsubr (&Swindow_height);
6706 defsubr (&Swindow_width);
6707 defsubr (&Swindow_hscroll);
6708 defsubr (&Sset_window_hscroll);
6709 defsubr (&Swindow_redisplay_end_trigger);
6710 defsubr (&Sset_window_redisplay_end_trigger);
6711 defsubr (&Swindow_edges);
6712 defsubr (&Swindow_pixel_edges);
6713 defsubr (&Swindow_inside_edges);
6714 defsubr (&Swindow_inside_pixel_edges);
6715 defsubr (&Scoordinates_in_window_p);
6716 defsubr (&Swindow_at);
6717 defsubr (&Swindow_point);
6718 defsubr (&Swindow_start);
6719 defsubr (&Swindow_end);
6720 defsubr (&Sset_window_point);
6721 defsubr (&Sset_window_start);
6722 defsubr (&Swindow_dedicated_p);
6723 defsubr (&Sset_window_dedicated_p);
6724 defsubr (&Swindow_display_table);
6725 defsubr (&Sset_window_display_table);
6726 defsubr (&Snext_window);
6727 defsubr (&Sprevious_window);
6728 defsubr (&Sother_window);
6729 defsubr (&Sget_lru_window);
6730 defsubr (&Sget_largest_window);
6731 defsubr (&Sget_buffer_window);
6732 defsubr (&Sdelete_other_windows);
6733 defsubr (&Sdelete_windows_on);
6734 defsubr (&Sreplace_buffer_in_windows);
6735 defsubr (&Sdelete_window);
6736 defsubr (&Sset_window_buffer);
6737 defsubr (&Sselect_window);
6738 defsubr (&Sspecial_display_p);
6739 defsubr (&Ssame_window_p);
6740 defsubr (&Sdisplay_buffer);
6741 defsubr (&Sforce_window_update);
6742 defsubr (&Ssplit_window);
6743 defsubr (&Senlarge_window);
6744 defsubr (&Sshrink_window);
6745 defsubr (&Sscroll_up);
6746 defsubr (&Sscroll_down);
6747 defsubr (&Sscroll_left);
6748 defsubr (&Sscroll_right);
6749 defsubr (&Sother_window_for_scrolling);
6750 defsubr (&Sscroll_other_window);
6751 defsubr (&Sminibuffer_selected_window);
6752 defsubr (&Srecenter);
6753 defsubr (&Swindow_text_height);
6754 defsubr (&Smove_to_window_line);
6755 defsubr (&Swindow_configuration_p);
6756 defsubr (&Swindow_configuration_frame);
6757 defsubr (&Sset_window_configuration);
6758 defsubr (&Scurrent_window_configuration);
6759 defsubr (&Ssave_window_excursion);
6760 defsubr (&Sset_window_margins);
6761 defsubr (&Swindow_margins);
6762 defsubr (&Sset_window_fringes);
6763 defsubr (&Swindow_fringes);
6764 defsubr (&Sset_window_scroll_bars);
6765 defsubr (&Swindow_scroll_bars);
6766 defsubr (&Swindow_vscroll);
6767 defsubr (&Sset_window_vscroll);
6768 defsubr (&Scompare_window_configurations);
6769 defsubr (&Swindow_list);
6770 }
6771
6772 void
6773 keys_of_window ()
6774 {
6775 initial_define_key (control_x_map, '1', "delete-other-windows");
6776 initial_define_key (control_x_map, '2', "split-window");
6777 initial_define_key (control_x_map, '0', "delete-window");
6778 initial_define_key (control_x_map, 'o', "other-window");
6779 initial_define_key (control_x_map, '^', "enlarge-window");
6780 initial_define_key (control_x_map, '<', "scroll-left");
6781 initial_define_key (control_x_map, '>', "scroll-right");
6782
6783 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6784 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6785 initial_define_key (meta_map, 'v', "scroll-down");
6786
6787 initial_define_key (global_map, Ctl('L'), "recenter");
6788 initial_define_key (meta_map, 'r', "move-to-window-line");
6789 }
6790
6791 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
6792 (do not change this comment) */