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