]> code.delx.au - gnu-emacs/blob - src/window.c
(draw_window_fringes): Return value now indicates if
[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 would be created specially.
3218 The value is actually t if the frame should be called with default frame
3219 parameters, and a list of frame parameters if they were specified.
3220 See `special-display-buffer-names', and `special-display-regexps'. */)
3221 (buffer_name)
3222 Lisp_Object buffer_name;
3223 {
3224 Lisp_Object tem;
3225
3226 CHECK_STRING (buffer_name);
3227
3228 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3229 if (!NILP (tem))
3230 return Qt;
3231
3232 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3233 if (!NILP (tem))
3234 return XCDR (tem);
3235
3236 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3237 {
3238 Lisp_Object car = XCAR (tem);
3239 if (STRINGP (car)
3240 && fast_string_match (car, buffer_name) >= 0)
3241 return Qt;
3242 else if (CONSP (car)
3243 && STRINGP (XCAR (car))
3244 && fast_string_match (XCAR (car), buffer_name) >= 0)
3245 return XCDR (car);
3246 }
3247 return Qnil;
3248 }
3249
3250 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3251 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
3252 See `same-window-buffer-names' and `same-window-regexps'. */)
3253 (buffer_name)
3254 Lisp_Object buffer_name;
3255 {
3256 Lisp_Object tem;
3257
3258 CHECK_STRING (buffer_name);
3259
3260 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3261 if (!NILP (tem))
3262 return Qt;
3263
3264 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3265 if (!NILP (tem))
3266 return Qt;
3267
3268 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3269 {
3270 Lisp_Object car = XCAR (tem);
3271 if (STRINGP (car)
3272 && fast_string_match (car, buffer_name) >= 0)
3273 return Qt;
3274 else if (CONSP (car)
3275 && STRINGP (XCAR (car))
3276 && fast_string_match (XCAR (car), buffer_name) >= 0)
3277 return Qt;
3278 }
3279 return Qnil;
3280 }
3281
3282 /* Use B so the default is (other-buffer). */
3283 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3284 "BDisplay buffer: \nP",
3285 doc: /* Make BUFFER appear in some window but don't select it.
3286 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3287 a buffer.
3288 If BUFFER is shown already in some window, just use that one,
3289 unless the window is the selected window and the optional second
3290 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3291 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3292 Returns the window displaying BUFFER.
3293 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3294 displaying BUFFER, then simply raise that frame.
3295
3296 The variables `special-display-buffer-names',
3297 `special-display-regexps', `same-window-buffer-names', and
3298 `same-window-regexps' customize how certain buffer names are handled.
3299 The latter two take effect only if NOT-THIS-WINDOW is t.
3300
3301 If optional argument FRAME is `visible', search all visible frames.
3302 If FRAME is 0, search all visible and iconified frames.
3303 If FRAME is t, search all frames.
3304 If FRAME is a frame, search only that frame.
3305 If FRAME is nil, search only the selected frame
3306 (actually the last nonminibuffer frame),
3307 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3308 which means search visible and iconified frames.
3309
3310 If a full-width window on a splittable frame is available to display
3311 the buffer, it may be split, subject to the value of the variable
3312 `split-height-threshold'.
3313
3314 If `even-window-heights' is non-nil, window heights will be evened out
3315 if displaying the buffer causes two vertically adjacent windows to be
3316 displayed. */)
3317 (buffer, not_this_window, frame)
3318 register Lisp_Object buffer, not_this_window, frame;
3319 {
3320 register Lisp_Object window, tem, swp;
3321 struct frame *f;
3322
3323 swp = Qnil;
3324 buffer = Fget_buffer (buffer);
3325 CHECK_BUFFER (buffer);
3326
3327 if (!NILP (Vdisplay_buffer_function))
3328 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3329
3330 if (NILP (not_this_window)
3331 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3332 return display_buffer_1 (selected_window);
3333
3334 /* See if the user has specified this buffer should appear
3335 in the selected window. */
3336 if (NILP (not_this_window))
3337 {
3338 swp = Fsame_window_p (XBUFFER (buffer)->name);
3339 if (!NILP (swp) && !no_switch_window (selected_window))
3340 {
3341 Fswitch_to_buffer (buffer, Qnil);
3342 return display_buffer_1 (selected_window);
3343 }
3344 }
3345
3346 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3347 look for a window showing BUFFER on any visible or iconified frame.
3348 Otherwise search only the current frame. */
3349 if (! NILP (frame))
3350 tem = frame;
3351 else if (pop_up_frames
3352 || display_buffer_reuse_frames
3353 || last_nonminibuf_frame == 0)
3354 XSETFASTINT (tem, 0);
3355 else
3356 XSETFRAME (tem, last_nonminibuf_frame);
3357
3358 window = Fget_buffer_window (buffer, tem);
3359 if (!NILP (window)
3360 && (NILP (not_this_window) || !EQ (window, selected_window)))
3361 return display_buffer_1 (window);
3362
3363 /* Certain buffer names get special handling. */
3364 if (!NILP (Vspecial_display_function) && NILP (swp))
3365 {
3366 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3367 if (EQ (tem, Qt))
3368 return call1 (Vspecial_display_function, buffer);
3369 if (CONSP (tem))
3370 return call2 (Vspecial_display_function, buffer, tem);
3371 }
3372
3373 /* If there are no frames open that have more than a minibuffer,
3374 we need to create a new frame. */
3375 if (pop_up_frames || last_nonminibuf_frame == 0)
3376 {
3377 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3378 Fset_window_buffer (window, buffer, Qnil);
3379 return display_buffer_1 (window);
3380 }
3381
3382 f = SELECTED_FRAME ();
3383 if (pop_up_windows
3384 || FRAME_MINIBUF_ONLY_P (f)
3385 /* If the current frame is a special display frame,
3386 don't try to reuse its windows. */
3387 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3388 {
3389 Lisp_Object frames;
3390
3391 frames = Qnil;
3392 if (FRAME_MINIBUF_ONLY_P (f))
3393 XSETFRAME (frames, last_nonminibuf_frame);
3394 /* Don't try to create a window if we would get an error. */
3395 if (split_height_threshold < window_min_height << 1)
3396 split_height_threshold = window_min_height << 1;
3397
3398 /* Note that both Fget_largest_window and Fget_lru_window
3399 ignore minibuffers and dedicated windows.
3400 This means they can return nil. */
3401
3402 /* If the frame we would try to split cannot be split,
3403 try other frames. */
3404 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3405 {
3406 /* Try visible frames first. */
3407 window = Fget_largest_window (Qvisible);
3408 /* If that didn't work, try iconified frames. */
3409 if (NILP (window))
3410 window = Fget_largest_window (make_number (0));
3411 if (NILP (window))
3412 window = Fget_largest_window (Qt);
3413 }
3414 else
3415 window = Fget_largest_window (frames);
3416
3417 /* If we got a tall enough full-width window that can be split,
3418 split it. */
3419 if (!NILP (window)
3420 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3421 && window_height (window) >= split_height_threshold
3422 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3423 window = Fsplit_window (window, Qnil, Qnil);
3424 else
3425 {
3426 Lisp_Object upper, lower, other;
3427
3428 window = Fget_lru_window (frames);
3429 /* If the LRU window is selected, and big enough,
3430 and can be split, split it. */
3431 if (!NILP (window)
3432 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3433 && (EQ (window, selected_window)
3434 || EQ (XWINDOW (window)->parent, Qnil))
3435 && window_height (window) >= window_min_height << 1)
3436 window = Fsplit_window (window, Qnil, Qnil);
3437 /* If Fget_lru_window returned nil, try other approaches. */
3438
3439 /* Try visible frames first. */
3440 if (NILP (window))
3441 window = Fget_buffer_window (buffer, Qvisible);
3442 if (NILP (window))
3443 window = Fget_largest_window (Qvisible);
3444 /* If that didn't work, try iconified frames. */
3445 if (NILP (window))
3446 window = Fget_buffer_window (buffer, make_number (0));
3447 if (NILP (window))
3448 window = Fget_largest_window (make_number (0));
3449 /* Try invisible frames. */
3450 if (NILP (window))
3451 window = Fget_buffer_window (buffer, Qt);
3452 if (NILP (window))
3453 window = Fget_largest_window (Qt);
3454 /* As a last resort, make a new frame. */
3455 if (NILP (window))
3456 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3457 /* If window appears above or below another,
3458 even out their heights. */
3459 other = upper = lower = Qnil;
3460 if (!NILP (XWINDOW (window)->prev))
3461 other = upper = XWINDOW (window)->prev, lower = window;
3462 if (!NILP (XWINDOW (window)->next))
3463 other = lower = XWINDOW (window)->next, upper = window;
3464 if (!NILP (other)
3465 && !NILP (Veven_window_heights)
3466 /* Check that OTHER and WINDOW are vertically arrayed. */
3467 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3468 && (XFASTINT (XWINDOW (other)->total_lines)
3469 > XFASTINT (XWINDOW (window)->total_lines)))
3470 {
3471 int total = (XFASTINT (XWINDOW (other)->total_lines)
3472 + XFASTINT (XWINDOW (window)->total_lines));
3473 enlarge_window (upper,
3474 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3475 0, 0);
3476 }
3477 }
3478 }
3479 else
3480 window = Fget_lru_window (Qnil);
3481
3482 Fset_window_buffer (window, buffer, Qnil);
3483 return display_buffer_1 (window);
3484 }
3485
3486
3487 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3488 0, 1, 0,
3489 doc: /* Force redisplay of all windows.
3490 If optional arg OBJECT is a window, force redisplay of that window only.
3491 If OBJECT is a buffer or buffer name, force redisplay of all windows
3492 displaying that buffer. */)
3493 (object)
3494 Lisp_Object object;
3495 {
3496 if (NILP (object))
3497 {
3498 windows_or_buffers_changed++;
3499 update_mode_lines++;
3500 return Qt;
3501 }
3502
3503 if (WINDOWP (object))
3504 {
3505 struct window *w = XWINDOW (object);
3506 mark_window_display_accurate (object, 0);
3507 w->update_mode_line = Qt;
3508 if (BUFFERP (w->buffer))
3509 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3510 ++update_mode_lines;
3511 return Qt;
3512 }
3513
3514 if (STRINGP (object))
3515 object = Fget_buffer (object);
3516 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3517 {
3518 /* Walk all windows looking for buffer, and force update
3519 of each of those windows. */
3520
3521 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3522 return NILP (object) ? Qnil : Qt;
3523 }
3524
3525 /* If nothing suitable was found, just return.
3526 We could signal an error, but this feature will typically be used
3527 asynchronously in timers or process sentinels, so we don't. */
3528 return Qnil;
3529 }
3530
3531
3532 void
3533 temp_output_buffer_show (buf)
3534 register Lisp_Object buf;
3535 {
3536 register struct buffer *old = current_buffer;
3537 register Lisp_Object window;
3538 register struct window *w;
3539
3540 XBUFFER (buf)->directory = current_buffer->directory;
3541
3542 Fset_buffer (buf);
3543 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3544 BEGV = BEG;
3545 ZV = Z;
3546 SET_PT (BEG);
3547 #if 0 /* rms: there should be no reason for this. */
3548 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3549 #endif
3550 set_buffer_internal (old);
3551
3552 if (!EQ (Vtemp_buffer_show_function, Qnil))
3553 call1 (Vtemp_buffer_show_function, buf);
3554 else
3555 {
3556 window = Fdisplay_buffer (buf, Qnil, Qnil);
3557
3558 if (!EQ (XWINDOW (window)->frame, selected_frame))
3559 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3560 Vminibuf_scroll_window = window;
3561 w = XWINDOW (window);
3562 XSETFASTINT (w->hscroll, 0);
3563 XSETFASTINT (w->min_hscroll, 0);
3564 set_marker_restricted_both (w->start, buf, BEG, BEG);
3565 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3566
3567 /* Run temp-buffer-show-hook, with the chosen window selected
3568 and its buffer current. */
3569
3570 if (!NILP (Vrun_hooks)
3571 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3572 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3573 {
3574 int count = SPECPDL_INDEX ();
3575 Lisp_Object prev_window, prev_buffer;
3576 prev_window = selected_window;
3577 XSETBUFFER (prev_buffer, old);
3578
3579 /* Select the window that was chosen, for running the hook.
3580 Note: Both Fselect_window and select_window_norecord may
3581 set-buffer to the buffer displayed in the window,
3582 so we need to save the current buffer. --stef */
3583 record_unwind_protect (Fset_buffer, prev_buffer);
3584 record_unwind_protect (select_window_norecord, prev_window);
3585 Fselect_window (window, Qt);
3586 Fset_buffer (w->buffer);
3587 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3588 unbind_to (count, Qnil);
3589 }
3590 }
3591 }
3592 \f
3593 static void
3594 make_dummy_parent (window)
3595 Lisp_Object window;
3596 {
3597 Lisp_Object new;
3598 register struct window *o, *p;
3599 int i;
3600
3601 o = XWINDOW (window);
3602 p = allocate_window ();
3603 for (i = 0; i < VECSIZE (struct window); ++i)
3604 ((struct Lisp_Vector *) p)->contents[i]
3605 = ((struct Lisp_Vector *)o)->contents[i];
3606 XSETWINDOW (new, p);
3607
3608 XSETFASTINT (p->sequence_number, ++sequence_number);
3609
3610 /* Put new into window structure in place of window */
3611 replace_window (window, new);
3612
3613 o->next = Qnil;
3614 o->prev = Qnil;
3615 o->vchild = Qnil;
3616 o->hchild = Qnil;
3617 o->parent = new;
3618
3619 p->start = Qnil;
3620 p->pointm = Qnil;
3621 p->buffer = Qnil;
3622 }
3623
3624 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3625 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3626 WINDOW defaults to selected one and SIZE to half its size.
3627 If optional third arg HORFLAG is non-nil, split side by side
3628 and put SIZE columns in the first of the pair. In that case,
3629 SIZE includes that window's scroll bar, or the divider column to its right.
3630 Interactively, all arguments are nil.
3631
3632 Returns the newly created window (which is the lower or rightmost one).
3633 The upper or leftmost window is the original one and remains selected.
3634 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
3635 (window, size, horflag)
3636 Lisp_Object window, size, horflag;
3637 {
3638 register Lisp_Object new;
3639 register struct window *o, *p;
3640 FRAME_PTR fo;
3641 register int size_int;
3642
3643 if (NILP (window))
3644 window = selected_window;
3645 else
3646 CHECK_LIVE_WINDOW (window);
3647
3648 o = XWINDOW (window);
3649 fo = XFRAME (WINDOW_FRAME (o));
3650
3651 if (NILP (size))
3652 {
3653 if (!NILP (horflag))
3654 /* Calculate the size of the left-hand window, by dividing
3655 the usable space in columns by two.
3656 We round up, since the left-hand window may include
3657 a dividing line, while the right-hand may not. */
3658 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3659 else
3660 size_int = XFASTINT (o->total_lines) >> 1;
3661 }
3662 else
3663 {
3664 CHECK_NUMBER (size);
3665 size_int = XINT (size);
3666 }
3667
3668 if (MINI_WINDOW_P (o))
3669 error ("Attempt to split minibuffer window");
3670 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3671 error ("Attempt to split fixed-size window");
3672
3673 check_min_window_sizes ();
3674
3675 if (NILP (horflag))
3676 {
3677 if (size_int < window_min_height)
3678 error ("Window height %d too small (after splitting)", size_int);
3679 if (size_int + window_min_height > XFASTINT (o->total_lines))
3680 error ("Window height %d too small (after splitting)",
3681 XFASTINT (o->total_lines) - size_int);
3682 if (NILP (o->parent)
3683 || NILP (XWINDOW (o->parent)->vchild))
3684 {
3685 make_dummy_parent (window);
3686 new = o->parent;
3687 XWINDOW (new)->vchild = window;
3688 }
3689 }
3690 else
3691 {
3692 if (size_int < window_min_width)
3693 error ("Window width %d too small (after splitting)", size_int);
3694
3695 if (size_int + window_min_width > XFASTINT (o->total_cols))
3696 error ("Window width %d too small (after splitting)",
3697 XFASTINT (o->total_cols) - size_int);
3698 if (NILP (o->parent)
3699 || NILP (XWINDOW (o->parent)->hchild))
3700 {
3701 make_dummy_parent (window);
3702 new = o->parent;
3703 XWINDOW (new)->hchild = window;
3704 }
3705 }
3706
3707 /* Now we know that window's parent is a vertical combination
3708 if we are dividing vertically, or a horizontal combination
3709 if we are making side-by-side windows */
3710
3711 windows_or_buffers_changed++;
3712 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3713 new = make_window ();
3714 p = XWINDOW (new);
3715
3716 p->frame = o->frame;
3717 p->next = o->next;
3718 if (!NILP (p->next))
3719 XWINDOW (p->next)->prev = new;
3720 p->prev = window;
3721 o->next = new;
3722 p->parent = o->parent;
3723 p->buffer = Qt;
3724 p->window_end_valid = Qnil;
3725 bzero (&p->last_cursor, sizeof p->last_cursor);
3726
3727 /* Duplicate special geometry settings. */
3728
3729 p->left_margin_cols = o->left_margin_cols;
3730 p->right_margin_cols = o->right_margin_cols;
3731 p->left_fringe_width = o->left_fringe_width;
3732 p->right_fringe_width = o->right_fringe_width;
3733 p->fringes_outside_margins = o->fringes_outside_margins;
3734 p->scroll_bar_width = o->scroll_bar_width;
3735 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3736
3737 /* Apportion the available frame space among the two new windows */
3738
3739 if (!NILP (horflag))
3740 {
3741 p->total_lines = o->total_lines;
3742 p->top_line = o->top_line;
3743 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3744 XSETFASTINT (o->total_cols, size_int);
3745 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3746 adjust_window_margins (p);
3747 adjust_window_margins (o);
3748 }
3749 else
3750 {
3751 p->left_col = o->left_col;
3752 p->total_cols = o->total_cols;
3753 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3754 XSETFASTINT (o->total_lines, size_int);
3755 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3756 }
3757
3758 /* Adjust glyph matrices. */
3759 adjust_glyphs (fo);
3760
3761 Fset_window_buffer (new, o->buffer, Qt);
3762 return new;
3763 }
3764 \f
3765 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
3766 doc: /* Make current window ARG lines bigger.
3767 From program, optional second arg non-nil means grow sideways ARG columns.
3768 Interactively, if an argument is not given, make the window one line bigger.
3769
3770 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3771 of the siblings above or to the left of the selected window. Only
3772 siblings to the right or below are changed. */)
3773 (arg, side, preserve_before)
3774 register Lisp_Object arg, side, preserve_before;
3775 {
3776 CHECK_NUMBER (arg);
3777 enlarge_window (selected_window, XINT (arg), !NILP (side),
3778 !NILP (preserve_before));
3779
3780 if (! NILP (Vwindow_configuration_change_hook))
3781 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3782
3783 return Qnil;
3784 }
3785
3786 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
3787 doc: /* Make current window ARG lines smaller.
3788 From program, optional second arg non-nil means shrink sideways arg columns.
3789 Interactively, if an argument is not given, make the window one line smaller.
3790
3791 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3792 of the siblings above or to the left of the selected window. Only
3793 siblings to the right or below are changed. */)
3794 (arg, side, preserve_before)
3795 register Lisp_Object arg, side, preserve_before;
3796 {
3797 CHECK_NUMBER (arg);
3798 enlarge_window (selected_window, -XINT (arg), !NILP (side),
3799 !NILP (preserve_before));
3800
3801 if (! NILP (Vwindow_configuration_change_hook))
3802 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3803
3804 return Qnil;
3805 }
3806
3807 int
3808 window_height (window)
3809 Lisp_Object window;
3810 {
3811 register struct window *p = XWINDOW (window);
3812 return WINDOW_TOTAL_LINES (p);
3813 }
3814
3815 int
3816 window_width (window)
3817 Lisp_Object window;
3818 {
3819 register struct window *p = XWINDOW (window);
3820 return WINDOW_TOTAL_COLS (p);
3821 }
3822
3823
3824 #define CURBEG(w) \
3825 *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3826
3827 #define CURSIZE(w) \
3828 *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3829
3830
3831 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3832 increase its width. Siblings of the selected window are resized to
3833 fulfill the size request. If they become too small in the process,
3834 they will be deleted.
3835
3836 If PRESERVE_BEFORE is nonzero, that means don't alter
3837 the siblings to the left or above WINDOW. */
3838
3839 static void
3840 enlarge_window (window, delta, widthflag, preserve_before)
3841 Lisp_Object window;
3842 int delta, widthflag, preserve_before;
3843 {
3844 Lisp_Object parent, next, prev;
3845 struct window *p;
3846 Lisp_Object *sizep;
3847 int maximum;
3848 int (*sizefun) P_ ((Lisp_Object))
3849 = widthflag ? window_width : window_height;
3850 void (*setsizefun) P_ ((Lisp_Object, int, int))
3851 = (widthflag ? set_window_width : set_window_height);
3852
3853 /* Check values of window_min_width and window_min_height for
3854 validity. */
3855 check_min_window_sizes ();
3856
3857 /* Give up if this window cannot be resized. */
3858 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3859 error ("Window is not resizable");
3860
3861 /* Find the parent of the selected window. */
3862 while (1)
3863 {
3864 p = XWINDOW (window);
3865 parent = p->parent;
3866
3867 if (NILP (parent))
3868 {
3869 if (widthflag)
3870 error ("No other window to side of this one");
3871 break;
3872 }
3873
3874 if (widthflag
3875 ? !NILP (XWINDOW (parent)->hchild)
3876 : !NILP (XWINDOW (parent)->vchild))
3877 break;
3878
3879 window = parent;
3880 }
3881
3882 sizep = &CURSIZE (window);
3883
3884 {
3885 register int maxdelta;
3886
3887 /* Compute the maximum size increment this window can have. */
3888
3889 if (preserve_before)
3890 {
3891 if (!NILP (parent))
3892 {
3893 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3894 /* Subtract size of siblings before, since we can't take that. */
3895 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
3896 }
3897 else
3898 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3899 - window_min_size (XWINDOW (p->next),
3900 widthflag, 0, 0))
3901 : (delta = 0));
3902 }
3903 else
3904 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3905 /* This is a main window followed by a minibuffer. */
3906 : !NILP (p->next) ? ((*sizefun) (p->next)
3907 - window_min_size (XWINDOW (p->next),
3908 widthflag, 0, 0))
3909 /* This is a minibuffer following a main window. */
3910 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3911 - window_min_size (XWINDOW (p->prev),
3912 widthflag, 0, 0))
3913 /* This is a frame with only one window, a minibuffer-only
3914 or a minibufferless frame. */
3915 : (delta = 0));
3916
3917 if (delta > maxdelta)
3918 /* This case traps trying to make the minibuffer
3919 the full frame, or make the only window aside from the
3920 minibuffer the full frame. */
3921 delta = maxdelta;
3922 }
3923
3924 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3925 {
3926 delete_window (window);
3927 return;
3928 }
3929
3930 if (delta == 0)
3931 return;
3932
3933 /* Find the total we can get from other siblings without deleting them. */
3934 maximum = 0;
3935 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3936 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3937 widthflag, 0, 0);
3938 if (! preserve_before)
3939 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3940 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3941 widthflag, 0, 0);
3942
3943 /* If we can get it all from them without deleting them, do so. */
3944 if (delta <= maximum)
3945 {
3946 Lisp_Object first_unaffected;
3947 Lisp_Object first_affected;
3948 int fixed_p;
3949
3950 next = p->next;
3951 prev = p->prev;
3952 first_affected = window;
3953 /* Look at one sibling at a time,
3954 moving away from this window in both directions alternately,
3955 and take as much as we can get without deleting that sibling. */
3956 while (delta != 0
3957 && (!NILP (next) || (!preserve_before && !NILP (prev))))
3958 {
3959 if (! NILP (next))
3960 {
3961 int this_one = ((*sizefun) (next)
3962 - window_min_size (XWINDOW (next),
3963 widthflag, 0, &fixed_p));
3964 if (!fixed_p)
3965 {
3966 if (this_one > delta)
3967 this_one = delta;
3968
3969 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3970 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3971
3972 delta -= this_one;
3973 }
3974
3975 next = XWINDOW (next)->next;
3976 }
3977
3978 if (delta == 0)
3979 break;
3980
3981 if (!preserve_before && ! NILP (prev))
3982 {
3983 int this_one = ((*sizefun) (prev)
3984 - window_min_size (XWINDOW (prev),
3985 widthflag, 0, &fixed_p));
3986 if (!fixed_p)
3987 {
3988 if (this_one > delta)
3989 this_one = delta;
3990
3991 first_affected = prev;
3992
3993 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3994 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3995
3996 delta -= this_one;
3997 }
3998
3999 prev = XWINDOW (prev)->prev;
4000 }
4001 }
4002
4003 xassert (delta == 0);
4004
4005 /* Now recalculate the edge positions of all the windows affected,
4006 based on the new sizes. */
4007 first_unaffected = next;
4008 prev = first_affected;
4009 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4010 prev = next, next = XWINDOW (next)->next)
4011 {
4012 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4013 /* This does not change size of NEXT,
4014 but it propagates the new top edge to its children */
4015 (*setsizefun) (next, (*sizefun) (next), 0);
4016 }
4017 }
4018 else
4019 {
4020 register int delta1;
4021 register int opht = (*sizefun) (parent);
4022
4023 if (opht <= XINT (*sizep) + delta)
4024 {
4025 /* If trying to grow this window to or beyond size of the parent,
4026 just delete all the sibling windows. */
4027 Lisp_Object start, tem, next;
4028
4029 start = XWINDOW (parent)->vchild;
4030 if (NILP (start))
4031 start = XWINDOW (parent)->hchild;
4032
4033 /* Delete any siblings that come after WINDOW. */
4034 tem = XWINDOW (window)->next;
4035 while (! NILP (tem))
4036 {
4037 next = XWINDOW (tem)->next;
4038 delete_window (tem);
4039 tem = next;
4040 }
4041
4042 /* Delete any siblings that come after WINDOW.
4043 Note that if START is not WINDOW, then WINDOW still
4044 Fhas siblings, so WINDOW has not yet replaced its parent. */
4045 tem = start;
4046 while (! EQ (tem, window))
4047 {
4048 next = XWINDOW (tem)->next;
4049 delete_window (tem);
4050 tem = next;
4051 }
4052 }
4053 else
4054 {
4055 /* Otherwise, make delta1 just right so that if we add
4056 delta1 lines to this window and to the parent, and then
4057 shrink the parent back to its original size, the new
4058 proportional size of this window will increase by delta.
4059
4060 The function size_window will compute the new height h'
4061 of the window from delta1 as:
4062
4063 e = delta1/n
4064 x = delta1 - delta1/n * n for the 1st resizable child
4065 h' = h + e + x
4066
4067 where n is the number of children that can be resized.
4068 We can ignore x by choosing a delta1 that is a multiple of
4069 n. We want the height of this window to come out as
4070
4071 h' = h + delta
4072
4073 So, delta1 must be
4074
4075 h + e = h + delta
4076 delta1/n = delta
4077 delta1 = n * delta.
4078
4079 The number of children n equals the number of resizable
4080 children of this window + 1 because we know window itself
4081 is resizable (otherwise we would have signalled an error. */
4082
4083 struct window *w = XWINDOW (window);
4084 Lisp_Object s;
4085 int n = 1;
4086
4087 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
4088 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
4089 ++n;
4090 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
4091 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
4092 ++n;
4093
4094 delta1 = n * delta;
4095
4096 /* Add delta1 lines or columns to this window, and to the parent,
4097 keeping things consistent while not affecting siblings. */
4098 XSETINT (CURSIZE (parent), opht + delta1);
4099 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4100
4101 /* Squeeze out delta1 lines or columns from our parent,
4102 shriking this window and siblings proportionately.
4103 This brings parent back to correct size.
4104 Delta1 was calculated so this makes this window the desired size,
4105 taking it all out of the siblings. */
4106 (*setsizefun) (parent, opht, 0);
4107
4108 }
4109 }
4110
4111 XSETFASTINT (p->last_modified, 0);
4112 XSETFASTINT (p->last_overlay_modified, 0);
4113
4114 /* Adjust glyph matrices. */
4115 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4116 }
4117
4118 #undef CURBEG
4119 #undef CURSIZE
4120
4121
4122 \f
4123 /***********************************************************************
4124 Resizing Mini-Windows
4125 ***********************************************************************/
4126
4127 static void shrink_window_lowest_first P_ ((struct window *, int));
4128
4129 enum save_restore_action
4130 {
4131 CHECK_ORIG_SIZES,
4132 SAVE_ORIG_SIZES,
4133 RESTORE_ORIG_SIZES
4134 };
4135
4136 static int save_restore_orig_size P_ ((struct window *,
4137 enum save_restore_action));
4138
4139 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4140 from lowest windows first. */
4141
4142 static void
4143 shrink_window_lowest_first (w, height)
4144 struct window *w;
4145 int height;
4146 {
4147 struct window *c;
4148 Lisp_Object child;
4149 int old_height;
4150
4151 xassert (!MINI_WINDOW_P (w));
4152
4153 /* Set redisplay hints. */
4154 XSETFASTINT (w->last_modified, 0);
4155 XSETFASTINT (w->last_overlay_modified, 0);
4156 windows_or_buffers_changed++;
4157 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4158
4159 old_height = XFASTINT (w->total_lines);
4160 XSETFASTINT (w->total_lines, height);
4161
4162 if (!NILP (w->hchild))
4163 {
4164 for (child = w->hchild; !NILP (child); child = c->next)
4165 {
4166 c = XWINDOW (child);
4167 c->top_line = w->top_line;
4168 shrink_window_lowest_first (c, height);
4169 }
4170 }
4171 else if (!NILP (w->vchild))
4172 {
4173 Lisp_Object last_child;
4174 int delta = old_height - height;
4175 int last_top;
4176
4177 last_child = Qnil;
4178
4179 /* Find the last child. We are taking space from lowest windows
4180 first, so we iterate over children from the last child
4181 backwards. */
4182 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4183 last_child = child;
4184
4185 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4186 for (child = last_child; delta && !NILP (child); child = c->prev)
4187 {
4188 int this_one;
4189
4190 c = XWINDOW (child);
4191 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4192
4193 if (this_one > delta)
4194 this_one = delta;
4195
4196 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4197 delta -= this_one;
4198 }
4199
4200 /* Compute new positions. */
4201 last_top = XINT (w->top_line);
4202 for (child = w->vchild; !NILP (child); child = c->next)
4203 {
4204 c = XWINDOW (child);
4205 c->top_line = make_number (last_top);
4206 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4207 last_top += XFASTINT (c->total_lines);
4208 }
4209 }
4210 }
4211
4212
4213 /* Save, restore, or check positions and sizes in the window tree
4214 rooted at W. ACTION says what to do.
4215
4216 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4217 orig_total_lines members are valid for all windows in the window
4218 tree. Value is non-zero if they are valid.
4219
4220 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4221 orig_top_line and orig_total_lines for all windows in the tree.
4222
4223 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4224 stored in orig_top_line and orig_total_lines for all windows. */
4225
4226 static int
4227 save_restore_orig_size (w, action)
4228 struct window *w;
4229 enum save_restore_action action;
4230 {
4231 int success_p = 1;
4232
4233 while (w)
4234 {
4235 if (!NILP (w->hchild))
4236 {
4237 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4238 success_p = 0;
4239 }
4240 else if (!NILP (w->vchild))
4241 {
4242 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4243 success_p = 0;
4244 }
4245
4246 switch (action)
4247 {
4248 case CHECK_ORIG_SIZES:
4249 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4250 return 0;
4251 break;
4252
4253 case SAVE_ORIG_SIZES:
4254 w->orig_top_line = w->top_line;
4255 w->orig_total_lines = w->total_lines;
4256 XSETFASTINT (w->last_modified, 0);
4257 XSETFASTINT (w->last_overlay_modified, 0);
4258 break;
4259
4260 case RESTORE_ORIG_SIZES:
4261 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4262 w->top_line = w->orig_top_line;
4263 w->total_lines = w->orig_total_lines;
4264 w->orig_total_lines = w->orig_top_line = Qnil;
4265 XSETFASTINT (w->last_modified, 0);
4266 XSETFASTINT (w->last_overlay_modified, 0);
4267 break;
4268
4269 default:
4270 abort ();
4271 }
4272
4273 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4274 }
4275
4276 return success_p;
4277 }
4278
4279
4280 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4281 without deleting other windows. */
4282
4283 void
4284 grow_mini_window (w, delta)
4285 struct window *w;
4286 int delta;
4287 {
4288 struct frame *f = XFRAME (w->frame);
4289 struct window *root;
4290
4291 xassert (MINI_WINDOW_P (w));
4292 xassert (delta >= 0);
4293
4294 /* Check values of window_min_width and window_min_height for
4295 validity. */
4296 check_min_window_sizes ();
4297
4298 /* Compute how much we can enlarge the mini-window without deleting
4299 other windows. */
4300 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4301 if (delta)
4302 {
4303 int min_height = window_min_size (root, 0, 0, 0);
4304 if (XFASTINT (root->total_lines) - delta < min_height)
4305 /* Note that the root window may already be smaller than
4306 min_height. */
4307 delta = max (0, XFASTINT (root->total_lines) - min_height);
4308 }
4309
4310 if (delta)
4311 {
4312 /* Save original window sizes and positions, if not already done. */
4313 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4314 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4315
4316 /* Shrink other windows. */
4317 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4318
4319 /* Grow the mini-window. */
4320 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4321 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4322 XSETFASTINT (w->last_modified, 0);
4323 XSETFASTINT (w->last_overlay_modified, 0);
4324
4325 adjust_glyphs (f);
4326 }
4327 }
4328
4329
4330 /* Shrink mini-window W. If there is recorded info about window sizes
4331 before a call to grow_mini_window, restore recorded window sizes.
4332 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4333 line. */
4334
4335 void
4336 shrink_mini_window (w)
4337 struct window *w;
4338 {
4339 struct frame *f = XFRAME (w->frame);
4340 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4341
4342 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4343 {
4344 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4345 adjust_glyphs (f);
4346 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4347 windows_or_buffers_changed = 1;
4348 }
4349 else if (XFASTINT (w->total_lines) > 1)
4350 {
4351 /* Distribute the additional lines of the mini-window
4352 among the other windows. */
4353 Lisp_Object window;
4354 XSETWINDOW (window, w);
4355 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0);
4356 }
4357 }
4358
4359
4360 \f
4361 /* Mark window cursors off for all windows in the window tree rooted
4362 at W by setting their phys_cursor_on_p flag to zero. Called from
4363 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4364 the frame are cleared. */
4365
4366 void
4367 mark_window_cursors_off (w)
4368 struct window *w;
4369 {
4370 while (w)
4371 {
4372 if (!NILP (w->hchild))
4373 mark_window_cursors_off (XWINDOW (w->hchild));
4374 else if (!NILP (w->vchild))
4375 mark_window_cursors_off (XWINDOW (w->vchild));
4376 else
4377 w->phys_cursor_on_p = 0;
4378
4379 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4380 }
4381 }
4382
4383
4384 /* Return number of lines of text (not counting mode lines) in W. */
4385
4386 int
4387 window_internal_height (w)
4388 struct window *w;
4389 {
4390 int ht = XFASTINT (w->total_lines);
4391
4392 if (!MINI_WINDOW_P (w))
4393 {
4394 if (!NILP (w->parent)
4395 || !NILP (w->vchild)
4396 || !NILP (w->hchild)
4397 || !NILP (w->next)
4398 || !NILP (w->prev)
4399 || WINDOW_WANTS_MODELINE_P (w))
4400 --ht;
4401
4402 if (WINDOW_WANTS_HEADER_LINE_P (w))
4403 --ht;
4404 }
4405
4406 return ht;
4407 }
4408
4409
4410 /* Return the number of columns in W.
4411 Don't count columns occupied by scroll bars or the vertical bar
4412 separating W from the sibling to its right. */
4413
4414 int
4415 window_box_text_cols (w)
4416 struct window *w;
4417 {
4418 struct frame *f = XFRAME (WINDOW_FRAME (w));
4419 int width = XINT (w->total_cols);
4420
4421 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4422 /* Scroll bars occupy a few columns. */
4423 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4424 else if (!FRAME_WINDOW_P (f)
4425 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4426 /* The column of `|' characters separating side-by-side windows
4427 occupies one column only. */
4428 width -= 1;
4429
4430 if (FRAME_WINDOW_P (f))
4431 /* On window-systems, fringes and display margins cannot be
4432 used for normal text. */
4433 width -= (WINDOW_FRINGE_COLS (w)
4434 + WINDOW_LEFT_MARGIN_COLS (w)
4435 + WINDOW_RIGHT_MARGIN_COLS (w));
4436
4437 return width;
4438 }
4439
4440 \f
4441 /************************************************************************
4442 Window Scrolling
4443 ***********************************************************************/
4444
4445 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4446 N screen-fulls, which is defined as the height of the window minus
4447 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4448 instead. Negative values of N mean scroll down. NOERROR non-zero
4449 means don't signal an error if we try to move over BEGV or ZV,
4450 respectively. */
4451
4452 static void
4453 window_scroll (window, n, whole, noerror)
4454 Lisp_Object window;
4455 int n;
4456 int whole;
4457 int noerror;
4458 {
4459 immediate_quit = 1;
4460
4461 /* If we must, use the pixel-based version which is much slower than
4462 the line-based one but can handle varying line heights. */
4463 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4464 window_scroll_pixel_based (window, n, whole, noerror);
4465 else
4466 window_scroll_line_based (window, n, whole, noerror);
4467
4468 immediate_quit = 0;
4469 }
4470
4471
4472 /* Implementation of window_scroll that works based on pixel line
4473 heights. See the comment of window_scroll for parameter
4474 descriptions. */
4475
4476 static void
4477 window_scroll_pixel_based (window, n, whole, noerror)
4478 Lisp_Object window;
4479 int n;
4480 int whole;
4481 int noerror;
4482 {
4483 struct it it;
4484 struct window *w = XWINDOW (window);
4485 struct text_pos start;
4486 Lisp_Object tem;
4487 int this_scroll_margin;
4488 int preserve_y;
4489 /* True if we fiddled the window vscroll field without really scrolling. */
4490 int vscrolled = 0;
4491
4492 SET_TEXT_POS_FROM_MARKER (start, w->start);
4493
4494 /* If PT is not visible in WINDOW, move back one half of
4495 the screen. Allow PT to be partially visible, otherwise
4496 something like (scroll-down 1) with PT in the line before
4497 the partially visible one would recenter. */
4498 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4499 if (NILP (tem))
4500 {
4501 /* Move backward half the height of the window. Performance note:
4502 vmotion used here is about 10% faster, but would give wrong
4503 results for variable height lines. */
4504 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4505 it.current_y = it.last_visible_y;
4506 move_it_vertically (&it, - window_box_height (w) / 2);
4507
4508 /* The function move_iterator_vertically may move over more than
4509 the specified y-distance. If it->w is small, e.g. a
4510 mini-buffer window, we may end up in front of the window's
4511 display area. This is the case when Start displaying at the
4512 start of the line containing PT in this case. */
4513 if (it.current_y <= 0)
4514 {
4515 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4516 move_it_vertically (&it, 0);
4517 it.current_y = 0;
4518 }
4519
4520 start = it.current.pos;
4521 }
4522
4523 /* If scroll_preserve_screen_position is non-zero, we try to set
4524 point in the same window line as it is now, so get that line. */
4525 if (!NILP (Vscroll_preserve_screen_position))
4526 {
4527 start_display (&it, w, start);
4528 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4529 preserve_y = it.current_y;
4530 }
4531 else
4532 preserve_y = -1;
4533
4534 /* Move iterator it from start the specified distance forward or
4535 backward. The result is the new window start. */
4536 start_display (&it, w, start);
4537 if (whole)
4538 {
4539 int screen_full = (window_box_height (w)
4540 - next_screen_context_lines * FRAME_LINE_HEIGHT (it.f));
4541 int dy = n * screen_full;
4542
4543 /* Note that move_it_vertically always moves the iterator to the
4544 start of a line. So, if the last line doesn't have a newline,
4545 we would end up at the start of the line ending at ZV. */
4546 if (dy <= 0)
4547 move_it_vertically_backward (&it, -dy);
4548 else if (dy > 0)
4549 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4550 MOVE_TO_POS | MOVE_TO_Y);
4551 }
4552 else
4553 move_it_by_lines (&it, n, 1);
4554
4555 /* We failed if we find ZV is already on the screen (scrolling up,
4556 means there's nothing past the end), or if we can't start any
4557 earlier (scrolling down, means there's nothing past the top). */
4558 if ((n > 0 && IT_CHARPOS (it) == ZV)
4559 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4560 {
4561 if (IT_CHARPOS (it) == ZV)
4562 {
4563 if (it.current_y < it.last_visible_y
4564 && (it.current_y + it.max_ascent + it.max_descent
4565 >= it.last_visible_y))
4566 {
4567 /* The last line was only partially visible, make it fully
4568 visible. */
4569 w->vscroll = (it.last_visible_y
4570 - it.current_y + it.max_ascent + it.max_descent);
4571 adjust_glyphs (it.f);
4572 }
4573 else if (noerror)
4574 return;
4575 else
4576 Fsignal (Qend_of_buffer, Qnil);
4577 }
4578 else
4579 {
4580 if (w->vscroll != 0)
4581 /* The first line was only partially visible, make it fully
4582 visible. */
4583 w->vscroll = 0;
4584 else if (noerror)
4585 return;
4586 else
4587 Fsignal (Qbeginning_of_buffer, Qnil);
4588 }
4589
4590 /* If control gets here, then we vscrolled. */
4591
4592 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4593
4594 /* Don't try to change the window start below. */
4595 vscrolled = 1;
4596 }
4597
4598 if (! vscrolled)
4599 {
4600 int pos = IT_CHARPOS (it);
4601 int bytepos;
4602
4603 /* If in the middle of a multi-glyph character move forward to
4604 the next character. */
4605 if (in_display_vector_p (&it))
4606 {
4607 ++pos;
4608 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4609 }
4610
4611 /* Set the window start, and set up the window for redisplay. */
4612 set_marker_restricted (w->start, make_number (pos),
4613 w->buffer);
4614 bytepos = XMARKER (w->start)->bytepos;
4615 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4616 ? Qt : Qnil);
4617 w->update_mode_line = Qt;
4618 XSETFASTINT (w->last_modified, 0);
4619 XSETFASTINT (w->last_overlay_modified, 0);
4620 /* Set force_start so that redisplay_window will run the
4621 window-scroll-functions. */
4622 w->force_start = Qt;
4623 }
4624
4625 it.current_y = it.vpos = 0;
4626
4627 /* Preserve the screen position if we must. */
4628 if (preserve_y >= 0)
4629 {
4630 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4631 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4632 }
4633 else
4634 {
4635 /* Move PT out of scroll margins. */
4636 this_scroll_margin = max (0, scroll_margin);
4637 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4638 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4639
4640 if (n > 0)
4641 {
4642 /* We moved the window start towards ZV, so PT may be now
4643 in the scroll margin at the top. */
4644 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4645 while (it.current_y < this_scroll_margin)
4646 {
4647 int prev = it.current_y;
4648 move_it_by_lines (&it, 1, 1);
4649 if (prev == it.current_y)
4650 break;
4651 }
4652 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4653 }
4654 else if (n < 0)
4655 {
4656 int charpos, bytepos;
4657
4658 /* We moved the window start towards BEGV, so PT may be now
4659 in the scroll margin at the bottom. */
4660 move_it_to (&it, PT, -1,
4661 it.last_visible_y - this_scroll_margin - 1, -1,
4662 MOVE_TO_POS | MOVE_TO_Y);
4663
4664 /* Save our position, in case it's correct. */
4665 charpos = IT_CHARPOS (it);
4666 bytepos = IT_BYTEPOS (it);
4667
4668 /* See if point is on a partially visible line at the end. */
4669 move_it_by_lines (&it, 1, 1);
4670 if (it.current_y > it.last_visible_y)
4671 /* The last line was only partially visible, so back up two
4672 lines to make sure we're on a fully visible line. */
4673 {
4674 move_it_by_lines (&it, -2, 0);
4675 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4676 }
4677 else
4678 /* No, the position we saved is OK, so use it. */
4679 SET_PT_BOTH (charpos, bytepos);
4680 }
4681 }
4682 }
4683
4684
4685 /* Implementation of window_scroll that works based on screen lines.
4686 See the comment of window_scroll for parameter descriptions. */
4687
4688 static void
4689 window_scroll_line_based (window, n, whole, noerror)
4690 Lisp_Object window;
4691 int n;
4692 int whole;
4693 int noerror;
4694 {
4695 register struct window *w = XWINDOW (window);
4696 register int opoint = PT, opoint_byte = PT_BYTE;
4697 register int pos, pos_byte;
4698 register int ht = window_internal_height (w);
4699 register Lisp_Object tem;
4700 int lose;
4701 Lisp_Object bolp;
4702 int startpos;
4703 struct position posit;
4704 int original_vpos;
4705
4706 /* If scrolling screen-fulls, compute the number of lines to
4707 scroll from the window's height. */
4708 if (whole)
4709 n *= max (1, ht - next_screen_context_lines);
4710
4711 startpos = marker_position (w->start);
4712
4713 posit = *compute_motion (startpos, 0, 0, 0,
4714 PT, ht, 0,
4715 -1, XINT (w->hscroll),
4716 0, w);
4717 original_vpos = posit.vpos;
4718
4719 XSETFASTINT (tem, PT);
4720 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4721
4722 if (NILP (tem))
4723 {
4724 Fvertical_motion (make_number (- (ht / 2)), window);
4725 startpos = PT;
4726 }
4727
4728 SET_PT (startpos);
4729 lose = n < 0 && PT == BEGV;
4730 Fvertical_motion (make_number (n), window);
4731 pos = PT;
4732 pos_byte = PT_BYTE;
4733 bolp = Fbolp ();
4734 SET_PT_BOTH (opoint, opoint_byte);
4735
4736 if (lose)
4737 {
4738 if (noerror)
4739 return;
4740 else
4741 Fsignal (Qbeginning_of_buffer, Qnil);
4742 }
4743
4744 if (pos < ZV)
4745 {
4746 int this_scroll_margin = scroll_margin;
4747
4748 /* Don't use a scroll margin that is negative or too large. */
4749 if (this_scroll_margin < 0)
4750 this_scroll_margin = 0;
4751
4752 if (XINT (w->total_lines) < 4 * scroll_margin)
4753 this_scroll_margin = XINT (w->total_lines) / 4;
4754
4755 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4756 w->start_at_line_beg = bolp;
4757 w->update_mode_line = Qt;
4758 XSETFASTINT (w->last_modified, 0);
4759 XSETFASTINT (w->last_overlay_modified, 0);
4760 /* Set force_start so that redisplay_window will run
4761 the window-scroll-functions. */
4762 w->force_start = Qt;
4763
4764 if (whole && !NILP (Vscroll_preserve_screen_position))
4765 {
4766 SET_PT_BOTH (pos, pos_byte);
4767 Fvertical_motion (make_number (original_vpos), window);
4768 }
4769 /* If we scrolled forward, put point enough lines down
4770 that it is outside the scroll margin. */
4771 else if (n > 0)
4772 {
4773 int top_margin;
4774
4775 if (this_scroll_margin > 0)
4776 {
4777 SET_PT_BOTH (pos, pos_byte);
4778 Fvertical_motion (make_number (this_scroll_margin), window);
4779 top_margin = PT;
4780 }
4781 else
4782 top_margin = pos;
4783
4784 if (top_margin <= opoint)
4785 SET_PT_BOTH (opoint, opoint_byte);
4786 else if (!NILP (Vscroll_preserve_screen_position))
4787 {
4788 SET_PT_BOTH (pos, pos_byte);
4789 Fvertical_motion (make_number (original_vpos), window);
4790 }
4791 else
4792 SET_PT (top_margin);
4793 }
4794 else if (n < 0)
4795 {
4796 int bottom_margin;
4797
4798 /* If we scrolled backward, put point near the end of the window
4799 but not within the scroll margin. */
4800 SET_PT_BOTH (pos, pos_byte);
4801 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4802 if (XFASTINT (tem) == ht - this_scroll_margin)
4803 bottom_margin = PT;
4804 else
4805 bottom_margin = PT + 1;
4806
4807 if (bottom_margin > opoint)
4808 SET_PT_BOTH (opoint, opoint_byte);
4809 else
4810 {
4811 if (!NILP (Vscroll_preserve_screen_position))
4812 {
4813 SET_PT_BOTH (pos, pos_byte);
4814 Fvertical_motion (make_number (original_vpos), window);
4815 }
4816 else
4817 Fvertical_motion (make_number (-1), window);
4818 }
4819 }
4820 }
4821 else
4822 {
4823 if (noerror)
4824 return;
4825 else
4826 Fsignal (Qend_of_buffer, Qnil);
4827 }
4828 }
4829
4830
4831 /* Scroll selected_window up or down. If N is nil, scroll a
4832 screen-full which is defined as the height of the window minus
4833 next_screen_context_lines. If N is the symbol `-', scroll.
4834 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4835 up. This is the guts of Fscroll_up and Fscroll_down. */
4836
4837 static void
4838 scroll_command (n, direction)
4839 Lisp_Object n;
4840 int direction;
4841 {
4842 int count = SPECPDL_INDEX ();
4843
4844 xassert (abs (direction) == 1);
4845
4846 /* If selected window's buffer isn't current, make it current for
4847 the moment. But don't screw up if window_scroll gets an error. */
4848 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4849 {
4850 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4851 Fset_buffer (XWINDOW (selected_window)->buffer);
4852
4853 /* Make redisplay consider other windows than just selected_window. */
4854 ++windows_or_buffers_changed;
4855 }
4856
4857 if (NILP (n))
4858 window_scroll (selected_window, direction, 1, 0);
4859 else if (EQ (n, Qminus))
4860 window_scroll (selected_window, -direction, 1, 0);
4861 else
4862 {
4863 n = Fprefix_numeric_value (n);
4864 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4865 }
4866
4867 unbind_to (count, Qnil);
4868 }
4869
4870 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4871 doc: /* Scroll text of current window upward ARG lines.
4872 If ARG is omitted or nil, scroll upward by a near full screen.
4873 A near full screen is `next-screen-context-lines' less than a full screen.
4874 Negative ARG means scroll downward.
4875 If ARG is the atom `-', scroll downward by nearly full screen.
4876 When calling from a program, supply as argument a number, nil, or `-'. */)
4877 (arg)
4878 Lisp_Object arg;
4879 {
4880 scroll_command (arg, 1);
4881 return Qnil;
4882 }
4883
4884 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4885 doc: /* Scroll text of current window down ARG lines.
4886 If ARG is omitted or nil, scroll down by a near full screen.
4887 A near full screen is `next-screen-context-lines' less than a full screen.
4888 Negative ARG means scroll upward.
4889 If ARG is the atom `-', scroll upward by nearly full screen.
4890 When calling from a program, supply as argument a number, nil, or `-'. */)
4891 (arg)
4892 Lisp_Object arg;
4893 {
4894 scroll_command (arg, -1);
4895 return Qnil;
4896 }
4897 \f
4898 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4899 doc: /* Return the other window for \"other window scroll\" commands.
4900 If `other-window-scroll-buffer' is non-nil, a window
4901 showing that buffer is used.
4902 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4903 specifies the window. This takes precedence over
4904 `other-window-scroll-buffer'. */)
4905 ()
4906 {
4907 Lisp_Object window;
4908
4909 if (MINI_WINDOW_P (XWINDOW (selected_window))
4910 && !NILP (Vminibuf_scroll_window))
4911 window = Vminibuf_scroll_window;
4912 /* If buffer is specified, scroll that buffer. */
4913 else if (!NILP (Vother_window_scroll_buffer))
4914 {
4915 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4916 if (NILP (window))
4917 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4918 }
4919 else
4920 {
4921 /* Nothing specified; look for a neighboring window on the same
4922 frame. */
4923 window = Fnext_window (selected_window, Qnil, Qnil);
4924
4925 if (EQ (window, selected_window))
4926 /* That didn't get us anywhere; look for a window on another
4927 visible frame. */
4928 do
4929 window = Fnext_window (window, Qnil, Qt);
4930 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4931 && ! EQ (window, selected_window));
4932 }
4933
4934 CHECK_LIVE_WINDOW (window);
4935
4936 if (EQ (window, selected_window))
4937 error ("There is no other window");
4938
4939 return window;
4940 }
4941
4942 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4943 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4944 A near full screen is `next-screen-context-lines' less than a full screen.
4945 The next window is the one below the current one; or the one at the top
4946 if the current one is at the bottom. Negative ARG means scroll downward.
4947 If ARG is the atom `-', scroll downward by nearly full screen.
4948 When calling from a program, supply as argument a number, nil, or `-'.
4949
4950 If `other-window-scroll-buffer' is non-nil, scroll the window
4951 showing that buffer, popping the buffer up if necessary.
4952 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4953 specifies the window to scroll. This takes precedence over
4954 `other-window-scroll-buffer'. */)
4955 (arg)
4956 Lisp_Object arg;
4957 {
4958 Lisp_Object window;
4959 struct window *w;
4960 int count = SPECPDL_INDEX ();
4961
4962 window = Fother_window_for_scrolling ();
4963 w = XWINDOW (window);
4964
4965 /* Don't screw up if window_scroll gets an error. */
4966 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4967 ++windows_or_buffers_changed;
4968
4969 Fset_buffer (w->buffer);
4970 SET_PT (marker_position (w->pointm));
4971
4972 if (NILP (arg))
4973 window_scroll (window, 1, 1, 1);
4974 else if (EQ (arg, Qminus))
4975 window_scroll (window, -1, 1, 1);
4976 else
4977 {
4978 if (CONSP (arg))
4979 arg = Fcar (arg);
4980 CHECK_NUMBER (arg);
4981 window_scroll (window, XINT (arg), 0, 1);
4982 }
4983
4984 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4985 unbind_to (count, Qnil);
4986
4987 return Qnil;
4988 }
4989 \f
4990 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4991 doc: /* Scroll selected window display ARG columns left.
4992 Default for ARG is window width minus 2.
4993 Value is the total amount of leftward horizontal scrolling in
4994 effect after the change.
4995 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4996 a lower bound for automatic scrolling, i.e. automatic scrolling
4997 will not scroll a window to a column less than the value returned
4998 by this function. */)
4999 (arg)
5000 register Lisp_Object arg;
5001 {
5002 Lisp_Object result;
5003 int hscroll;
5004 struct window *w = XWINDOW (selected_window);
5005
5006 if (NILP (arg))
5007 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5008 else
5009 arg = Fprefix_numeric_value (arg);
5010
5011 hscroll = XINT (w->hscroll) + XINT (arg);
5012 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5013
5014 if (interactive_p (0))
5015 w->min_hscroll = w->hscroll;
5016
5017 return result;
5018 }
5019
5020 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
5021 doc: /* Scroll selected window display ARG columns right.
5022 Default for ARG is window width minus 2.
5023 Value is the total amount of leftward horizontal scrolling in
5024 effect after the change.
5025 If `automatic-hscrolling' is non-nil, the argument ARG modifies
5026 a lower bound for automatic scrolling, i.e. automatic scrolling
5027 will not scroll a window to a column less than the value returned
5028 by this function. */)
5029 (arg)
5030 register Lisp_Object arg;
5031 {
5032 Lisp_Object result;
5033 int hscroll;
5034 struct window *w = XWINDOW (selected_window);
5035
5036 if (NILP (arg))
5037 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5038 else
5039 arg = Fprefix_numeric_value (arg);
5040
5041 hscroll = XINT (w->hscroll) - XINT (arg);
5042 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5043
5044 if (interactive_p (0))
5045 w->min_hscroll = w->hscroll;
5046
5047 return result;
5048 }
5049
5050 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5051 doc: /* Return the window which was selected when entering the minibuffer.
5052 Returns nil, if current window is not a minibuffer window. */)
5053 ()
5054 {
5055 if (minibuf_level > 0
5056 && MINI_WINDOW_P (XWINDOW (selected_window))
5057 && WINDOW_LIVE_P (minibuf_selected_window))
5058 return minibuf_selected_window;
5059
5060 return Qnil;
5061 }
5062
5063 /* Value is the number of lines actually displayed in window W,
5064 as opposed to its height. */
5065
5066 static int
5067 displayed_window_lines (w)
5068 struct window *w;
5069 {
5070 struct it it;
5071 struct text_pos start;
5072 int height = window_box_height (w);
5073 struct buffer *old_buffer;
5074 int bottom_y;
5075
5076 if (XBUFFER (w->buffer) != current_buffer)
5077 {
5078 old_buffer = current_buffer;
5079 set_buffer_internal (XBUFFER (w->buffer));
5080 }
5081 else
5082 old_buffer = NULL;
5083
5084 /* In case W->start is out of the accessible range, do something
5085 reasonable. This happens in Info mode when Info-scroll-down
5086 calls (recenter -1) while W->start is 1. */
5087 if (XMARKER (w->start)->charpos < BEGV)
5088 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5089 else if (XMARKER (w->start)->charpos > ZV)
5090 SET_TEXT_POS (start, ZV, ZV_BYTE);
5091 else
5092 SET_TEXT_POS_FROM_MARKER (start, w->start);
5093
5094 start_display (&it, w, start);
5095 move_it_vertically (&it, height);
5096 bottom_y = line_bottom_y (&it);
5097
5098 /* rms: On a non-window display,
5099 the value of it.vpos at the bottom of the screen
5100 seems to be 1 larger than window_box_height (w).
5101 This kludge fixes a bug whereby (move-to-window-line -1)
5102 when ZV is on the last screen line
5103 moves to the previous screen line instead of the last one. */
5104 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5105 height++;
5106
5107 /* Add in empty lines at the bottom of the window. */
5108 if (bottom_y < height)
5109 {
5110 int uy = FRAME_LINE_HEIGHT (it.f);
5111 it.vpos += (height - bottom_y + uy - 1) / uy;
5112 }
5113
5114 if (old_buffer)
5115 set_buffer_internal (old_buffer);
5116
5117 return it.vpos;
5118 }
5119
5120
5121 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5122 doc: /* Center point in window and redisplay frame.
5123 With prefix argument ARG, recenter putting point on screen line ARG
5124 relative to the current window. If ARG is negative, it counts up from the
5125 bottom of the window. (ARG should be less than the height of the window.)
5126
5127 If ARG is omitted or nil, erase the entire frame and then
5128 redraw with point in the center of the current window.
5129 Just C-u as prefix means put point in the center of the window
5130 and redisplay normally--don't erase and redraw the frame. */)
5131 (arg)
5132 register Lisp_Object arg;
5133 {
5134 struct window *w = XWINDOW (selected_window);
5135 struct buffer *buf = XBUFFER (w->buffer);
5136 struct buffer *obuf = current_buffer;
5137 int center_p = 0;
5138 int charpos, bytepos;
5139
5140 /* If redisplay is suppressed due to an error, try again. */
5141 obuf->display_error_modiff = 0;
5142
5143 if (NILP (arg))
5144 {
5145 int i;
5146
5147 /* Invalidate pixel data calculated for all compositions. */
5148 for (i = 0; i < n_compositions; i++)
5149 composition_table[i]->font = NULL;
5150
5151 Fredraw_frame (w->frame);
5152 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
5153 center_p = 1;
5154 }
5155 else if (CONSP (arg)) /* Just C-u. */
5156 center_p = 1;
5157 else
5158 {
5159 arg = Fprefix_numeric_value (arg);
5160 CHECK_NUMBER (arg);
5161 }
5162
5163 set_buffer_internal (buf);
5164
5165 /* Handle centering on a graphical frame specially. Such frames can
5166 have variable-height lines and centering point on the basis of
5167 line counts would lead to strange effects. */
5168 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5169 {
5170 if (center_p)
5171 {
5172 struct it it;
5173 struct text_pos pt;
5174
5175 SET_TEXT_POS (pt, PT, PT_BYTE);
5176 start_display (&it, w, pt);
5177 move_it_vertically (&it, - window_box_height (w) / 2);
5178 charpos = IT_CHARPOS (it);
5179 bytepos = IT_BYTEPOS (it);
5180 }
5181 else if (XINT (arg) < 0)
5182 {
5183 struct it it;
5184 struct text_pos pt;
5185 int y0, y1, h, nlines;
5186
5187 SET_TEXT_POS (pt, PT, PT_BYTE);
5188 start_display (&it, w, pt);
5189 y0 = it.current_y;
5190
5191 /* The amount of pixels we have to move back is the window
5192 height minus what's displayed in the line containing PT,
5193 and the lines below. */
5194 nlines = - XINT (arg) - 1;
5195 move_it_by_lines (&it, nlines, 1);
5196
5197 y1 = line_bottom_y (&it);
5198
5199 /* If we can't move down NLINES lines because we hit
5200 the end of the buffer, count in some empty lines. */
5201 if (it.vpos < nlines)
5202 y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
5203
5204 h = window_box_height (w) - (y1 - y0);
5205
5206 start_display (&it, w, pt);
5207 move_it_vertically (&it, - h);
5208 charpos = IT_CHARPOS (it);
5209 bytepos = IT_BYTEPOS (it);
5210 }
5211 else
5212 {
5213 struct position pos;
5214 pos = *vmotion (PT, - XINT (arg), w);
5215 charpos = pos.bufpos;
5216 bytepos = pos.bytepos;
5217 }
5218 }
5219 else
5220 {
5221 struct position pos;
5222 int ht = window_internal_height (w);
5223
5224 if (center_p)
5225 arg = make_number (ht / 2);
5226 else if (XINT (arg) < 0)
5227 arg = make_number (XINT (arg) + ht);
5228
5229 pos = *vmotion (PT, - XINT (arg), w);
5230 charpos = pos.bufpos;
5231 bytepos = pos.bytepos;
5232 }
5233
5234 /* Set the new window start. */
5235 set_marker_both (w->start, w->buffer, charpos, bytepos);
5236 w->window_end_valid = Qnil;
5237
5238 w->optional_new_start = Qt;
5239
5240 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5241 w->start_at_line_beg = Qt;
5242 else
5243 w->start_at_line_beg = Qnil;
5244
5245 set_buffer_internal (obuf);
5246 return Qnil;
5247 }
5248
5249
5250 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5251 0, 1, 0,
5252 doc: /* Return the height in lines of the text display area of WINDOW.
5253 This doesn't include the mode-line (or header-line if any) or any
5254 partial-height lines in the text display area. */)
5255 (window)
5256 Lisp_Object window;
5257 {
5258 struct window *w = decode_window (window);
5259 int pixel_height = window_box_height (w);
5260 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5261 return make_number (line_height);
5262 }
5263
5264
5265 \f
5266 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5267 1, 1, "P",
5268 doc: /* Position point relative to window.
5269 With no argument, position point at center of window.
5270 An argument specifies vertical position within the window;
5271 zero means top of window, negative means relative to bottom of window. */)
5272 (arg)
5273 Lisp_Object arg;
5274 {
5275 struct window *w = XWINDOW (selected_window);
5276 int lines, start;
5277 Lisp_Object window;
5278
5279 window = selected_window;
5280 start = marker_position (w->start);
5281 if (start < BEGV || start > ZV)
5282 {
5283 int height = window_internal_height (w);
5284 Fvertical_motion (make_number (- (height / 2)), window);
5285 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5286 w->start_at_line_beg = Fbolp ();
5287 w->force_start = Qt;
5288 }
5289 else
5290 Fgoto_char (w->start);
5291
5292 lines = displayed_window_lines (w);
5293 if (NILP (arg))
5294 XSETFASTINT (arg, lines / 2);
5295 else
5296 {
5297 arg = Fprefix_numeric_value (arg);
5298 if (XINT (arg) < 0)
5299 XSETINT (arg, XINT (arg) + lines);
5300 }
5301
5302 /* Skip past a partially visible first line. */
5303 if (w->vscroll)
5304 XSETINT (arg, XINT (arg) + 1);
5305
5306 return Fvertical_motion (arg, window);
5307 }
5308
5309
5310 \f
5311 /***********************************************************************
5312 Window Configuration
5313 ***********************************************************************/
5314
5315 struct save_window_data
5316 {
5317 EMACS_INT size_from_Lisp_Vector_struct;
5318 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5319 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
5320 Lisp_Object frame_tool_bar_lines;
5321 Lisp_Object selected_frame;
5322 Lisp_Object current_window;
5323 Lisp_Object current_buffer;
5324 Lisp_Object minibuf_scroll_window;
5325 Lisp_Object minibuf_selected_window;
5326 Lisp_Object root_window;
5327 Lisp_Object focus_frame;
5328 /* Record the values of window-min-width and window-min-height
5329 so that window sizes remain consistent with them. */
5330 Lisp_Object min_width, min_height;
5331 /* A vector, each of whose elements is a struct saved_window
5332 for one window. */
5333 Lisp_Object saved_windows;
5334 };
5335
5336 /* This is saved as a Lisp_Vector */
5337 struct saved_window
5338 {
5339 /* these first two must agree with struct Lisp_Vector in lisp.h */
5340 EMACS_INT size_from_Lisp_Vector_struct;
5341 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5342
5343 Lisp_Object window;
5344 Lisp_Object buffer, start, pointm, mark;
5345 Lisp_Object left_col, top_line, total_cols, total_lines;
5346 Lisp_Object hscroll, min_hscroll;
5347 Lisp_Object parent, prev;
5348 Lisp_Object start_at_line_beg;
5349 Lisp_Object display_table;
5350 Lisp_Object orig_top_line, orig_total_lines;
5351 Lisp_Object left_margin_cols, right_margin_cols;
5352 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5353 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5354 };
5355
5356 #define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
5357
5358 #define SAVED_WINDOW_N(swv,n) \
5359 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5360
5361 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5362 doc: /* Return t if OBJECT is a window-configuration object. */)
5363 (object)
5364 Lisp_Object object;
5365 {
5366 if (WINDOW_CONFIGURATIONP (object))
5367 return Qt;
5368 return Qnil;
5369 }
5370
5371 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5372 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5373 (config)
5374 Lisp_Object config;
5375 {
5376 register struct save_window_data *data;
5377 struct Lisp_Vector *saved_windows;
5378
5379 if (! WINDOW_CONFIGURATIONP (config))
5380 wrong_type_argument (Qwindow_configuration_p, config);
5381
5382 data = (struct save_window_data *) XVECTOR (config);
5383 saved_windows = XVECTOR (data->saved_windows);
5384 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5385 }
5386
5387 DEFUN ("set-window-configuration", Fset_window_configuration,
5388 Sset_window_configuration, 1, 1, 0,
5389 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5390 CONFIGURATION must be a value previously returned
5391 by `current-window-configuration' (which see).
5392 If CONFIGURATION was made from a frame that is now deleted,
5393 only frame-independent values can be restored. In this case,
5394 the return value is nil. Otherwise the value is t. */)
5395 (configuration)
5396 Lisp_Object configuration;
5397 {
5398 register struct save_window_data *data;
5399 struct Lisp_Vector *saved_windows;
5400 Lisp_Object new_current_buffer;
5401 Lisp_Object frame;
5402 FRAME_PTR f;
5403 int old_point = -1;
5404
5405 while (!WINDOW_CONFIGURATIONP (configuration))
5406 wrong_type_argument (Qwindow_configuration_p, configuration);
5407
5408 data = (struct save_window_data *) XVECTOR (configuration);
5409 saved_windows = XVECTOR (data->saved_windows);
5410
5411 new_current_buffer = data->current_buffer;
5412 if (NILP (XBUFFER (new_current_buffer)->name))
5413 new_current_buffer = Qnil;
5414 else
5415 {
5416 if (XBUFFER (new_current_buffer) == current_buffer)
5417 old_point = PT;
5418 else
5419 old_point = BUF_PT (XBUFFER (new_current_buffer));
5420 }
5421
5422 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5423 f = XFRAME (frame);
5424
5425 /* If f is a dead frame, don't bother rebuilding its window tree.
5426 However, there is other stuff we should still try to do below. */
5427 if (FRAME_LIVE_P (f))
5428 {
5429 register struct window *w;
5430 register struct saved_window *p;
5431 struct window *root_window;
5432 struct window **leaf_windows;
5433 int n_leaf_windows;
5434 int k, i, n;
5435
5436 /* If the frame has been resized since this window configuration was
5437 made, we change the frame to the size specified in the
5438 configuration, restore the configuration, and then resize it
5439 back. We keep track of the prevailing height in these variables. */
5440 int previous_frame_lines = FRAME_LINES (f);
5441 int previous_frame_cols = FRAME_COLS (f);
5442 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5443 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5444
5445 /* The mouse highlighting code could get screwed up
5446 if it runs during this. */
5447 BLOCK_INPUT;
5448
5449 if (XFASTINT (data->frame_lines) != previous_frame_lines
5450 || XFASTINT (data->frame_cols) != previous_frame_cols)
5451 change_frame_size (f, XFASTINT (data->frame_lines),
5452 XFASTINT (data->frame_cols), 0, 0, 0);
5453 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5454 if (XFASTINT (data->frame_menu_bar_lines)
5455 != previous_frame_menu_bar_lines)
5456 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5457 #ifdef HAVE_WINDOW_SYSTEM
5458 if (XFASTINT (data->frame_tool_bar_lines)
5459 != previous_frame_tool_bar_lines)
5460 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5461 #endif
5462 #endif
5463
5464 /* "Swap out" point from the selected window
5465 into its buffer. We do this now, before
5466 restoring the window contents, and prevent it from
5467 being done later on when we select a new window. */
5468 if (! NILP (XWINDOW (selected_window)->buffer))
5469 {
5470 w = XWINDOW (selected_window);
5471 set_marker_both (w->pointm,
5472 w->buffer,
5473 BUF_PT (XBUFFER (w->buffer)),
5474 BUF_PT_BYTE (XBUFFER (w->buffer)));
5475 }
5476
5477 windows_or_buffers_changed++;
5478 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5479
5480 /* Problem: Freeing all matrices and later allocating them again
5481 is a serious redisplay flickering problem. What we would
5482 really like to do is to free only those matrices not reused
5483 below. */
5484 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5485 leaf_windows
5486 = (struct window **) alloca (count_windows (root_window)
5487 * sizeof (struct window *));
5488 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5489
5490 /* Temporarily avoid any problems with windows that are smaller
5491 than they are supposed to be. */
5492 window_min_height = 1;
5493 window_min_width = 1;
5494
5495 /* Kludge Alert!
5496 Mark all windows now on frame as "deleted".
5497 Restoring the new configuration "undeletes" any that are in it.
5498
5499 Save their current buffers in their height fields, since we may
5500 need it later, if a buffer saved in the configuration is now
5501 dead. */
5502 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5503
5504 for (k = 0; k < saved_windows->size; k++)
5505 {
5506 p = SAVED_WINDOW_N (saved_windows, k);
5507 w = XWINDOW (p->window);
5508 w->next = Qnil;
5509
5510 if (!NILP (p->parent))
5511 w->parent = SAVED_WINDOW_N (saved_windows,
5512 XFASTINT (p->parent))->window;
5513 else
5514 w->parent = Qnil;
5515
5516 if (!NILP (p->prev))
5517 {
5518 w->prev = SAVED_WINDOW_N (saved_windows,
5519 XFASTINT (p->prev))->window;
5520 XWINDOW (w->prev)->next = p->window;
5521 }
5522 else
5523 {
5524 w->prev = Qnil;
5525 if (!NILP (w->parent))
5526 {
5527 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5528 {
5529 XWINDOW (w->parent)->vchild = p->window;
5530 XWINDOW (w->parent)->hchild = Qnil;
5531 }
5532 else
5533 {
5534 XWINDOW (w->parent)->hchild = p->window;
5535 XWINDOW (w->parent)->vchild = Qnil;
5536 }
5537 }
5538 }
5539
5540 /* If we squirreled away the buffer in the window's height,
5541 restore it now. */
5542 if (BUFFERP (w->total_lines))
5543 w->buffer = w->total_lines;
5544 w->left_col = p->left_col;
5545 w->top_line = p->top_line;
5546 w->total_cols = p->total_cols;
5547 w->total_lines = p->total_lines;
5548 w->hscroll = p->hscroll;
5549 w->min_hscroll = p->min_hscroll;
5550 w->display_table = p->display_table;
5551 w->orig_top_line = p->orig_top_line;
5552 w->orig_total_lines = p->orig_total_lines;
5553 w->left_margin_cols = p->left_margin_cols;
5554 w->right_margin_cols = p->right_margin_cols;
5555 w->left_fringe_width = p->left_fringe_width;
5556 w->right_fringe_width = p->right_fringe_width;
5557 w->fringes_outside_margins = p->fringes_outside_margins;
5558 w->scroll_bar_width = p->scroll_bar_width;
5559 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5560 XSETFASTINT (w->last_modified, 0);
5561 XSETFASTINT (w->last_overlay_modified, 0);
5562
5563 /* Reinstall the saved buffer and pointers into it. */
5564 if (NILP (p->buffer))
5565 w->buffer = p->buffer;
5566 else
5567 {
5568 if (!NILP (XBUFFER (p->buffer)->name))
5569 /* If saved buffer is alive, install it. */
5570 {
5571 w->buffer = p->buffer;
5572 w->start_at_line_beg = p->start_at_line_beg;
5573 set_marker_restricted (w->start, p->start, w->buffer);
5574 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5575 Fset_marker (XBUFFER (w->buffer)->mark,
5576 p->mark, w->buffer);
5577
5578 /* As documented in Fcurrent_window_configuration, don't
5579 restore the location of point in the buffer which was
5580 current when the window configuration was recorded. */
5581 if (!EQ (p->buffer, new_current_buffer)
5582 && XBUFFER (p->buffer) == current_buffer)
5583 Fgoto_char (w->pointm);
5584 }
5585 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5586 /* Else unless window has a live buffer, get one. */
5587 {
5588 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5589 /* This will set the markers to beginning of visible
5590 range. */
5591 set_marker_restricted (w->start, make_number (0), w->buffer);
5592 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5593 w->start_at_line_beg = Qt;
5594 }
5595 else
5596 /* Keeping window's old buffer; make sure the markers
5597 are real. */
5598 {
5599 /* Set window markers at start of visible range. */
5600 if (XMARKER (w->start)->buffer == 0)
5601 set_marker_restricted (w->start, make_number (0),
5602 w->buffer);
5603 if (XMARKER (w->pointm)->buffer == 0)
5604 set_marker_restricted_both (w->pointm, w->buffer,
5605 BUF_PT (XBUFFER (w->buffer)),
5606 BUF_PT_BYTE (XBUFFER (w->buffer)));
5607 w->start_at_line_beg = Qt;
5608 }
5609 }
5610 }
5611
5612 FRAME_ROOT_WINDOW (f) = data->root_window;
5613 /* Prevent "swapping out point" in the old selected window
5614 using the buffer that has been restored into it.
5615 Use the point value from the beginning of this function
5616 since unshow_buffer (called from delete_all_subwindows)
5617 could have altered it. */
5618 selected_window = Qnil;
5619 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5620 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5621 make_number (old_point),
5622 XWINDOW (data->current_window)->buffer);
5623
5624 Fselect_window (data->current_window, Qnil);
5625 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5626 = selected_window;
5627
5628 if (NILP (data->focus_frame)
5629 || (FRAMEP (data->focus_frame)
5630 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5631 Fredirect_frame_focus (frame, data->focus_frame);
5632
5633 #if 0 /* I don't understand why this is needed, and it causes problems
5634 when the frame's old selected window has been deleted. */
5635 if (f != selected_frame && FRAME_WINDOW_P (f))
5636 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5637 0, 0);
5638 #endif
5639
5640 /* Set the screen height to the value it had before this function. */
5641 if (previous_frame_lines != FRAME_LINES (f)
5642 || previous_frame_cols != FRAME_COLS (f))
5643 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5644 0, 0, 0);
5645 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5646 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5647 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5648 make_number (0));
5649 #ifdef HAVE_WINDOW_SYSTEM
5650 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5651 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5652 make_number (0));
5653 #endif
5654 #endif
5655
5656 /* Now, free glyph matrices in windows that were not reused. */
5657 for (i = n = 0; i < n_leaf_windows; ++i)
5658 {
5659 if (NILP (leaf_windows[i]->buffer))
5660 {
5661 /* Assert it's not reused as a combination. */
5662 xassert (NILP (leaf_windows[i]->hchild)
5663 && NILP (leaf_windows[i]->vchild));
5664 free_window_matrices (leaf_windows[i]);
5665 }
5666 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5667 ++n;
5668 }
5669
5670 adjust_glyphs (f);
5671
5672 UNBLOCK_INPUT;
5673
5674 /* Fselect_window will have made f the selected frame, so we
5675 reselect the proper frame here. Fhandle_switch_frame will change the
5676 selected window too, but that doesn't make the call to
5677 Fselect_window above totally superfluous; it still sets f's
5678 selected window. */
5679 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5680 do_switch_frame (data->selected_frame, 0, 0);
5681
5682 if (! NILP (Vwindow_configuration_change_hook)
5683 && ! NILP (Vrun_hooks))
5684 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5685 }
5686
5687 if (!NILP (new_current_buffer))
5688 Fset_buffer (new_current_buffer);
5689
5690 /* Restore the minimum heights recorded in the configuration. */
5691 window_min_height = XINT (data->min_height);
5692 window_min_width = XINT (data->min_width);
5693
5694 Vminibuf_scroll_window = data->minibuf_scroll_window;
5695 minibuf_selected_window = data->minibuf_selected_window;
5696
5697 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5698 }
5699
5700 /* Mark all windows now on frame as deleted
5701 by setting their buffers to nil. */
5702
5703 void
5704 delete_all_subwindows (w)
5705 register struct window *w;
5706 {
5707 if (!NILP (w->next))
5708 delete_all_subwindows (XWINDOW (w->next));
5709 if (!NILP (w->vchild))
5710 delete_all_subwindows (XWINDOW (w->vchild));
5711 if (!NILP (w->hchild))
5712 delete_all_subwindows (XWINDOW (w->hchild));
5713
5714 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
5715
5716 if (!NILP (w->buffer))
5717 unshow_buffer (w);
5718
5719 /* We set all three of these fields to nil, to make sure that we can
5720 distinguish this dead window from any live window. Live leaf
5721 windows will have buffer set, and combination windows will have
5722 vchild or hchild set. */
5723 w->buffer = Qnil;
5724 w->vchild = Qnil;
5725 w->hchild = Qnil;
5726
5727 Vwindow_list = Qnil;
5728 }
5729 \f
5730 static int
5731 count_windows (window)
5732 register struct window *window;
5733 {
5734 register int count = 1;
5735 if (!NILP (window->next))
5736 count += count_windows (XWINDOW (window->next));
5737 if (!NILP (window->vchild))
5738 count += count_windows (XWINDOW (window->vchild));
5739 if (!NILP (window->hchild))
5740 count += count_windows (XWINDOW (window->hchild));
5741 return count;
5742 }
5743
5744
5745 /* Fill vector FLAT with leaf windows under W, starting at index I.
5746 Value is last index + 1. */
5747
5748 static int
5749 get_leaf_windows (w, flat, i)
5750 struct window *w;
5751 struct window **flat;
5752 int i;
5753 {
5754 while (w)
5755 {
5756 if (!NILP (w->hchild))
5757 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5758 else if (!NILP (w->vchild))
5759 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5760 else
5761 flat[i++] = w;
5762
5763 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5764 }
5765
5766 return i;
5767 }
5768
5769
5770 /* Return a pointer to the glyph W's physical cursor is on. Value is
5771 null if W's current matrix is invalid, so that no meaningfull glyph
5772 can be returned. */
5773
5774 struct glyph *
5775 get_phys_cursor_glyph (w)
5776 struct window *w;
5777 {
5778 struct glyph_row *row;
5779 struct glyph *glyph;
5780
5781 if (w->phys_cursor.vpos >= 0
5782 && w->phys_cursor.vpos < w->current_matrix->nrows
5783 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5784 row->enabled_p)
5785 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5786 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5787 else
5788 glyph = NULL;
5789
5790 return glyph;
5791 }
5792
5793
5794 static int
5795 save_window_save (window, vector, i)
5796 Lisp_Object window;
5797 struct Lisp_Vector *vector;
5798 int i;
5799 {
5800 register struct saved_window *p;
5801 register struct window *w;
5802 register Lisp_Object tem;
5803
5804 for (;!NILP (window); window = w->next)
5805 {
5806 p = SAVED_WINDOW_N (vector, i);
5807 w = XWINDOW (window);
5808
5809 XSETFASTINT (w->temslot, i++);
5810 p->window = window;
5811 p->buffer = w->buffer;
5812 p->left_col = w->left_col;
5813 p->top_line = w->top_line;
5814 p->total_cols = w->total_cols;
5815 p->total_lines = w->total_lines;
5816 p->hscroll = w->hscroll;
5817 p->min_hscroll = w->min_hscroll;
5818 p->display_table = w->display_table;
5819 p->orig_top_line = w->orig_top_line;
5820 p->orig_total_lines = w->orig_total_lines;
5821 p->left_margin_cols = w->left_margin_cols;
5822 p->right_margin_cols = w->right_margin_cols;
5823 p->left_fringe_width = w->left_fringe_width;
5824 p->right_fringe_width = w->right_fringe_width;
5825 p->fringes_outside_margins = w->fringes_outside_margins;
5826 p->scroll_bar_width = w->scroll_bar_width;
5827 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
5828 if (!NILP (w->buffer))
5829 {
5830 /* Save w's value of point in the window configuration.
5831 If w is the selected window, then get the value of point
5832 from the buffer; pointm is garbage in the selected window. */
5833 if (EQ (window, selected_window))
5834 {
5835 p->pointm = Fmake_marker ();
5836 set_marker_both (p->pointm, w->buffer,
5837 BUF_PT (XBUFFER (w->buffer)),
5838 BUF_PT_BYTE (XBUFFER (w->buffer)));
5839 }
5840 else
5841 p->pointm = Fcopy_marker (w->pointm, Qnil);
5842
5843 p->start = Fcopy_marker (w->start, Qnil);
5844 p->start_at_line_beg = w->start_at_line_beg;
5845
5846 tem = XBUFFER (w->buffer)->mark;
5847 p->mark = Fcopy_marker (tem, Qnil);
5848 }
5849 else
5850 {
5851 p->pointm = Qnil;
5852 p->start = Qnil;
5853 p->mark = Qnil;
5854 p->start_at_line_beg = Qnil;
5855 }
5856
5857 if (NILP (w->parent))
5858 p->parent = Qnil;
5859 else
5860 p->parent = XWINDOW (w->parent)->temslot;
5861
5862 if (NILP (w->prev))
5863 p->prev = Qnil;
5864 else
5865 p->prev = XWINDOW (w->prev)->temslot;
5866
5867 if (!NILP (w->vchild))
5868 i = save_window_save (w->vchild, vector, i);
5869 if (!NILP (w->hchild))
5870 i = save_window_save (w->hchild, vector, i);
5871 }
5872
5873 return i;
5874 }
5875
5876 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5877 Scurrent_window_configuration, 0, 1, 0,
5878 doc: /* Return an object representing the current window configuration of FRAME.
5879 If FRAME is nil or omitted, use the selected frame.
5880 This describes the number of windows, their sizes and current buffers,
5881 and for each displayed buffer, where display starts, and the positions of
5882 point and mark. An exception is made for point in the current buffer:
5883 its value is -not- saved.
5884 This also records the currently selected frame, and FRAME's focus
5885 redirection (see `redirect-frame-focus'). */)
5886 (frame)
5887 Lisp_Object frame;
5888 {
5889 register Lisp_Object tem;
5890 register int n_windows;
5891 register struct save_window_data *data;
5892 register struct Lisp_Vector *vec;
5893 register int i;
5894 FRAME_PTR f;
5895
5896 if (NILP (frame))
5897 frame = selected_frame;
5898 CHECK_LIVE_FRAME (frame);
5899 f = XFRAME (frame);
5900
5901 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5902 vec = allocate_other_vector (VECSIZE (struct save_window_data));
5903 data = (struct save_window_data *)vec;
5904
5905 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
5906 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
5907 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5908 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5909 data->selected_frame = selected_frame;
5910 data->current_window = FRAME_SELECTED_WINDOW (f);
5911 XSETBUFFER (data->current_buffer, current_buffer);
5912 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5913 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5914 data->root_window = FRAME_ROOT_WINDOW (f);
5915 data->focus_frame = FRAME_FOCUS_FRAME (f);
5916 XSETINT (data->min_height, window_min_height);
5917 XSETINT (data->min_width, window_min_width);
5918 tem = Fmake_vector (make_number (n_windows), Qnil);
5919 data->saved_windows = tem;
5920 for (i = 0; i < n_windows; i++)
5921 XVECTOR (tem)->contents[i]
5922 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5923 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5924 XSETWINDOW_CONFIGURATION (tem, data);
5925 return (tem);
5926 }
5927
5928 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5929 0, UNEVALLED, 0,
5930 doc: /* Execute BODY, preserving window sizes and contents.
5931 Return the value of the last form in BODY.
5932 Restore which buffer appears in which window, where display starts,
5933 and the value of point and mark for each window.
5934 Also restore the choice of selected window.
5935 Also restore which buffer is current.
5936 Does not restore the value of point in current buffer.
5937 usage: (save-window-excursion BODY ...) */)
5938 (args)
5939 Lisp_Object args;
5940 {
5941 register Lisp_Object val;
5942 register int count = SPECPDL_INDEX ();
5943
5944 record_unwind_protect (Fset_window_configuration,
5945 Fcurrent_window_configuration (Qnil));
5946 val = Fprogn (args);
5947 return unbind_to (count, val);
5948 }
5949
5950 \f
5951 /***********************************************************************
5952 Marginal Areas
5953 ***********************************************************************/
5954
5955 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5956 2, 3, 0,
5957 doc: /* Set width of marginal areas of window WINDOW.
5958 If WINDOW is nil, set margins of the currently selected window.
5959 Second arg LEFT-WIDTH specifies the number of character cells to
5960 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
5961 does the same for the right marginal area. A nil width parameter
5962 means no margin. */)
5963 (window, left, right)
5964 Lisp_Object window, left, right;
5965 {
5966 struct window *w = decode_window (window);
5967
5968 /* Translate negative or zero widths to nil.
5969 Margins that are too wide have to be checked elsewhere. */
5970
5971 if (!NILP (left))
5972 {
5973 CHECK_NUMBER (left);
5974 if (XINT (left) <= 0)
5975 left = Qnil;
5976 }
5977
5978 if (!NILP (right))
5979 {
5980 CHECK_NUMBER (right);
5981 if (XINT (right) <= 0)
5982 right = Qnil;
5983 }
5984
5985 if (!EQ (w->left_margin_cols, left)
5986 || !EQ (w->right_margin_cols, right))
5987 {
5988 w->left_margin_cols = left;
5989 w->right_margin_cols = right;
5990
5991 adjust_window_margins (w);
5992
5993 ++windows_or_buffers_changed;
5994 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5995 }
5996
5997 return Qnil;
5998 }
5999
6000
6001 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6002 0, 1, 0,
6003 doc: /* Get width of marginal areas of window WINDOW.
6004 If WINDOW is omitted or nil, use the currently selected window.
6005 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6006 If a marginal area does not exist, its width will be returned
6007 as nil. */)
6008 (window)
6009 Lisp_Object window;
6010 {
6011 struct window *w = decode_window (window);
6012 return Fcons (w->left_margin_cols, w->right_margin_cols);
6013 }
6014
6015
6016 \f
6017 /***********************************************************************
6018 Fringes
6019 ***********************************************************************/
6020
6021 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6022 2, 4, 0,
6023 doc: /* Set the fringe widths of window WINDOW.
6024 If WINDOW is nil, set the fringe widths of the currently selected
6025 window.
6026 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6027 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6028 fringe width. If a fringe width arg is nil, that means to use the
6029 frame's default fringe width. Default fringe widths can be set with
6030 the command `set-fringe-style'.
6031 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6032 outside of the display margins. By default, fringes are drawn between
6033 display marginal areas and the text area. */)
6034 (window, left, right, outside_margins)
6035 Lisp_Object window, left, right, outside_margins;
6036 {
6037 struct window *w = decode_window (window);
6038
6039 if (!NILP (left))
6040 CHECK_NATNUM (left);
6041 if (!NILP (right))
6042 CHECK_NATNUM (right);
6043
6044 if (!EQ (w->left_fringe_width, left)
6045 || !EQ (w->right_fringe_width, right)
6046 || !EQ (w->fringes_outside_margins, outside_margins))
6047 {
6048 w->left_fringe_width = left;
6049 w->right_fringe_width = right;
6050 w->fringes_outside_margins = outside_margins;
6051
6052 adjust_window_margins (w);
6053
6054 clear_glyph_matrix (w->current_matrix);
6055 w->window_end_valid = Qnil;
6056
6057 ++windows_or_buffers_changed;
6058 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6059 }
6060
6061 return Qnil;
6062 }
6063
6064
6065 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6066 0, 1, 0,
6067 doc: /* Get width of fringes of window WINDOW.
6068 If WINDOW is omitted or nil, use the currently selected window.
6069 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6070 (window)
6071 Lisp_Object window;
6072 {
6073 struct window *w = decode_window (window);
6074 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6075 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6076 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
6077 Qt : Qnil), Qnil)));
6078 }
6079
6080
6081 \f
6082 /***********************************************************************
6083 Scroll bars
6084 ***********************************************************************/
6085
6086 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6087 2, 4, 0,
6088 doc: /* Set width and type of scroll bars of window WINDOW.
6089 If window is nil, set scroll bars of the currently selected window.
6090 Second parameter WIDTH specifies the pixel width for the scroll bar;
6091 this is automatically adjusted to a multiple of the frame column width.
6092 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6093 bar: left, right, or nil.
6094 If WIDTH is nil, use the frame's scroll-bar width.
6095 If TYPE is t, use the frame's scroll-bar type. */)
6096 (window, width, vertical_type, horizontal_type)
6097 Lisp_Object window, width, vertical_type, horizontal_type;
6098 {
6099 struct window *w = decode_window (window);
6100
6101 if (!NILP (width))
6102 CHECK_NATNUM (width);
6103
6104 if (XINT (width) == 0)
6105 vertical_type = Qnil;
6106
6107 if (!(EQ (vertical_type, Qnil)
6108 || EQ (vertical_type, Qleft)
6109 || EQ (vertical_type, Qright)
6110 || EQ (vertical_type, Qt)))
6111 error ("Invalid type of vertical scroll bar");
6112
6113 if (!EQ (w->scroll_bar_width, width)
6114 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6115 {
6116 w->scroll_bar_width = width;
6117 w->vertical_scroll_bar_type = vertical_type;
6118
6119 adjust_window_margins (w);
6120
6121 clear_glyph_matrix (w->current_matrix);
6122 w->window_end_valid = Qnil;
6123
6124 ++windows_or_buffers_changed;
6125 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6126 }
6127
6128 return Qnil;
6129 }
6130
6131
6132 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6133 0, 1, 0,
6134 doc: /* Get width and type of scroll bars of window WINDOW.
6135 If WINDOW is omitted or nil, use the currently selected window.
6136 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6137 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6138 value. */)
6139 (window)
6140 Lisp_Object window;
6141 {
6142 struct window *w = decode_window (window);
6143 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6144 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6145 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6146 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6147 Fcons (w->vertical_scroll_bar_type,
6148 Fcons (Qnil, Qnil))));
6149 }
6150
6151
6152 \f
6153 /***********************************************************************
6154 Smooth scrolling
6155 ***********************************************************************/
6156
6157 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6158 doc: /* Return the amount by which WINDOW is scrolled vertically.
6159 Use the selected window if WINDOW is nil or omitted.
6160 Normally, value is a multiple of the canonical character height of WINDOW;
6161 optional second arg PIXELS_P means value is measured in pixels. */)
6162 (window, pixels_p)
6163 Lisp_Object window, pixels_p;
6164 {
6165 Lisp_Object result;
6166 struct frame *f;
6167 struct window *w;
6168
6169 if (NILP (window))
6170 window = selected_window;
6171 else
6172 CHECK_WINDOW (window);
6173 w = XWINDOW (window);
6174 f = XFRAME (w->frame);
6175
6176 if (FRAME_WINDOW_P (f))
6177 result = (NILP (pixels_p)
6178 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6179 : make_number (-w->vscroll));
6180 else
6181 result = make_number (0);
6182 return result;
6183 }
6184
6185
6186 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6187 2, 3, 0,
6188 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6189 WINDOW nil means use the selected window. Normally, VSCROLL is a
6190 non-negative multiple of the canonical character height of WINDOW;
6191 optional third arg PIXELS_P non-nil means that VSCROLL is in pixels.
6192 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6193 corresponds to an integral number of pixels. The return value is the
6194 result of this rounding.
6195 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6196 (window, vscroll, pixels_p)
6197 Lisp_Object window, vscroll, pixels_p;
6198 {
6199 struct window *w;
6200 struct frame *f;
6201
6202 if (NILP (window))
6203 window = selected_window;
6204 else
6205 CHECK_WINDOW (window);
6206 CHECK_NUMBER_OR_FLOAT (vscroll);
6207
6208 w = XWINDOW (window);
6209 f = XFRAME (w->frame);
6210
6211 if (FRAME_WINDOW_P (f))
6212 {
6213 int old_dy = w->vscroll;
6214
6215 w->vscroll = - (NILP (pixels_p)
6216 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6217 : XFLOATINT (vscroll));
6218 w->vscroll = min (w->vscroll, 0);
6219
6220 /* Adjust glyph matrix of the frame if the virtual display
6221 area becomes larger than before. */
6222 if (w->vscroll < 0 && w->vscroll < old_dy)
6223 adjust_glyphs (f);
6224
6225 /* Prevent redisplay shortcuts. */
6226 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6227 }
6228
6229 return Fwindow_vscroll (window, pixels_p);
6230 }
6231
6232 \f
6233 /* Call FN for all leaf windows on frame F. FN is called with the
6234 first argument being a pointer to the leaf window, and with
6235 additional argument USER_DATA. Stops when FN returns 0. */
6236
6237 void
6238 foreach_window (f, fn, user_data)
6239 struct frame *f;
6240 int (* fn) P_ ((struct window *, void *));
6241 void *user_data;
6242 {
6243 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6244 }
6245
6246
6247 /* Helper function for foreach_window. Call FN for all leaf windows
6248 reachable from W. FN is called with the first argument being a
6249 pointer to the leaf window, and with additional argument USER_DATA.
6250 Stop when FN returns 0. Value is 0 if stopped by FN. */
6251
6252 static int
6253 foreach_window_1 (w, fn, user_data)
6254 struct window *w;
6255 int (* fn) P_ ((struct window *, void *));
6256 void *user_data;
6257 {
6258 int cont;
6259
6260 for (cont = 1; w && cont;)
6261 {
6262 if (!NILP (w->hchild))
6263 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6264 else if (!NILP (w->vchild))
6265 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6266 else
6267 cont = fn (w, user_data);
6268
6269 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6270 }
6271
6272 return cont;
6273 }
6274
6275
6276 /* Freeze or unfreeze the window start of W unless it is a
6277 mini-window or the selected window. FREEZE_P non-null means freeze
6278 the window start. */
6279
6280 static int
6281 freeze_window_start (w, freeze_p)
6282 struct window *w;
6283 void *freeze_p;
6284 {
6285 if (w == XWINDOW (selected_window)
6286 || MINI_WINDOW_P (w)
6287 || (MINI_WINDOW_P (XWINDOW (selected_window))
6288 && ! NILP (Vminibuf_scroll_window)
6289 && w == XWINDOW (Vminibuf_scroll_window)))
6290 freeze_p = NULL;
6291
6292 w->frozen_window_start_p = freeze_p != NULL;
6293 return 1;
6294 }
6295
6296
6297 /* Freeze or unfreeze the window starts of all leaf windows on frame
6298 F, except the selected window and a mini-window. FREEZE_P non-zero
6299 means freeze the window start. */
6300
6301 void
6302 freeze_window_starts (f, freeze_p)
6303 struct frame *f;
6304 int freeze_p;
6305 {
6306 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6307 }
6308
6309 \f
6310 /***********************************************************************
6311 Initialization
6312 ***********************************************************************/
6313
6314 /* Return 1 if window configurations C1 and C2
6315 describe the same state of affairs. This is used by Fequal. */
6316
6317 int
6318 compare_window_configurations (c1, c2, ignore_positions)
6319 Lisp_Object c1, c2;
6320 int ignore_positions;
6321 {
6322 register struct save_window_data *d1, *d2;
6323 struct Lisp_Vector *sw1, *sw2;
6324 int i;
6325
6326 if (!WINDOW_CONFIGURATIONP (c1))
6327 wrong_type_argument (Qwindow_configuration_p, c1);
6328 if (!WINDOW_CONFIGURATIONP (c2))
6329 wrong_type_argument (Qwindow_configuration_p, c2);
6330
6331 d1 = (struct save_window_data *) XVECTOR (c1);
6332 d2 = (struct save_window_data *) XVECTOR (c2);
6333 sw1 = XVECTOR (d1->saved_windows);
6334 sw2 = XVECTOR (d2->saved_windows);
6335
6336 if (! EQ (d1->frame_cols, d2->frame_cols))
6337 return 0;
6338 if (! EQ (d1->frame_lines, d2->frame_lines))
6339 return 0;
6340 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6341 return 0;
6342 if (! EQ (d1->selected_frame, d2->selected_frame))
6343 return 0;
6344 /* Don't compare the current_window field directly.
6345 Instead see w1_is_current and w2_is_current, below. */
6346 if (! EQ (d1->current_buffer, d2->current_buffer))
6347 return 0;
6348 if (! ignore_positions)
6349 {
6350 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6351 return 0;
6352 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6353 return 0;
6354 }
6355 /* Don't compare the root_window field.
6356 We don't require the two configurations
6357 to use the same window object,
6358 and the two root windows must be equivalent
6359 if everything else compares equal. */
6360 if (! EQ (d1->focus_frame, d2->focus_frame))
6361 return 0;
6362 if (! EQ (d1->min_width, d2->min_width))
6363 return 0;
6364 if (! EQ (d1->min_height, d2->min_height))
6365 return 0;
6366
6367 /* Verify that the two confis have the same number of windows. */
6368 if (sw1->size != sw2->size)
6369 return 0;
6370
6371 for (i = 0; i < sw1->size; i++)
6372 {
6373 struct saved_window *p1, *p2;
6374 int w1_is_current, w2_is_current;
6375
6376 p1 = SAVED_WINDOW_N (sw1, i);
6377 p2 = SAVED_WINDOW_N (sw2, i);
6378
6379 /* Verify that the current windows in the two
6380 configurations correspond to each other. */
6381 w1_is_current = EQ (d1->current_window, p1->window);
6382 w2_is_current = EQ (d2->current_window, p2->window);
6383
6384 if (w1_is_current != w2_is_current)
6385 return 0;
6386
6387 /* Verify that the corresponding windows do match. */
6388 if (! EQ (p1->buffer, p2->buffer))
6389 return 0;
6390 if (! EQ (p1->left_col, p2->left_col))
6391 return 0;
6392 if (! EQ (p1->top_line, p2->top_line))
6393 return 0;
6394 if (! EQ (p1->total_cols, p2->total_cols))
6395 return 0;
6396 if (! EQ (p1->total_lines, p2->total_lines))
6397 return 0;
6398 if (! EQ (p1->display_table, p2->display_table))
6399 return 0;
6400 if (! EQ (p1->parent, p2->parent))
6401 return 0;
6402 if (! EQ (p1->prev, p2->prev))
6403 return 0;
6404 if (! ignore_positions)
6405 {
6406 if (! EQ (p1->hscroll, p2->hscroll))
6407 return 0;
6408 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6409 return 0;
6410 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6411 return 0;
6412 if (NILP (Fequal (p1->start, p2->start)))
6413 return 0;
6414 if (NILP (Fequal (p1->pointm, p2->pointm)))
6415 return 0;
6416 if (NILP (Fequal (p1->mark, p2->mark)))
6417 return 0;
6418 }
6419 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6420 return 0;
6421 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6422 return 0;
6423 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6424 return 0;
6425 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6426 return 0;
6427 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6428 return 0;
6429 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6430 return 0;
6431 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6432 return 0;
6433 }
6434
6435 return 1;
6436 }
6437
6438 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6439 Scompare_window_configurations, 2, 2, 0,
6440 doc: /* Compare two window configurations as regards the structure of windows.
6441 This function ignores details such as the values of point and mark
6442 and scrolling positions. */)
6443 (x, y)
6444 Lisp_Object x, y;
6445 {
6446 if (compare_window_configurations (x, y, 1))
6447 return Qt;
6448 return Qnil;
6449 }
6450 \f
6451 void
6452 init_window_once ()
6453 {
6454 struct frame *f = make_terminal_frame ();
6455 XSETFRAME (selected_frame, f);
6456 Vterminal_frame = selected_frame;
6457 minibuf_window = f->minibuffer_window;
6458 selected_window = f->selected_window;
6459 last_nonminibuf_frame = f;
6460
6461 window_initialized = 1;
6462 }
6463
6464 void
6465 init_window ()
6466 {
6467 Vwindow_list = Qnil;
6468 }
6469
6470 void
6471 syms_of_window ()
6472 {
6473 Qwindow_size_fixed = intern ("window-size-fixed");
6474 staticpro (&Qwindow_size_fixed);
6475
6476 staticpro (&Qwindow_configuration_change_hook);
6477 Qwindow_configuration_change_hook
6478 = intern ("window-configuration-change-hook");
6479
6480 Qwindowp = intern ("windowp");
6481 staticpro (&Qwindowp);
6482
6483 Qwindow_configuration_p = intern ("window-configuration-p");
6484 staticpro (&Qwindow_configuration_p);
6485
6486 Qwindow_live_p = intern ("window-live-p");
6487 staticpro (&Qwindow_live_p);
6488
6489 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
6490 staticpro (&Qtemp_buffer_show_hook);
6491
6492 staticpro (&Vwindow_list);
6493
6494 minibuf_selected_window = Qnil;
6495 staticpro (&minibuf_selected_window);
6496
6497 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
6498 doc: /* Non-nil means call as function to display a help buffer.
6499 The function is called with one argument, the buffer to be displayed.
6500 Used by `with-output-to-temp-buffer'.
6501 If this function is used, then it must do the entire job of showing
6502 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6503 Vtemp_buffer_show_function = Qnil;
6504
6505 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
6506 doc: /* If non-nil, function to call to handle `display-buffer'.
6507 It will receive two args, the buffer and a flag which if non-nil means
6508 that the currently selected window is not acceptable.
6509 It should choose or create a window, display the specified buffer in it,
6510 and return the window.
6511 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
6512 work using this function. */);
6513 Vdisplay_buffer_function = Qnil;
6514
6515 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
6516 doc: /* *If non-nil, `display-buffer' should even the window heights.
6517 If nil, `display-buffer' will leave the window configuration alone. */);
6518 Veven_window_heights = Qt;
6519
6520 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
6521 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6522 Vminibuf_scroll_window = Qnil;
6523
6524 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
6525 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6526 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6527 is displayed in the `mode-line' face. */);
6528 mode_line_in_non_selected_windows = 1;
6529
6530 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
6531 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6532 Vother_window_scroll_buffer = Qnil;
6533
6534 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
6535 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
6536 pop_up_frames = 0;
6537
6538 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
6539 doc: /* *Non-nil means `display-buffer' should reuse frames.
6540 If the buffer in question is already displayed in a frame, raise that frame. */);
6541 display_buffer_reuse_frames = 0;
6542
6543 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
6544 doc: /* Function to call to handle automatic new frame creation.
6545 It is called with no arguments and should return a newly created frame.
6546
6547 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
6548 where `pop-up-frame-alist' would hold the default frame parameters. */);
6549 Vpop_up_frame_function = Qnil;
6550
6551 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
6552 doc: /* *List of buffer names that should have their own special frames.
6553 Displaying a buffer whose name is in this list makes a special frame for it
6554 using `special-display-function'. See also `special-display-regexps'.
6555
6556 An element of the list can be a list instead of just a string.
6557 There are two ways to use a list as an element:
6558 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
6559 In the first case, the FRAME-PARAMETERS are pairs of the form
6560 \(PARAMETER . VALUE); these parameter values are used to create the frame.
6561 In the second case, FUNCTION is called with BUFFER as the first argument,
6562 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
6563 All this is done by the function found in `special-display-function'.
6564
6565 If the specified frame parameters include (same-buffer . t), the
6566 buffer is displayed in the currently selected window. Otherwise, if
6567 they include (same-frame . t), the buffer is displayed in a new window
6568 in the currently selected frame.
6569
6570 If this variable appears \"not to work\", because you add a name to it
6571 but that buffer still appears in the selected window, look at the
6572 values of `same-window-buffer-names' and `same-window-regexps'.
6573 Those variables take precedence over this one. */);
6574 Vspecial_display_buffer_names = Qnil;
6575
6576 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
6577 doc: /* *List of regexps saying which buffers should have their own special frames.
6578 If a buffer name matches one of these regexps, it gets its own frame.
6579 Displaying a buffer whose name is in this list makes a special frame for it
6580 using `special-display-function'.
6581
6582 An element of the list can be a list instead of just a string.
6583 There are two ways to use a list as an element:
6584 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6585 In the first case, the FRAME-PARAMETERS are pairs of the form
6586 \(PARAMETER . VALUE); these parameter values are used to create the frame.
6587 In the second case, FUNCTION is called with BUFFER as the first argument,
6588 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
6589 All this is done by the function found in `special-display-function'.
6590
6591 If the specified frame parameters include (same-buffer . t), the
6592 buffer is displayed in the currently selected window. Otherwise, if
6593 they include (same-frame . t), the buffer is displayed in a new window
6594 in the currently selected frame.
6595
6596 If this variable appears \"not to work\", because you add a regexp to it
6597 but the matching buffers still appear in the selected window, look at the
6598 values of `same-window-buffer-names' and `same-window-regexps'.
6599 Those variables take precedence over this one. */);
6600 Vspecial_display_regexps = Qnil;
6601
6602 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
6603 doc: /* Function to call to make a new frame for a special buffer.
6604 It is called with two arguments, the buffer and optional buffer specific
6605 data, and should return a window displaying that buffer.
6606 The default value normally makes a separate frame for the buffer,
6607 using `special-display-frame-alist' to specify the frame parameters.
6608 But if the buffer specific data includes (same-buffer . t) then the
6609 buffer is displayed in the current selected window.
6610 Otherwise if it includes (same-frame . t) then the buffer is displayed in
6611 a new window in the currently selected frame.
6612
6613 A buffer is special if it is listed in `special-display-buffer-names'
6614 or matches a regexp in `special-display-regexps'. */);
6615 Vspecial_display_function = Qnil;
6616
6617 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
6618 doc: /* *List of buffer names that should appear in the selected window.
6619 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6620 switches to it in the selected window, rather than making it appear
6621 in some other window.
6622
6623 An element of the list can be a cons cell instead of just a string.
6624 Then the car must be a string, which specifies the buffer name.
6625 This is for compatibility with `special-display-buffer-names';
6626 the cdr of the cons cell is ignored.
6627
6628 See also `same-window-regexps'. */);
6629 Vsame_window_buffer_names = Qnil;
6630
6631 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
6632 doc: /* *List of regexps saying which buffers should appear in the selected window.
6633 If a buffer name matches one of these regexps, then displaying it
6634 using `display-buffer' or `pop-to-buffer' switches to it
6635 in the selected window, rather than making it appear in some other window.
6636
6637 An element of the list can be a cons cell instead of just a string.
6638 Then the car must be a string, which specifies the buffer name.
6639 This is for compatibility with `special-display-buffer-names';
6640 the cdr of the cons cell is ignored.
6641
6642 See also `same-window-buffer-names'. */);
6643 Vsame_window_regexps = Qnil;
6644
6645 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
6646 doc: /* *Non-nil means display-buffer should make new windows. */);
6647 pop_up_windows = 1;
6648
6649 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
6650 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
6651 next_screen_context_lines = 2;
6652
6653 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
6654 doc: /* *A window must be at least this tall to be eligible for splitting by `display-buffer'.
6655 If there is only one window, it is split regardless of this value. */);
6656 split_height_threshold = 500;
6657
6658 DEFVAR_INT ("window-min-height", &window_min_height,
6659 doc: /* *Delete any window less than this tall (including its mode line). */);
6660 window_min_height = 4;
6661
6662 DEFVAR_INT ("window-min-width", &window_min_width,
6663 doc: /* *Delete any window less than this wide. */);
6664 window_min_width = 10;
6665
6666 DEFVAR_LISP ("scroll-preserve-screen-position",
6667 &Vscroll_preserve_screen_position,
6668 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
6669 Vscroll_preserve_screen_position = Qnil;
6670
6671 DEFVAR_LISP ("window-configuration-change-hook",
6672 &Vwindow_configuration_change_hook,
6673 doc: /* Functions to call when window configuration changes.
6674 The selected frame is the one whose configuration has changed. */);
6675 Vwindow_configuration_change_hook = Qnil;
6676
6677 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6678 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6679 If the value is`height', then only the window's height is fixed.
6680 If the value is `width', then only the window's width is fixed.
6681 Any other non-nil value fixes both the width and the height.
6682 Emacs won't change the size of any window displaying that buffer,
6683 unless you explicitly change the size, or Emacs has no other choice. */);
6684 Fmake_variable_buffer_local (Qwindow_size_fixed);
6685 window_size_fixed = 0;
6686
6687 defsubr (&Sselected_window);
6688 defsubr (&Sminibuffer_window);
6689 defsubr (&Swindow_minibuffer_p);
6690 defsubr (&Swindowp);
6691 defsubr (&Swindow_live_p);
6692 defsubr (&Spos_visible_in_window_p);
6693 defsubr (&Swindow_buffer);
6694 defsubr (&Swindow_height);
6695 defsubr (&Swindow_width);
6696 defsubr (&Swindow_hscroll);
6697 defsubr (&Sset_window_hscroll);
6698 defsubr (&Swindow_redisplay_end_trigger);
6699 defsubr (&Sset_window_redisplay_end_trigger);
6700 defsubr (&Swindow_edges);
6701 defsubr (&Swindow_pixel_edges);
6702 defsubr (&Swindow_inside_edges);
6703 defsubr (&Swindow_inside_pixel_edges);
6704 defsubr (&Scoordinates_in_window_p);
6705 defsubr (&Swindow_at);
6706 defsubr (&Swindow_point);
6707 defsubr (&Swindow_start);
6708 defsubr (&Swindow_end);
6709 defsubr (&Sset_window_point);
6710 defsubr (&Sset_window_start);
6711 defsubr (&Swindow_dedicated_p);
6712 defsubr (&Sset_window_dedicated_p);
6713 defsubr (&Swindow_display_table);
6714 defsubr (&Sset_window_display_table);
6715 defsubr (&Snext_window);
6716 defsubr (&Sprevious_window);
6717 defsubr (&Sother_window);
6718 defsubr (&Sget_lru_window);
6719 defsubr (&Sget_largest_window);
6720 defsubr (&Sget_buffer_window);
6721 defsubr (&Sdelete_other_windows);
6722 defsubr (&Sdelete_windows_on);
6723 defsubr (&Sreplace_buffer_in_windows);
6724 defsubr (&Sdelete_window);
6725 defsubr (&Sset_window_buffer);
6726 defsubr (&Sselect_window);
6727 defsubr (&Sspecial_display_p);
6728 defsubr (&Ssame_window_p);
6729 defsubr (&Sdisplay_buffer);
6730 defsubr (&Sforce_window_update);
6731 defsubr (&Ssplit_window);
6732 defsubr (&Senlarge_window);
6733 defsubr (&Sshrink_window);
6734 defsubr (&Sscroll_up);
6735 defsubr (&Sscroll_down);
6736 defsubr (&Sscroll_left);
6737 defsubr (&Sscroll_right);
6738 defsubr (&Sother_window_for_scrolling);
6739 defsubr (&Sscroll_other_window);
6740 defsubr (&Sminibuffer_selected_window);
6741 defsubr (&Srecenter);
6742 defsubr (&Swindow_text_height);
6743 defsubr (&Smove_to_window_line);
6744 defsubr (&Swindow_configuration_p);
6745 defsubr (&Swindow_configuration_frame);
6746 defsubr (&Sset_window_configuration);
6747 defsubr (&Scurrent_window_configuration);
6748 defsubr (&Ssave_window_excursion);
6749 defsubr (&Sset_window_margins);
6750 defsubr (&Swindow_margins);
6751 defsubr (&Sset_window_fringes);
6752 defsubr (&Swindow_fringes);
6753 defsubr (&Sset_window_scroll_bars);
6754 defsubr (&Swindow_scroll_bars);
6755 defsubr (&Swindow_vscroll);
6756 defsubr (&Sset_window_vscroll);
6757 defsubr (&Scompare_window_configurations);
6758 defsubr (&Swindow_list);
6759 }
6760
6761 void
6762 keys_of_window ()
6763 {
6764 initial_define_key (control_x_map, '1', "delete-other-windows");
6765 initial_define_key (control_x_map, '2', "split-window");
6766 initial_define_key (control_x_map, '0', "delete-window");
6767 initial_define_key (control_x_map, 'o', "other-window");
6768 initial_define_key (control_x_map, '^', "enlarge-window");
6769 initial_define_key (control_x_map, '<', "scroll-left");
6770 initial_define_key (control_x_map, '>', "scroll-right");
6771
6772 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6773 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6774 initial_define_key (meta_map, 'v', "scroll-down");
6775
6776 initial_define_key (global_map, Ctl('L'), "recenter");
6777 initial_define_key (meta_map, 'r', "move-to-window-line");
6778 }
6779
6780 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
6781 (do not change this comment) */