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