(window_min_size_2): Don't count header-line.
[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 "lisp.h"
25 #include "buffer.h"
26 #include "keyboard.h"
27 #include "keymap.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "commands.h"
31 #include "indent.h"
32 #include "termchar.h"
33 #include "disptab.h"
34 #include "dispextern.h"
35 #include "blockinput.h"
36 #include "intervals.h"
37
38 #ifdef HAVE_X_WINDOWS
39 #include "xterm.h"
40 #endif /* HAVE_X_WINDOWS */
41 #ifdef WINDOWSNT
42 #include "w32term.h"
43 #endif
44 #ifdef MSDOS
45 #include "msdos.h"
46 #endif
47 #ifdef MAC_OS
48 #include "macterm.h"
49 #endif
50
51
52 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
53 Lisp_Object Qscroll_up, Qscroll_down;
54 Lisp_Object Qwindow_size_fixed;
55 extern Lisp_Object Qleft_margin, Qright_margin;
56
57 static int displayed_window_lines P_ ((struct window *));
58 static struct window *decode_window P_ ((Lisp_Object));
59 static int count_windows P_ ((struct window *));
60 static int get_leaf_windows P_ ((struct window *, struct window **, int));
61 static void window_scroll P_ ((Lisp_Object, int, int, int));
62 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
63 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
64 static int window_min_size_1 P_ ((struct window *, int));
65 static int window_min_size_2 P_ ((struct window *, int));
66 static int window_min_size P_ ((struct window *, int, int, int *));
67 static void size_window P_ ((Lisp_Object, int, int, int, int, int));
68 static int freeze_window_start P_ ((struct window *, void *));
69 static int window_fixed_size_p P_ ((struct window *, int, int));
70 static void enlarge_window P_ ((Lisp_Object, int, int));
71 static Lisp_Object window_list P_ ((void));
72 static int add_window_to_list P_ ((struct window *, void *));
73 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
74 Lisp_Object));
75 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
76 Lisp_Object, int));
77 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
78 Lisp_Object *));
79 static int foreach_window_1 P_ ((struct window *,
80 int (* fn) (struct window *, void *),
81 void *));
82 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
83
84 /* This is the window in which the terminal's cursor should
85 be left when nothing is being done with it. This must
86 always be a leaf window, and its buffer is selected by
87 the top level editing loop at the end of each command.
88
89 This value is always the same as
90 FRAME_SELECTED_WINDOW (selected_frame). */
91
92 Lisp_Object selected_window;
93
94 /* A list of all windows for use by next_window and Fwindow_list.
95 Functions creating or deleting windows should invalidate this cache
96 by setting it to nil. */
97
98 Lisp_Object Vwindow_list;
99
100 /* The mini-buffer window of the selected frame.
101 Note that you cannot test for mini-bufferness of an arbitrary window
102 by comparing against this; but you can test for mini-bufferness of
103 the selected window. */
104
105 Lisp_Object minibuf_window;
106
107 /* Non-nil means it is the window whose mode line should be
108 shown as the selected window when the minibuffer is selected. */
109
110 Lisp_Object minibuf_selected_window;
111
112 /* Non-nil means it is the window for C-M-v to scroll
113 when the mini-buffer is selected. */
114
115 Lisp_Object Vminibuf_scroll_window;
116
117 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
118
119 Lisp_Object Vother_window_scroll_buffer;
120
121 /* Non-nil means it's function to call to display temp buffers. */
122
123 Lisp_Object Vtemp_buffer_show_function;
124
125 /* Non-zero means line and page scrolling on tall lines (with images)
126 does partial scrolling by modifying window-vscroll. */
127
128 int auto_window_vscroll_p;
129
130 /* Non-zero means to use mode-line-inactive face in all windows but the
131 selected-window and the minibuffer-scroll-window when the
132 minibuffer is active. */
133 int mode_line_in_non_selected_windows;
134
135 /* If a window gets smaller than either of these, it is removed. */
136
137 EMACS_INT window_min_height;
138 EMACS_INT window_min_width;
139
140 /* Nonzero implies Fdisplay_buffer should create windows. */
141
142 int pop_up_windows;
143
144 /* Nonzero implies make new frames for Fdisplay_buffer. */
145
146 int pop_up_frames;
147
148 /* Nonzero means reuse existing frames for displaying buffers. */
149
150 int display_buffer_reuse_frames;
151
152 /* Non-nil means use this function instead of default */
153
154 Lisp_Object Vpop_up_frame_function;
155
156 /* Function to call to handle Fdisplay_buffer. */
157
158 Lisp_Object Vdisplay_buffer_function;
159
160 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
161
162 Lisp_Object Veven_window_heights;
163
164 /* List of buffer *names* for buffers that should have their own frames. */
165
166 Lisp_Object Vspecial_display_buffer_names;
167
168 /* List of regexps for buffer names that should have their own frames. */
169
170 Lisp_Object Vspecial_display_regexps;
171
172 /* Function to pop up a special frame. */
173
174 Lisp_Object Vspecial_display_function;
175
176 /* List of buffer *names* for buffers to appear in selected window. */
177
178 Lisp_Object Vsame_window_buffer_names;
179
180 /* List of regexps for buffer names to appear in selected window. */
181
182 Lisp_Object Vsame_window_regexps;
183
184 /* Hook run at end of temp_output_buffer_show. */
185
186 Lisp_Object Qtemp_buffer_show_hook;
187
188 /* Fdisplay_buffer always splits the largest window
189 if that window is more than this high. */
190
191 EMACS_INT split_height_threshold;
192
193 /* Number of lines of continuity in scrolling by screenfuls. */
194
195 EMACS_INT next_screen_context_lines;
196
197 /* Incremented for each window created. */
198
199 static int sequence_number;
200
201 /* Nonzero after init_window_once has finished. */
202
203 static int window_initialized;
204
205 /* Hook to run when window config changes. */
206
207 Lisp_Object Qwindow_configuration_change_hook;
208 Lisp_Object Vwindow_configuration_change_hook;
209
210 /* Non-nil means scroll commands try to put point
211 at the same screen height as previously. */
212
213 Lisp_Object Vscroll_preserve_screen_position;
214
215 /* Incremented by 1 whenever a window is deleted. */
216
217 int window_deletion_count;
218
219 /* Used by the function window_scroll_pixel_based */
220
221 static int window_scroll_pixel_based_preserve_y;
222
223 #if 0 /* This isn't used anywhere. */
224 /* Nonzero means we can split a frame even if it is "unsplittable". */
225 static int inhibit_frame_unsplittable;
226 #endif /* 0 */
227
228 extern EMACS_INT scroll_margin;
229
230 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
231 \f
232 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
233 doc: /* Returns t if OBJECT is a window. */)
234 (object)
235 Lisp_Object object;
236 {
237 return WINDOWP (object) ? Qt : Qnil;
238 }
239
240 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
241 doc: /* Returns t if OBJECT is a window which is currently visible. */)
242 (object)
243 Lisp_Object object;
244 {
245 return WINDOW_LIVE_P (object) ? Qt : Qnil;
246 }
247
248 Lisp_Object
249 make_window ()
250 {
251 Lisp_Object val;
252 register struct window *p;
253
254 p = allocate_window ();
255 ++sequence_number;
256 XSETFASTINT (p->sequence_number, sequence_number);
257 XSETFASTINT (p->left_col, 0);
258 XSETFASTINT (p->top_line, 0);
259 XSETFASTINT (p->total_lines, 0);
260 XSETFASTINT (p->total_cols, 0);
261 XSETFASTINT (p->hscroll, 0);
262 XSETFASTINT (p->min_hscroll, 0);
263 p->orig_top_line = p->orig_total_lines = Qnil;
264 p->start = Fmake_marker ();
265 p->pointm = Fmake_marker ();
266 XSETFASTINT (p->use_time, 0);
267 p->frame = Qnil;
268 p->display_table = Qnil;
269 p->dedicated = Qnil;
270 p->pseudo_window_p = 0;
271 bzero (&p->cursor, sizeof (p->cursor));
272 bzero (&p->last_cursor, sizeof (p->last_cursor));
273 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
274 p->desired_matrix = p->current_matrix = 0;
275 p->nrows_scale_factor = p->ncols_scale_factor = 1;
276 p->phys_cursor_type = -1;
277 p->phys_cursor_width = -1;
278 p->must_be_updated_p = 0;
279 XSETFASTINT (p->window_end_vpos, 0);
280 XSETFASTINT (p->window_end_pos, 0);
281 p->window_end_valid = Qnil;
282 p->vscroll = 0;
283 XSETWINDOW (val, p);
284 XSETFASTINT (p->last_point, 0);
285 p->frozen_window_start_p = 0;
286 p->last_cursor_off_p = p->cursor_off_p = 0;
287 p->left_margin_cols = Qnil;
288 p->right_margin_cols = Qnil;
289 p->left_fringe_width = Qnil;
290 p->right_fringe_width = Qnil;
291 p->fringes_outside_margins = Qnil;
292 p->scroll_bar_width = Qnil;
293 p->vertical_scroll_bar_type = Qt;
294
295 Vwindow_list = Qnil;
296 return val;
297 }
298
299 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
300 doc: /* Return the window that the cursor now appears in and commands apply to. */)
301 ()
302 {
303 return selected_window;
304 }
305
306 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
307 doc: /* Return the window used now for minibuffers.
308 If the optional argument FRAME is specified, return the minibuffer window
309 used by that frame. */)
310 (frame)
311 Lisp_Object frame;
312 {
313 if (NILP (frame))
314 frame = selected_frame;
315 CHECK_LIVE_FRAME (frame);
316 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
317 }
318
319 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
320 doc: /* Returns non-nil if WINDOW is a minibuffer window.
321 WINDOW defaults to the selected window. */)
322 (window)
323 Lisp_Object window;
324 {
325 struct window *w = decode_window (window);
326 return MINI_WINDOW_P (w) ? Qt : Qnil;
327 }
328
329
330 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
331 Spos_visible_in_window_p, 0, 3, 0,
332 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
333 Return nil if that position is scrolled vertically out of view.
334 If a character is only partially visible, nil is returned, unless the
335 optional argument PARTIALLY is non-nil.
336 If POS is only out of view because of horizontal scrolling, return non-nil.
337 If POS is t, it specifies the position of the last visible glyph in WINDOW.
338 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
339
340 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
341 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
342 where X and Y are the pixel coordinates relative to the top left corner
343 of the window. The remaining elements are omitted if the character after
344 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
345 off-window at the top and bottom of the row, ROWH is the height of the
346 display row, and VPOS is the row number (0-based) containing POS. */)
347 (pos, window, partially)
348 Lisp_Object pos, window, partially;
349 {
350 register struct window *w;
351 register int posint;
352 register struct buffer *buf;
353 struct text_pos top;
354 Lisp_Object in_window = Qnil;
355 int rtop, rbot, rowh, vpos, fully_p = 1;
356 int x, y;
357
358 w = decode_window (window);
359 buf = XBUFFER (w->buffer);
360 SET_TEXT_POS_FROM_MARKER (top, w->start);
361
362 if (EQ (pos, Qt))
363 posint = -1;
364 else if (!NILP (pos))
365 {
366 CHECK_NUMBER_COERCE_MARKER (pos);
367 posint = XINT (pos);
368 }
369 else if (w == XWINDOW (selected_window))
370 posint = PT;
371 else
372 posint = XMARKER (w->pointm)->charpos;
373
374 /* If position is above window start or outside buffer boundaries,
375 or if window start is out of range, position is not visible. */
376 if ((EQ (pos, Qt)
377 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
378 && CHARPOS (top) >= BUF_BEGV (buf)
379 && CHARPOS (top) <= BUF_ZV (buf)
380 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
381 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
382 in_window = Qt;
383
384 if (!NILP (in_window) && !NILP (partially))
385 {
386 Lisp_Object part = Qnil;
387 if (!fully_p)
388 part = list4 (make_number (rtop), make_number (rbot),
389 make_number (rowh), make_number (vpos));
390 in_window = Fcons (make_number (x),
391 Fcons (make_number (y), part));
392 }
393
394 return in_window;
395 }
396
397 DEFUN ("window-line-height", Fwindow_line_height,
398 Swindow_line_height, 0, 2, 0,
399 doc: /* Return height in pixels of text line LINE in window WINDOW.
400 If WINDOW is nil or omitted, use selected window.
401
402 Return height of current line if LINE is omitted or nil. Return height of
403 header or mode line if LINE is `header-line' and `mode-line'.
404 Otherwise, LINE is a text line number starting from 0. A negative number
405 counts from the end of the window.
406
407 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
408 in pixels of the visible part of the line, VPOS and YPOS are the
409 vertical position in lines and pixels of the line, relative to the top
410 of the first text line, and OFFBOT is the number of off-window pixels at
411 the bottom of the text line. If there are off-window pixels at the top
412 of the (first) text line, YPOS is negative.
413
414 Return nil if window display is not up-to-date. In that case, use
415 `pos-visible-in-window-p' to obtain the information. */)
416 (line, window)
417 Lisp_Object line, window;
418 {
419 register struct window *w;
420 register struct buffer *b;
421 struct glyph_row *row, *end_row;
422 int max_y, crop, i, n;
423
424 w = decode_window (window);
425
426 if (noninteractive
427 || w->pseudo_window_p)
428 return Qnil;
429
430 CHECK_BUFFER (w->buffer);
431 b = XBUFFER (w->buffer);
432
433 /* Fail if current matrix is not up-to-date. */
434 if (NILP (w->window_end_valid)
435 || current_buffer->clip_changed
436 || current_buffer->prevent_redisplay_optimizations_p
437 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
438 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
439 return Qnil;
440
441 if (NILP (line))
442 {
443 i = w->cursor.vpos;
444 if (i < 0 || i >= w->current_matrix->nrows
445 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
446 return Qnil;
447 max_y = window_text_bottom_y (w);
448 goto found_row;
449 }
450
451 if (EQ (line, Qheader_line))
452 {
453 if (!WINDOW_WANTS_HEADER_LINE_P (w))
454 return Qnil;
455 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
456 if (!row->enabled_p)
457 return Qnil;
458 return list4 (make_number (row->height),
459 make_number (0), make_number (0),
460 make_number (0));
461 }
462
463 if (EQ (line, Qmode_line))
464 {
465 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
466 if (!row->enabled_p)
467 return Qnil;
468 return list4 (make_number (row->height),
469 make_number (0), /* not accurate */
470 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
471 + window_text_bottom_y (w)),
472 make_number (0));
473 }
474
475 CHECK_NUMBER (line);
476 n = XINT (line);
477
478 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
479 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
480 max_y = window_text_bottom_y (w);
481 i = 0;
482
483 while ((n < 0 || i < n)
484 && row <= end_row && row->enabled_p
485 && row->y + row->height < max_y)
486 row++, i++;
487
488 if (row > end_row || !row->enabled_p)
489 return Qnil;
490
491 if (++n < 0)
492 {
493 if (-n > i)
494 return Qnil;
495 row += n;
496 i += n;
497 }
498
499 found_row:
500 crop = max (0, (row->y + row->height) - max_y);
501 return list4 (make_number (row->height + min (0, row->y) - crop),
502 make_number (i),
503 make_number (row->y),
504 make_number (crop));
505 }
506
507
508 \f
509 static struct window *
510 decode_window (window)
511 register Lisp_Object window;
512 {
513 if (NILP (window))
514 return XWINDOW (selected_window);
515
516 CHECK_LIVE_WINDOW (window);
517 return XWINDOW (window);
518 }
519
520 static struct window *
521 decode_any_window (window)
522 register Lisp_Object window;
523 {
524 if (NILP (window))
525 return XWINDOW (selected_window);
526
527 CHECK_WINDOW (window);
528 return XWINDOW (window);
529 }
530
531 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
532 doc: /* Return the buffer that WINDOW is displaying.
533 WINDOW defaults to the selected window. */)
534 (window)
535 Lisp_Object window;
536 {
537 return decode_window (window)->buffer;
538 }
539
540 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
541 doc: /* Return the number of lines in WINDOW (including its mode line).
542 WINDOW defaults to the selected window. */)
543 (window)
544 Lisp_Object window;
545 {
546 return decode_any_window (window)->total_lines;
547 }
548
549 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
550 doc: /* Return the number of display columns in WINDOW.
551 This is the width that is usable columns available for text in WINDOW.
552 If you want to find out how many columns WINDOW takes up,
553 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
554 (window)
555 Lisp_Object window;
556 {
557 return make_number (window_box_text_cols (decode_any_window (window)));
558 }
559
560 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
561 doc: /* Return t if WINDOW is as wide as its frame.
562 WINDOW defaults to the selected window. */)
563 (window)
564 Lisp_Object window;
565 {
566 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
567 }
568
569 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
570 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
571 WINDOW defaults to the selected window. */)
572 (window)
573 Lisp_Object window;
574 {
575 return decode_window (window)->hscroll;
576 }
577
578 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
579 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
580 Return NCOL. NCOL should be zero or positive.
581
582 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
583 window so that the location of point moves off-window. */)
584 (window, ncol)
585 Lisp_Object window, ncol;
586 {
587 struct window *w = decode_window (window);
588 int hscroll;
589
590 CHECK_NUMBER (ncol);
591 hscroll = max (0, XINT (ncol));
592
593 /* Prevent redisplay shortcuts when changing the hscroll. */
594 if (XINT (w->hscroll) != hscroll)
595 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
596
597 w->hscroll = make_number (hscroll);
598 return ncol;
599 }
600
601 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
602 Swindow_redisplay_end_trigger, 0, 1, 0,
603 doc: /* Return WINDOW's redisplay end trigger value.
604 WINDOW defaults to the selected window.
605 See `set-window-redisplay-end-trigger' for more information. */)
606 (window)
607 Lisp_Object window;
608 {
609 return decode_window (window)->redisplay_end_trigger;
610 }
611
612 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
613 Sset_window_redisplay_end_trigger, 2, 2, 0,
614 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
615 VALUE should be a buffer position (typically a marker) or nil.
616 If it is a buffer position, then if redisplay in WINDOW reaches a position
617 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
618 with two arguments: WINDOW, and the end trigger value.
619 Afterwards the end-trigger value is reset to nil. */)
620 (window, value)
621 register Lisp_Object window, value;
622 {
623 register struct window *w;
624
625 w = decode_window (window);
626 w->redisplay_end_trigger = value;
627 return value;
628 }
629
630 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
631 doc: /* Return a list of the edge coordinates of WINDOW.
632 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
633 RIGHT is one more than the rightmost column occupied by WINDOW,
634 and BOTTOM is one more than the bottommost row occupied by WINDOW.
635 The edges include the space used by the window's scroll bar,
636 display margins, fringes, header line, and mode line, if it has them.
637 To get the edges of the actual text area, use `window-inside-edges'. */)
638 (window)
639 Lisp_Object window;
640 {
641 register struct window *w = decode_any_window (window);
642
643 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
644 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
645 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
646 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
647 Qnil))));
648 }
649
650 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
651 doc: /* Return a list of the edge pixel coordinates of WINDOW.
652 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
653 RIGHT is one more than the rightmost x position occupied by WINDOW,
654 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
655 The pixel edges include the space used by the window's scroll bar,
656 display margins, fringes, header line, and mode line, if it has them.
657 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
658 (window)
659 Lisp_Object window;
660 {
661 register struct window *w = decode_any_window (window);
662
663 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
664 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
665 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
666 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
667 Qnil))));
668 }
669
670 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
671 doc: /* Return a list of the edge coordinates of WINDOW.
672 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
673 RIGHT is one more than the rightmost column used by text in WINDOW,
674 and BOTTOM is one more than the bottommost row used by text in WINDOW.
675 The inside edges do not include the space used by the window's scroll bar,
676 display margins, fringes, header line, and/or mode line. */)
677 (window)
678 Lisp_Object window;
679 {
680 register struct window *w = decode_any_window (window);
681
682 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
683 + WINDOW_LEFT_MARGIN_COLS (w)
684 + WINDOW_LEFT_FRINGE_COLS (w)),
685 make_number (WINDOW_TOP_EDGE_LINE (w)
686 + WINDOW_HEADER_LINE_LINES (w)),
687 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
688 - WINDOW_RIGHT_MARGIN_COLS (w)
689 - WINDOW_RIGHT_FRINGE_COLS (w)),
690 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
691 - WINDOW_MODE_LINE_LINES (w)));
692 }
693
694 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
695 doc: /* Return a list of the edge pixel coordinates of WINDOW.
696 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
697 RIGHT is one more than the rightmost x position used by text in WINDOW,
698 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
699 The inside edges do not include the space used by the window's scroll bar,
700 display margins, fringes, header line, and/or mode line. */)
701 (window)
702 Lisp_Object window;
703 {
704 register struct window *w = decode_any_window (window);
705
706 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
707 + WINDOW_LEFT_MARGIN_WIDTH (w)
708 + WINDOW_LEFT_FRINGE_WIDTH (w)),
709 make_number (WINDOW_TOP_EDGE_Y (w)
710 + WINDOW_HEADER_LINE_HEIGHT (w)),
711 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
712 - WINDOW_RIGHT_MARGIN_WIDTH (w)
713 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
714 make_number (WINDOW_BOTTOM_EDGE_Y (w)
715 - WINDOW_MODE_LINE_HEIGHT (w)));
716 }
717
718 /* Test if the character at column *X, row *Y is within window W.
719 If it is not, return ON_NOTHING;
720 if it is in the window's text area,
721 set *x and *y to its location relative to the upper left corner
722 of the window, and
723 return ON_TEXT;
724 if it is on the window's modeline, return ON_MODE_LINE;
725 if it is on the border between the window and its right sibling,
726 return ON_VERTICAL_BORDER.
727 if it is on a scroll bar,
728 return ON_SCROLL_BAR.
729 if it is on the window's top line, return ON_HEADER_LINE;
730 if it is in left or right fringe of the window,
731 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
732 to window-relative coordinates;
733 if it is in the marginal area to the left/right of the window,
734 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
735 to window-relative coordinates.
736
737 X and Y are frame relative pixel coordinates. */
738
739 static enum window_part
740 coordinates_in_window (w, x, y)
741 register struct window *w;
742 register int *x, *y;
743 {
744 struct frame *f = XFRAME (WINDOW_FRAME (w));
745 int left_x, right_x, top_y, bottom_y;
746 enum window_part part;
747 int ux = FRAME_COLUMN_WIDTH (f);
748 int x0 = WINDOW_LEFT_EDGE_X (w);
749 int x1 = WINDOW_RIGHT_EDGE_X (w);
750 /* The width of the area where the vertical line can be dragged.
751 (Between mode lines for instance. */
752 int grabbable_width = ux;
753 int lmargin_width, rmargin_width, text_left, text_right;
754
755 /* In what's below, we subtract 1 when computing right_x because we
756 want the rightmost pixel, which is given by left_pixel+width-1. */
757 if (w->pseudo_window_p)
758 {
759 left_x = 0;
760 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
761 top_y = WINDOW_TOP_EDGE_Y (w);
762 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
763 }
764 else
765 {
766 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
767 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
768 top_y = WINDOW_TOP_EDGE_Y (w);
769 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
770 }
771
772 /* Outside any interesting row? */
773 if (*y < top_y || *y >= bottom_y)
774 return ON_NOTHING;
775
776 /* On the mode line or header line? If it's near the start of
777 the mode or header line of window that's has a horizontal
778 sibling, say it's on the vertical line. That's to be able
779 to resize windows horizontally in case we're using toolkit
780 scroll bars. */
781
782 if (WINDOW_WANTS_MODELINE_P (w)
783 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
784 {
785 part = ON_MODE_LINE;
786
787 header_vertical_border_check:
788 /* We're somewhere on the mode line. We consider the place
789 between mode lines of horizontally adjacent mode lines
790 as the vertical border. If scroll bars on the left,
791 return the right window. */
792 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
793 || WINDOW_RIGHTMOST_P (w))
794 {
795 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
796 {
797 /* Convert X and Y to window relative coordinates.
798 Vertical border is at the left edge of window. */
799 *x = max (0, *x - x0);
800 *y -= top_y;
801 return ON_VERTICAL_BORDER;
802 }
803 }
804 else
805 {
806 if (abs (*x - x1) < grabbable_width)
807 {
808 /* Convert X and Y to window relative coordinates.
809 Vertical border is at the right edge of window. */
810 *x = min (x1, *x) - x0;
811 *y -= top_y;
812 return ON_VERTICAL_BORDER;
813 }
814 }
815
816 if (*x < x0 || *x >= x1)
817 return ON_NOTHING;
818
819 /* Convert X and Y to window relative coordinates.
820 Mode line starts at left edge of window. */
821 *x -= x0;
822 *y -= top_y;
823 return part;
824 }
825
826 if (WINDOW_WANTS_HEADER_LINE_P (w)
827 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
828 {
829 part = ON_HEADER_LINE;
830 goto header_vertical_border_check;
831 }
832
833 if (*x < x0 || *x >= x1)
834 return ON_NOTHING;
835
836 /* Outside any interesting column? */
837 if (*x < left_x || *x > right_x)
838 {
839 *y -= top_y;
840 return ON_SCROLL_BAR;
841 }
842
843 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
844 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
845
846 text_left = window_box_left (w, TEXT_AREA);
847 text_right = text_left + window_box_width (w, TEXT_AREA);
848
849 if (FRAME_WINDOW_P (f))
850 {
851 if (!w->pseudo_window_p
852 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
853 && !WINDOW_RIGHTMOST_P (w)
854 && (abs (*x - right_x) < grabbable_width))
855 {
856 /* Convert X and Y to window relative coordinates.
857 Vertical border is at the right edge of window. */
858 *x = min (right_x, *x) - left_x;
859 *y -= top_y;
860 return ON_VERTICAL_BORDER;
861 }
862 }
863 else
864 {
865 /* Need to say "*x > right_x" rather than >=, since on character
866 terminals, the vertical line's x coordinate is right_x. */
867 if (!w->pseudo_window_p
868 && !WINDOW_RIGHTMOST_P (w)
869 && *x > right_x - ux)
870 {
871 /* On the border on the right side of the window? Assume that
872 this area begins at RIGHT_X minus a canonical char width. */
873 *x = min (right_x, *x) - left_x;
874 *y -= top_y;
875 return ON_VERTICAL_BORDER;
876 }
877 }
878
879 if (*x < text_left)
880 {
881 if (lmargin_width > 0
882 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
883 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
884 : (*x < left_x + lmargin_width)))
885 {
886 *x -= left_x;
887 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
888 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
889 *y -= top_y;
890 return ON_LEFT_MARGIN;
891 }
892
893 /* Convert X and Y to window-relative pixel coordinates. */
894 *x -= left_x;
895 *y -= top_y;
896 return ON_LEFT_FRINGE;
897 }
898
899 if (*x >= text_right)
900 {
901 if (rmargin_width > 0
902 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
903 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
904 : (*x >= right_x - rmargin_width)))
905 {
906 *x -= right_x - rmargin_width;
907 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
908 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
909 *y -= top_y;
910 return ON_RIGHT_MARGIN;
911 }
912
913 /* Convert X and Y to window-relative pixel coordinates. */
914 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
915 *y -= top_y;
916 return ON_RIGHT_FRINGE;
917 }
918
919 /* Everything special ruled out - must be on text area */
920 *x -= text_left;
921 *y -= top_y;
922 return ON_TEXT;
923 }
924
925
926 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
927 Scoordinates_in_window_p, 2, 2, 0,
928 doc: /* Return non-nil if COORDINATES are in WINDOW.
929 COORDINATES is a cons of the form (X . Y), X and Y being distances
930 measured in characters from the upper-left corner of the frame.
931 \(0 . 0) denotes the character in the upper left corner of the
932 frame.
933 If COORDINATES are in the text portion of WINDOW,
934 the coordinates relative to the window are returned.
935 If they are in the mode line of WINDOW, `mode-line' is returned.
936 If they are in the top mode line of WINDOW, `header-line' is returned.
937 If they are in the left fringe of WINDOW, `left-fringe' is returned.
938 If they are in the right fringe of WINDOW, `right-fringe' is returned.
939 If they are on the border between WINDOW and its right sibling,
940 `vertical-line' is returned.
941 If they are in the windows's left or right marginal areas, `left-margin'\n\
942 or `right-margin' is returned. */)
943 (coordinates, window)
944 register Lisp_Object coordinates, window;
945 {
946 struct window *w;
947 struct frame *f;
948 int x, y;
949 Lisp_Object lx, ly;
950
951 CHECK_WINDOW (window);
952 w = XWINDOW (window);
953 f = XFRAME (w->frame);
954 CHECK_CONS (coordinates);
955 lx = Fcar (coordinates);
956 ly = Fcdr (coordinates);
957 CHECK_NUMBER_OR_FLOAT (lx);
958 CHECK_NUMBER_OR_FLOAT (ly);
959 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
960 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
961
962 switch (coordinates_in_window (w, &x, &y))
963 {
964 case ON_NOTHING:
965 return Qnil;
966
967 case ON_TEXT:
968 /* X and Y are now window relative pixel coordinates. Convert
969 them to canonical char units before returning them. */
970 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
971 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
972
973 case ON_MODE_LINE:
974 return Qmode_line;
975
976 case ON_VERTICAL_BORDER:
977 return Qvertical_line;
978
979 case ON_HEADER_LINE:
980 return Qheader_line;
981
982 case ON_LEFT_FRINGE:
983 return Qleft_fringe;
984
985 case ON_RIGHT_FRINGE:
986 return Qright_fringe;
987
988 case ON_LEFT_MARGIN:
989 return Qleft_margin;
990
991 case ON_RIGHT_MARGIN:
992 return Qright_margin;
993
994 case ON_SCROLL_BAR:
995 /* Historically we are supposed to return nil in this case. */
996 return Qnil;
997
998 default:
999 abort ();
1000 }
1001 }
1002
1003
1004 /* Callback for foreach_window, used in window_from_coordinates.
1005 Check if window W contains coordinates specified by USER_DATA which
1006 is actually a pointer to a struct check_window_data CW.
1007
1008 Check if window W contains coordinates *CW->x and *CW->y. If it
1009 does, return W in *CW->window, as Lisp_Object, and return in
1010 *CW->part the part of the window under coordinates *X,*Y. Return
1011 zero from this function to stop iterating over windows. */
1012
1013 struct check_window_data
1014 {
1015 Lisp_Object *window;
1016 int *x, *y;
1017 enum window_part *part;
1018 };
1019
1020 static int
1021 check_window_containing (w, user_data)
1022 struct window *w;
1023 void *user_data;
1024 {
1025 struct check_window_data *cw = (struct check_window_data *) user_data;
1026 enum window_part found;
1027 int continue_p = 1;
1028
1029 found = coordinates_in_window (w, cw->x, cw->y);
1030 if (found != ON_NOTHING)
1031 {
1032 *cw->part = found;
1033 XSETWINDOW (*cw->window, w);
1034 continue_p = 0;
1035 }
1036
1037 return continue_p;
1038 }
1039
1040
1041 /* Find the window containing frame-relative pixel position X/Y and
1042 return it as a Lisp_Object.
1043
1044 If X, Y is on one of the window's special `window_part' elements,
1045 set *PART to the id of that element, and return X and Y converted
1046 to window relative coordinates in WX and WY.
1047
1048 If there is no window under X, Y return nil and leave *PART
1049 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1050
1051 This function was previously implemented with a loop cycling over
1052 windows with Fnext_window, and starting with the frame's selected
1053 window. It turned out that this doesn't work with an
1054 implementation of next_window using Vwindow_list, because
1055 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1056 tree of F when this function is called asynchronously from
1057 note_mouse_highlight. The original loop didn't terminate in this
1058 case. */
1059
1060 Lisp_Object
1061 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1062 struct frame *f;
1063 int x, y;
1064 enum window_part *part;
1065 int *wx, *wy;
1066 int tool_bar_p;
1067 {
1068 Lisp_Object window;
1069 struct check_window_data cw;
1070 enum window_part dummy;
1071
1072 if (part == 0)
1073 part = &dummy;
1074
1075 window = Qnil;
1076 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1077 foreach_window (f, check_window_containing, &cw);
1078
1079 /* If not found above, see if it's in the tool bar window, if a tool
1080 bar exists. */
1081 if (NILP (window)
1082 && tool_bar_p
1083 && WINDOWP (f->tool_bar_window)
1084 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1085 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1086 != ON_NOTHING))
1087 {
1088 *part = ON_TEXT;
1089 window = f->tool_bar_window;
1090 }
1091
1092 if (wx) *wx = x;
1093 if (wy) *wy = y;
1094
1095 return window;
1096 }
1097
1098 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1099 doc: /* Return window containing coordinates X and Y on FRAME.
1100 If omitted, FRAME defaults to the currently selected frame.
1101 The top left corner of the frame is considered to be row 0,
1102 column 0. */)
1103 (x, y, frame)
1104 Lisp_Object x, y, frame;
1105 {
1106 struct frame *f;
1107
1108 if (NILP (frame))
1109 frame = selected_frame;
1110 CHECK_LIVE_FRAME (frame);
1111 f = XFRAME (frame);
1112
1113 /* Check that arguments are integers or floats. */
1114 CHECK_NUMBER_OR_FLOAT (x);
1115 CHECK_NUMBER_OR_FLOAT (y);
1116
1117 return window_from_coordinates (f,
1118 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1119 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1120 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1121 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1122 0, 0, 0, 0);
1123 }
1124
1125 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1126 doc: /* Return current value of point in WINDOW.
1127 WINDOW defaults to the selected window.
1128
1129 For a nonselected window, this is the value point would have
1130 if that window were selected.
1131
1132 Note that, when WINDOW is the selected window and its buffer
1133 is also currently selected, the value returned is the same as (point).
1134 It would be more strictly correct to return the `top-level' value
1135 of point, outside of any save-excursion forms.
1136 But that is hard to define. */)
1137 (window)
1138 Lisp_Object window;
1139 {
1140 register struct window *w = decode_window (window);
1141
1142 if (w == XWINDOW (selected_window)
1143 && current_buffer == XBUFFER (w->buffer))
1144 return Fpoint ();
1145 return Fmarker_position (w->pointm);
1146 }
1147
1148 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1149 doc: /* Return position at which display currently starts in WINDOW.
1150 WINDOW defaults to the selected window.
1151 This is updated by redisplay or by calling `set-window-start'. */)
1152 (window)
1153 Lisp_Object window;
1154 {
1155 return Fmarker_position (decode_window (window)->start);
1156 }
1157
1158 /* This is text temporarily removed from the doc string below.
1159
1160 This function returns nil if the position is not currently known.
1161 That happens when redisplay is preempted and doesn't finish.
1162 If in that case you want to compute where the end of the window would
1163 have been if redisplay had finished, do this:
1164 (save-excursion
1165 (goto-char (window-start window))
1166 (vertical-motion (1- (window-height window)) window)
1167 (point))") */
1168
1169 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1170 doc: /* Return position at which display currently ends in WINDOW.
1171 WINDOW defaults to the selected window.
1172 This is updated by redisplay, when it runs to completion.
1173 Simply changing the buffer text or setting `window-start'
1174 does not update this value.
1175 Return nil if there is no recorded value. \(This can happen if the
1176 last redisplay of WINDOW was preempted, and did not finish.)
1177 If UPDATE is non-nil, compute the up-to-date position
1178 if it isn't already recorded. */)
1179 (window, update)
1180 Lisp_Object window, update;
1181 {
1182 Lisp_Object value;
1183 struct window *w = decode_window (window);
1184 Lisp_Object buf;
1185 struct buffer *b;
1186
1187 buf = w->buffer;
1188 CHECK_BUFFER (buf);
1189 b = XBUFFER (buf);
1190
1191 #if 0 /* This change broke some things. We should make it later. */
1192 /* If we don't know the end position, return nil.
1193 The user can compute it with vertical-motion if he wants to.
1194 It would be nicer to do it automatically,
1195 but that's so slow that it would probably bother people. */
1196 if (NILP (w->window_end_valid))
1197 return Qnil;
1198 #endif
1199
1200 if (! NILP (update)
1201 && ! (! NILP (w->window_end_valid)
1202 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1203 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1204 && !noninteractive)
1205 {
1206 struct text_pos startp;
1207 struct it it;
1208 struct buffer *old_buffer = NULL;
1209
1210 /* Cannot use Fvertical_motion because that function doesn't
1211 cope with variable-height lines. */
1212 if (b != current_buffer)
1213 {
1214 old_buffer = current_buffer;
1215 set_buffer_internal (b);
1216 }
1217
1218 /* In case W->start is out of the range, use something
1219 reasonable. This situation occurred when loading a file with
1220 `-l' containing a call to `rmail' with subsequent other
1221 commands. At the end, W->start happened to be BEG, while
1222 rmail had already narrowed the buffer. */
1223 if (XMARKER (w->start)->charpos < BEGV)
1224 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1225 else if (XMARKER (w->start)->charpos > ZV)
1226 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1227 else
1228 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1229
1230 start_display (&it, w, startp);
1231 move_it_vertically (&it, window_box_height (w));
1232 if (it.current_y < it.last_visible_y)
1233 move_it_past_eol (&it);
1234 value = make_number (IT_CHARPOS (it));
1235
1236 if (old_buffer)
1237 set_buffer_internal (old_buffer);
1238 }
1239 else
1240 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1241
1242 return value;
1243 }
1244
1245 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1246 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1247 Return POS. */)
1248 (window, pos)
1249 Lisp_Object window, pos;
1250 {
1251 register struct window *w = decode_window (window);
1252
1253 CHECK_NUMBER_COERCE_MARKER (pos);
1254 if (w == XWINDOW (selected_window)
1255 && XBUFFER (w->buffer) == current_buffer)
1256 Fgoto_char (pos);
1257 else
1258 set_marker_restricted (w->pointm, pos, w->buffer);
1259
1260 /* We have to make sure that redisplay updates the window to show
1261 the new value of point. */
1262 if (!EQ (window, selected_window))
1263 ++windows_or_buffers_changed;
1264
1265 return pos;
1266 }
1267
1268 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1269 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1270 Return POS.
1271 Optional third arg NOFORCE non-nil inhibits next redisplay
1272 from overriding motion of point in order to display at this exact start. */)
1273 (window, pos, noforce)
1274 Lisp_Object window, pos, noforce;
1275 {
1276 register struct window *w = decode_window (window);
1277
1278 CHECK_NUMBER_COERCE_MARKER (pos);
1279 set_marker_restricted (w->start, pos, w->buffer);
1280 /* this is not right, but much easier than doing what is right. */
1281 w->start_at_line_beg = Qnil;
1282 if (NILP (noforce))
1283 w->force_start = Qt;
1284 w->update_mode_line = Qt;
1285 XSETFASTINT (w->last_modified, 0);
1286 XSETFASTINT (w->last_overlay_modified, 0);
1287 if (!EQ (window, selected_window))
1288 windows_or_buffers_changed++;
1289
1290 return pos;
1291 }
1292
1293 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1294 1, 1, 0,
1295 doc: /* Return WINDOW's dedicated object, usually t or nil.
1296 See also `set-window-dedicated-p'. */)
1297 (window)
1298 Lisp_Object window;
1299 {
1300 return decode_window (window)->dedicated;
1301 }
1302
1303 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1304 Sset_window_dedicated_p, 2, 2, 0,
1305 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1306 If it is dedicated, Emacs will not automatically change
1307 which buffer appears in it.
1308 The second argument is the new value for the dedication flag;
1309 non-nil means yes. */)
1310 (window, arg)
1311 Lisp_Object window, arg;
1312 {
1313 register struct window *w = decode_window (window);
1314
1315 w->dedicated = arg;
1316
1317 return w->dedicated;
1318 }
1319
1320 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1321 0, 1, 0,
1322 doc: /* Return the display-table that WINDOW is using.
1323 WINDOW defaults to the selected window. */)
1324 (window)
1325 Lisp_Object window;
1326 {
1327 return decode_window (window)->display_table;
1328 }
1329
1330 /* Get the display table for use on window W. This is either W's
1331 display table or W's buffer's display table. Ignore the specified
1332 tables if they are not valid; if no valid table is specified,
1333 return 0. */
1334
1335 struct Lisp_Char_Table *
1336 window_display_table (w)
1337 struct window *w;
1338 {
1339 struct Lisp_Char_Table *dp = NULL;
1340
1341 if (DISP_TABLE_P (w->display_table))
1342 dp = XCHAR_TABLE (w->display_table);
1343 else if (BUFFERP (w->buffer))
1344 {
1345 struct buffer *b = XBUFFER (w->buffer);
1346
1347 if (DISP_TABLE_P (b->display_table))
1348 dp = XCHAR_TABLE (b->display_table);
1349 else if (DISP_TABLE_P (Vstandard_display_table))
1350 dp = XCHAR_TABLE (Vstandard_display_table);
1351 }
1352
1353 return dp;
1354 }
1355
1356 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1357 doc: /* Set WINDOW's display-table to TABLE. */)
1358 (window, table)
1359 register Lisp_Object window, table;
1360 {
1361 register struct window *w;
1362
1363 w = decode_window (window);
1364 w->display_table = table;
1365 return table;
1366 }
1367 \f
1368 /* Record info on buffer window w is displaying
1369 when it is about to cease to display that buffer. */
1370 static void
1371 unshow_buffer (w)
1372 register struct window *w;
1373 {
1374 Lisp_Object buf;
1375 struct buffer *b;
1376
1377 buf = w->buffer;
1378 b = XBUFFER (buf);
1379 if (b != XMARKER (w->pointm)->buffer)
1380 abort ();
1381
1382 #if 0
1383 if (w == XWINDOW (selected_window)
1384 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1385 /* Do this except when the selected window's buffer
1386 is being removed from some other window. */
1387 #endif
1388 /* last_window_start records the start position that this buffer
1389 had in the last window to be disconnected from it.
1390 Now that this statement is unconditional,
1391 it is possible for the buffer to be displayed in the
1392 selected window, while last_window_start reflects another
1393 window which was recently showing the same buffer.
1394 Some people might say that might be a good thing. Let's see. */
1395 b->last_window_start = marker_position (w->start);
1396
1397 /* Point in the selected window's buffer
1398 is actually stored in that buffer, and the window's pointm isn't used.
1399 So don't clobber point in that buffer. */
1400 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1401 /* This line helps to fix Horsley's testbug.el bug. */
1402 && !(WINDOWP (b->last_selected_window)
1403 && w != XWINDOW (b->last_selected_window)
1404 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1405 temp_set_point_both (b,
1406 clip_to_bounds (BUF_BEGV (b),
1407 XMARKER (w->pointm)->charpos,
1408 BUF_ZV (b)),
1409 clip_to_bounds (BUF_BEGV_BYTE (b),
1410 marker_byte_position (w->pointm),
1411 BUF_ZV_BYTE (b)));
1412
1413 if (WINDOWP (b->last_selected_window)
1414 && w == XWINDOW (b->last_selected_window))
1415 b->last_selected_window = Qnil;
1416 }
1417
1418 /* Put replacement into the window structure in place of old. */
1419 static void
1420 replace_window (old, replacement)
1421 Lisp_Object old, replacement;
1422 {
1423 register Lisp_Object tem;
1424 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1425
1426 /* If OLD is its frame's root_window, then replacement is the new
1427 root_window for that frame. */
1428
1429 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1430 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1431
1432 p->left_col = o->left_col;
1433 p->top_line = o->top_line;
1434 p->total_cols = o->total_cols;
1435 p->total_lines = o->total_lines;
1436 p->desired_matrix = p->current_matrix = 0;
1437 p->vscroll = 0;
1438 bzero (&p->cursor, sizeof (p->cursor));
1439 bzero (&p->last_cursor, sizeof (p->last_cursor));
1440 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1441 p->phys_cursor_type = -1;
1442 p->phys_cursor_width = -1;
1443 p->must_be_updated_p = 0;
1444 p->pseudo_window_p = 0;
1445 XSETFASTINT (p->window_end_vpos, 0);
1446 XSETFASTINT (p->window_end_pos, 0);
1447 p->window_end_valid = Qnil;
1448 p->frozen_window_start_p = 0;
1449 p->orig_top_line = p->orig_total_lines = Qnil;
1450
1451 p->next = tem = o->next;
1452 if (!NILP (tem))
1453 XWINDOW (tem)->prev = replacement;
1454
1455 p->prev = tem = o->prev;
1456 if (!NILP (tem))
1457 XWINDOW (tem)->next = replacement;
1458
1459 p->parent = tem = o->parent;
1460 if (!NILP (tem))
1461 {
1462 if (EQ (XWINDOW (tem)->vchild, old))
1463 XWINDOW (tem)->vchild = replacement;
1464 if (EQ (XWINDOW (tem)->hchild, old))
1465 XWINDOW (tem)->hchild = replacement;
1466 }
1467
1468 /*** Here, if replacement is a vertical combination
1469 and so is its new parent, we should make replacement's
1470 children be children of that parent instead. ***/
1471 }
1472
1473 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1474 doc: /* Remove WINDOW from the display. Default is selected window. */)
1475 (window)
1476 register Lisp_Object window;
1477 {
1478 delete_window (window);
1479
1480 if (! NILP (Vwindow_configuration_change_hook)
1481 && ! NILP (Vrun_hooks))
1482 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1483
1484 return Qnil;
1485 }
1486
1487 void
1488 delete_window (window)
1489 register Lisp_Object window;
1490 {
1491 register Lisp_Object tem, parent, sib;
1492 register struct window *p;
1493 register struct window *par;
1494 struct frame *f;
1495
1496 /* Because this function is called by other C code on non-leaf
1497 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1498 so we can't decode_window here. */
1499 if (NILP (window))
1500 window = selected_window;
1501 else
1502 CHECK_WINDOW (window);
1503 p = XWINDOW (window);
1504
1505 /* It's a no-op to delete an already-deleted window. */
1506 if (NILP (p->buffer)
1507 && NILP (p->hchild)
1508 && NILP (p->vchild))
1509 return;
1510
1511 parent = p->parent;
1512 if (NILP (parent))
1513 error ("Attempt to delete minibuffer or sole ordinary window");
1514 par = XWINDOW (parent);
1515
1516 windows_or_buffers_changed++;
1517 Vwindow_list = Qnil;
1518 f = XFRAME (WINDOW_FRAME (p));
1519 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1520
1521 /* Are we trying to delete any frame's selected window? */
1522 {
1523 Lisp_Object swindow, pwindow;
1524
1525 /* See if the frame's selected window is either WINDOW
1526 or any subwindow of it, by finding all that window's parents
1527 and comparing each one with WINDOW. */
1528 swindow = FRAME_SELECTED_WINDOW (f);
1529
1530 while (1)
1531 {
1532 pwindow = swindow;
1533 while (!NILP (pwindow))
1534 {
1535 if (EQ (window, pwindow))
1536 break;
1537 pwindow = XWINDOW (pwindow)->parent;
1538 }
1539
1540 /* If the window being deleted is not a parent of SWINDOW,
1541 then SWINDOW is ok as the new selected window. */
1542 if (!EQ (window, pwindow))
1543 break;
1544 /* Otherwise, try another window for SWINDOW. */
1545 swindow = Fnext_window (swindow, Qlambda, Qnil);
1546
1547 /* If we get back to the frame's selected window,
1548 it means there was no acceptable alternative,
1549 so we cannot delete. */
1550 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1551 error ("Cannot delete window");
1552 }
1553
1554 /* If we need to change SWINDOW, do it. */
1555 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1556 {
1557 /* If we're about to delete the selected window on the
1558 selected frame, then we should use Fselect_window to select
1559 the new window. On the other hand, if we're about to
1560 delete the selected window on any other frame, we shouldn't do
1561 anything but set the frame's selected_window slot. */
1562 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1563 Fselect_window (swindow, Qnil);
1564 else
1565 FRAME_SELECTED_WINDOW (f) = swindow;
1566 }
1567 }
1568
1569 /* Now we know we can delete this one. */
1570 window_deletion_count++;
1571
1572 tem = p->buffer;
1573 /* tem is null for dummy parent windows
1574 (which have inferiors but not any contents themselves) */
1575 if (!NILP (tem))
1576 {
1577 unshow_buffer (p);
1578 unchain_marker (XMARKER (p->pointm));
1579 unchain_marker (XMARKER (p->start));
1580 }
1581
1582 /* Free window glyph matrices. It is sure that they are allocated
1583 again when ADJUST_GLYPHS is called. Block input so that expose
1584 events and other events that access glyph matrices are not
1585 processed while we are changing them. */
1586 BLOCK_INPUT;
1587 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1588
1589 tem = p->next;
1590 if (!NILP (tem))
1591 XWINDOW (tem)->prev = p->prev;
1592
1593 tem = p->prev;
1594 if (!NILP (tem))
1595 XWINDOW (tem)->next = p->next;
1596
1597 if (EQ (window, par->hchild))
1598 par->hchild = p->next;
1599 if (EQ (window, par->vchild))
1600 par->vchild = p->next;
1601
1602 /* Find one of our siblings to give our space to. */
1603 sib = p->prev;
1604 if (NILP (sib))
1605 {
1606 /* If p gives its space to its next sibling, that sibling needs
1607 to have its top/left side pulled back to where p's is.
1608 set_window_{height,width} will re-position the sibling's
1609 children. */
1610 sib = p->next;
1611 XWINDOW (sib)->top_line = p->top_line;
1612 XWINDOW (sib)->left_col = p->left_col;
1613 }
1614
1615 /* Stretch that sibling. */
1616 if (!NILP (par->vchild))
1617 set_window_height (sib,
1618 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1619 1);
1620 if (!NILP (par->hchild))
1621 set_window_width (sib,
1622 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1623 1);
1624
1625 /* If parent now has only one child,
1626 put the child into the parent's place. */
1627 tem = par->hchild;
1628 if (NILP (tem))
1629 tem = par->vchild;
1630 if (NILP (XWINDOW (tem)->next)) {
1631 replace_window (parent, tem);
1632 par = XWINDOW (tem);
1633 }
1634
1635 /* Since we may be deleting combination windows, we must make sure that
1636 not only p but all its children have been marked as deleted. */
1637 if (! NILP (p->hchild))
1638 delete_all_subwindows (XWINDOW (p->hchild));
1639 else if (! NILP (p->vchild))
1640 delete_all_subwindows (XWINDOW (p->vchild));
1641
1642 /* Mark this window as deleted. */
1643 p->buffer = p->hchild = p->vchild = Qnil;
1644
1645 if (! NILP (par->parent))
1646 par = XWINDOW (par->parent);
1647
1648 /* Check if we have a v/hchild with a v/hchild. In that case remove
1649 one of them. */
1650
1651 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1652 {
1653 p = XWINDOW (par->vchild);
1654 par->vchild = p->vchild;
1655 tem = p->vchild;
1656 }
1657 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1658 {
1659 p = XWINDOW (par->hchild);
1660 par->hchild = p->hchild;
1661 tem = p->hchild;
1662 }
1663 else
1664 p = 0;
1665
1666 if (p)
1667 {
1668 while (! NILP (tem)) {
1669 XWINDOW (tem)->parent = p->parent;
1670 if (NILP (XWINDOW (tem)->next))
1671 break;
1672 tem = XWINDOW (tem)->next;
1673 }
1674 if (! NILP (tem)) {
1675 /* The next of the v/hchild we are removing is now the next of the
1676 last child for the v/hchild:
1677 Before v/hchild -> v/hchild -> next1 -> next2
1678 |
1679 -> next3
1680 After: v/hchild -> next1 -> next2 -> next3
1681 */
1682 XWINDOW (tem)->next = p->next;
1683 if (! NILP (p->next))
1684 XWINDOW (p->next)->prev = tem;
1685 }
1686 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1687 }
1688
1689
1690 /* Adjust glyph matrices. */
1691 adjust_glyphs (f);
1692 UNBLOCK_INPUT;
1693 }
1694
1695
1696 \f
1697 /***********************************************************************
1698 Window List
1699 ***********************************************************************/
1700
1701 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1702 pointer. This is a callback function for foreach_window, used in
1703 function window_list. */
1704
1705 static int
1706 add_window_to_list (w, user_data)
1707 struct window *w;
1708 void *user_data;
1709 {
1710 Lisp_Object *list = (Lisp_Object *) user_data;
1711 Lisp_Object window;
1712 XSETWINDOW (window, w);
1713 *list = Fcons (window, *list);
1714 return 1;
1715 }
1716
1717
1718 /* Return a list of all windows, for use by next_window. If
1719 Vwindow_list is a list, return that list. Otherwise, build a new
1720 list, cache it in Vwindow_list, and return that. */
1721
1722 static Lisp_Object
1723 window_list ()
1724 {
1725 if (!CONSP (Vwindow_list))
1726 {
1727 Lisp_Object tail;
1728
1729 Vwindow_list = Qnil;
1730 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1731 {
1732 Lisp_Object args[2];
1733
1734 /* We are visiting windows in canonical order, and add
1735 new windows at the front of args[1], which means we
1736 have to reverse this list at the end. */
1737 args[1] = Qnil;
1738 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1739 args[0] = Vwindow_list;
1740 args[1] = Fnreverse (args[1]);
1741 Vwindow_list = Fnconc (2, args);
1742 }
1743 }
1744
1745 return Vwindow_list;
1746 }
1747
1748
1749 /* Value is non-zero if WINDOW satisfies the constraints given by
1750 OWINDOW, MINIBUF and ALL_FRAMES.
1751
1752 MINIBUF t means WINDOW may be minibuffer windows.
1753 `lambda' means WINDOW may not be a minibuffer window.
1754 a window means a specific minibuffer window
1755
1756 ALL_FRAMES t means search all frames,
1757 nil means search just current frame,
1758 `visible' means search just visible frames,
1759 0 means search visible and iconified frames,
1760 a window means search the frame that window belongs to,
1761 a frame means consider windows on that frame, only. */
1762
1763 static int
1764 candidate_window_p (window, owindow, minibuf, all_frames)
1765 Lisp_Object window, owindow, minibuf, all_frames;
1766 {
1767 struct window *w = XWINDOW (window);
1768 struct frame *f = XFRAME (w->frame);
1769 int candidate_p = 1;
1770
1771 if (!BUFFERP (w->buffer))
1772 candidate_p = 0;
1773 else if (MINI_WINDOW_P (w)
1774 && (EQ (minibuf, Qlambda)
1775 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1776 {
1777 /* If MINIBUF is `lambda' don't consider any mini-windows.
1778 If it is a window, consider only that one. */
1779 candidate_p = 0;
1780 }
1781 else if (EQ (all_frames, Qt))
1782 candidate_p = 1;
1783 else if (NILP (all_frames))
1784 {
1785 xassert (WINDOWP (owindow));
1786 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1787 }
1788 else if (EQ (all_frames, Qvisible))
1789 {
1790 FRAME_SAMPLE_VISIBILITY (f);
1791 candidate_p = FRAME_VISIBLE_P (f);
1792 }
1793 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1794 {
1795 FRAME_SAMPLE_VISIBILITY (f);
1796 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1797 }
1798 else if (WINDOWP (all_frames))
1799 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1800 || EQ (XWINDOW (all_frames)->frame, w->frame)
1801 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1802 else if (FRAMEP (all_frames))
1803 candidate_p = EQ (all_frames, w->frame);
1804
1805 return candidate_p;
1806 }
1807
1808
1809 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1810 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1811 ALL_FRAMES. */
1812
1813 static void
1814 decode_next_window_args (window, minibuf, all_frames)
1815 Lisp_Object *window, *minibuf, *all_frames;
1816 {
1817 if (NILP (*window))
1818 *window = selected_window;
1819 else
1820 CHECK_LIVE_WINDOW (*window);
1821
1822 /* MINIBUF nil may or may not include minibuffers. Decide if it
1823 does. */
1824 if (NILP (*minibuf))
1825 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1826 else if (!EQ (*minibuf, Qt))
1827 *minibuf = Qlambda;
1828
1829 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1830 => count none of them, or a specific minibuffer window (the
1831 active one) to count. */
1832
1833 /* ALL_FRAMES nil doesn't specify which frames to include. */
1834 if (NILP (*all_frames))
1835 *all_frames = (!EQ (*minibuf, Qlambda)
1836 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1837 : Qnil);
1838 else if (EQ (*all_frames, Qvisible))
1839 ;
1840 else if (EQ (*all_frames, make_number (0)))
1841 ;
1842 else if (FRAMEP (*all_frames))
1843 ;
1844 else if (!EQ (*all_frames, Qt))
1845 *all_frames = Qnil;
1846
1847 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1848 search just current frame, `visible' meaning search just visible
1849 frames, 0 meaning search visible and iconified frames, or a
1850 window, meaning search the frame that window belongs to, or a
1851 frame, meaning consider windows on that frame, only. */
1852 }
1853
1854
1855 /* Return the next or previous window of WINDOW in canonical ordering
1856 of windows. NEXT_P non-zero means return the next window. See the
1857 documentation string of next-window for the meaning of MINIBUF and
1858 ALL_FRAMES. */
1859
1860 static Lisp_Object
1861 next_window (window, minibuf, all_frames, next_p)
1862 Lisp_Object window, minibuf, all_frames;
1863 int next_p;
1864 {
1865 decode_next_window_args (&window, &minibuf, &all_frames);
1866
1867 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1868 return the first window on the frame. */
1869 if (FRAMEP (all_frames)
1870 && !EQ (all_frames, XWINDOW (window)->frame))
1871 return Fframe_first_window (all_frames);
1872
1873 if (next_p)
1874 {
1875 Lisp_Object list;
1876
1877 /* Find WINDOW in the list of all windows. */
1878 list = Fmemq (window, window_list ());
1879
1880 /* Scan forward from WINDOW to the end of the window list. */
1881 if (CONSP (list))
1882 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1883 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1884 break;
1885
1886 /* Scan from the start of the window list up to WINDOW. */
1887 if (!CONSP (list))
1888 for (list = Vwindow_list;
1889 CONSP (list) && !EQ (XCAR (list), window);
1890 list = XCDR (list))
1891 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1892 break;
1893
1894 if (CONSP (list))
1895 window = XCAR (list);
1896 }
1897 else
1898 {
1899 Lisp_Object candidate, list;
1900
1901 /* Scan through the list of windows for candidates. If there are
1902 candidate windows in front of WINDOW, the last one of these
1903 is the one we want. If there are candidates following WINDOW
1904 in the list, again the last one of these is the one we want. */
1905 candidate = Qnil;
1906 for (list = window_list (); CONSP (list); list = XCDR (list))
1907 {
1908 if (EQ (XCAR (list), window))
1909 {
1910 if (WINDOWP (candidate))
1911 break;
1912 }
1913 else if (candidate_window_p (XCAR (list), window, minibuf,
1914 all_frames))
1915 candidate = XCAR (list);
1916 }
1917
1918 if (WINDOWP (candidate))
1919 window = candidate;
1920 }
1921
1922 return window;
1923 }
1924
1925
1926 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1927 doc: /* Return next window after WINDOW in canonical ordering of windows.
1928 If omitted, WINDOW defaults to the selected window.
1929
1930 Optional second arg MINIBUF t means count the minibuffer window even
1931 if not active. MINIBUF nil or omitted means count the minibuffer iff
1932 it is active. MINIBUF neither t nor nil means not to count the
1933 minibuffer even if it is active.
1934
1935 Several frames may share a single minibuffer; if the minibuffer
1936 counts, all windows on all frames that share that minibuffer count
1937 too. Therefore, `next-window' can be used to iterate through the
1938 set of windows even when the minibuffer is on another frame. If the
1939 minibuffer does not count, only windows from WINDOW's frame count.
1940
1941 Optional third arg ALL-FRAMES t means include windows on all frames.
1942 ALL-FRAMES nil or omitted means cycle within the frames as specified
1943 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1944 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1945 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1946 Anything else means restrict to WINDOW's frame.
1947
1948 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1949 `next-window' to iterate through the entire cycle of acceptable
1950 windows, eventually ending up back at the window you started with.
1951 `previous-window' traverses the same cycle, in the reverse order. */)
1952 (window, minibuf, all_frames)
1953 Lisp_Object window, minibuf, all_frames;
1954 {
1955 return next_window (window, minibuf, all_frames, 1);
1956 }
1957
1958
1959 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1960 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1961 If omitted, WINDOW defaults to the selected window.
1962
1963 Optional second arg MINIBUF t means count the minibuffer window even
1964 if not active. MINIBUF nil or omitted means count the minibuffer iff
1965 it is active. MINIBUF neither t nor nil means not to count the
1966 minibuffer even if it is active.
1967
1968 Several frames may share a single minibuffer; if the minibuffer
1969 counts, all windows on all frames that share that minibuffer count
1970 too. Therefore, `previous-window' can be used to iterate through
1971 the set of windows even when the minibuffer is on another frame. If
1972 the minibuffer does not count, only windows from WINDOW's frame count
1973
1974 Optional third arg ALL-FRAMES t means include windows on all frames.
1975 ALL-FRAMES nil or omitted means cycle within the frames as specified
1976 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1977 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1978 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1979 Anything else means restrict to WINDOW's frame.
1980
1981 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1982 `previous-window' to iterate through the entire cycle of acceptable
1983 windows, eventually ending up back at the window you started with.
1984 `next-window' traverses the same cycle, in the reverse order. */)
1985 (window, minibuf, all_frames)
1986 Lisp_Object window, minibuf, all_frames;
1987 {
1988 return next_window (window, minibuf, all_frames, 0);
1989 }
1990
1991
1992 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1993 doc: /* Select the ARG'th different window on this frame.
1994 All windows on current frame are arranged in a cyclic order.
1995 This command selects the window ARG steps away in that order.
1996 A negative ARG moves in the opposite order. The optional second
1997 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
1998 (arg, all_frames)
1999 Lisp_Object arg, all_frames;
2000 {
2001 Lisp_Object window;
2002 int i;
2003
2004 CHECK_NUMBER (arg);
2005 window = selected_window;
2006
2007 for (i = XINT (arg); i > 0; --i)
2008 window = Fnext_window (window, Qnil, all_frames);
2009 for (; i < 0; ++i)
2010 window = Fprevious_window (window, Qnil, all_frames);
2011
2012 Fselect_window (window, Qnil);
2013 return Qnil;
2014 }
2015
2016
2017 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2018 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2019 FRAME nil or omitted means use the selected frame.
2020 WINDOW nil or omitted means use the selected window.
2021 MINIBUF t means include the minibuffer window, even if it isn't active.
2022 MINIBUF nil or omitted means include the minibuffer window only
2023 if it's active.
2024 MINIBUF neither nil nor t means never include the minibuffer window. */)
2025 (frame, minibuf, window)
2026 Lisp_Object frame, minibuf, window;
2027 {
2028 if (NILP (window))
2029 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2030 CHECK_WINDOW (window);
2031 if (NILP (frame))
2032 frame = selected_frame;
2033
2034 if (!EQ (frame, XWINDOW (window)->frame))
2035 error ("Window is on a different frame");
2036
2037 return window_list_1 (window, minibuf, frame);
2038 }
2039
2040
2041 /* Return a list of windows in canonical ordering. Arguments are like
2042 for `next-window'. */
2043
2044 static Lisp_Object
2045 window_list_1 (window, minibuf, all_frames)
2046 Lisp_Object window, minibuf, all_frames;
2047 {
2048 Lisp_Object tail, list, rest;
2049
2050 decode_next_window_args (&window, &minibuf, &all_frames);
2051 list = Qnil;
2052
2053 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2054 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2055 list = Fcons (XCAR (tail), list);
2056
2057 /* Rotate the list to start with WINDOW. */
2058 list = Fnreverse (list);
2059 rest = Fmemq (window, list);
2060 if (!NILP (rest) && !EQ (rest, list))
2061 {
2062 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2063 ;
2064 XSETCDR (tail, Qnil);
2065 list = nconc2 (rest, list);
2066 }
2067 return list;
2068 }
2069
2070
2071 \f
2072 /* Look at all windows, performing an operation specified by TYPE
2073 with argument OBJ.
2074 If FRAMES is Qt, look at all frames;
2075 Qnil, look at just the selected frame;
2076 Qvisible, look at visible frames;
2077 a frame, just look at windows on that frame.
2078 If MINI is non-zero, perform the operation on minibuffer windows too. */
2079
2080 enum window_loop
2081 {
2082 WINDOW_LOOP_UNUSED,
2083 GET_BUFFER_WINDOW, /* Arg is buffer */
2084 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2085 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2086 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2087 GET_LARGEST_WINDOW,
2088 UNSHOW_BUFFER, /* Arg is buffer */
2089 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2090 CHECK_ALL_WINDOWS
2091 };
2092
2093 static Lisp_Object
2094 window_loop (type, obj, mini, frames)
2095 enum window_loop type;
2096 Lisp_Object obj, frames;
2097 int mini;
2098 {
2099 Lisp_Object window, windows, best_window, frame_arg;
2100 struct frame *f;
2101 struct gcpro gcpro1;
2102
2103 /* If we're only looping through windows on a particular frame,
2104 frame points to that frame. If we're looping through windows
2105 on all frames, frame is 0. */
2106 if (FRAMEP (frames))
2107 f = XFRAME (frames);
2108 else if (NILP (frames))
2109 f = SELECTED_FRAME ();
2110 else
2111 f = NULL;
2112
2113 if (f)
2114 frame_arg = Qlambda;
2115 else if (EQ (frames, make_number (0)))
2116 frame_arg = frames;
2117 else if (EQ (frames, Qvisible))
2118 frame_arg = frames;
2119 else
2120 frame_arg = Qt;
2121
2122 /* frame_arg is Qlambda to stick to one frame,
2123 Qvisible to consider all visible frames,
2124 or Qt otherwise. */
2125
2126 /* Pick a window to start with. */
2127 if (WINDOWP (obj))
2128 window = obj;
2129 else if (f)
2130 window = FRAME_SELECTED_WINDOW (f);
2131 else
2132 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2133
2134 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2135 GCPRO1 (windows);
2136 best_window = Qnil;
2137
2138 for (; CONSP (windows); windows = XCDR (windows))
2139 {
2140 struct window *w;
2141
2142 window = XCAR (windows);
2143 w = XWINDOW (window);
2144
2145 /* Note that we do not pay attention here to whether the frame
2146 is visible, since Fwindow_list skips non-visible frames if
2147 that is desired, under the control of frame_arg. */
2148 if (!MINI_WINDOW_P (w)
2149 /* For UNSHOW_BUFFER, we must always consider all windows. */
2150 || type == UNSHOW_BUFFER
2151 || (mini && minibuf_level > 0))
2152 switch (type)
2153 {
2154 case GET_BUFFER_WINDOW:
2155 if (EQ (w->buffer, obj)
2156 /* Don't find any minibuffer window
2157 except the one that is currently in use. */
2158 && (MINI_WINDOW_P (w)
2159 ? EQ (window, minibuf_window)
2160 : 1))
2161 {
2162 if (NILP (best_window))
2163 best_window = window;
2164 else if (EQ (window, selected_window))
2165 /* For compatibility with 20.x, prefer to return
2166 selected-window. */
2167 best_window = window;
2168 }
2169 break;
2170
2171 case GET_LRU_WINDOW:
2172 /* `obj' is an integer encoding a bitvector.
2173 `obj & 1' means consider only full-width windows.
2174 `obj & 2' means consider also dedicated windows. */
2175 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2176 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2177 /* Minibuffer windows are always ignored. */
2178 || MINI_WINDOW_P (w))
2179 break;
2180 if (NILP (best_window)
2181 || (XFASTINT (XWINDOW (best_window)->use_time)
2182 > XFASTINT (w->use_time)))
2183 best_window = window;
2184 break;
2185
2186 case DELETE_OTHER_WINDOWS:
2187 if (!EQ (window, obj))
2188 Fdelete_window (window);
2189 break;
2190
2191 case DELETE_BUFFER_WINDOWS:
2192 if (EQ (w->buffer, obj))
2193 {
2194 struct frame *f = XFRAME (WINDOW_FRAME (w));
2195
2196 /* If this window is dedicated, and in a frame of its own,
2197 kill the frame. */
2198 if (EQ (window, FRAME_ROOT_WINDOW (f))
2199 && !NILP (w->dedicated)
2200 && other_visible_frames (f))
2201 {
2202 /* Skip the other windows on this frame.
2203 There might be one, the minibuffer! */
2204 while (CONSP (XCDR (windows))
2205 && EQ (XWINDOW (XCAR (windows))->frame,
2206 XWINDOW (XCAR (XCDR (windows)))->frame))
2207 windows = XCDR (windows);
2208
2209 /* Now we can safely delete the frame. */
2210 Fdelete_frame (w->frame, Qnil);
2211 }
2212 else if (NILP (w->parent))
2213 {
2214 /* If we're deleting the buffer displayed in the
2215 only window on the frame, find a new buffer to
2216 display there. */
2217 Lisp_Object buffer;
2218 buffer = Fother_buffer (obj, Qnil, w->frame);
2219 Fset_window_buffer (window, buffer, Qnil);
2220 if (EQ (window, selected_window))
2221 Fset_buffer (w->buffer);
2222 }
2223 else
2224 Fdelete_window (window);
2225 }
2226 break;
2227
2228 case GET_LARGEST_WINDOW:
2229 { /* nil `obj' means to ignore dedicated windows. */
2230 /* Ignore dedicated windows and minibuffers. */
2231 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2232 break;
2233
2234 if (NILP (best_window))
2235 best_window = window;
2236 else
2237 {
2238 struct window *b = XWINDOW (best_window);
2239 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2240 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2241 best_window = window;
2242 }
2243 }
2244 break;
2245
2246 case UNSHOW_BUFFER:
2247 if (EQ (w->buffer, obj))
2248 {
2249 Lisp_Object buffer;
2250 struct frame *f = XFRAME (w->frame);
2251
2252 /* Find another buffer to show in this window. */
2253 buffer = Fother_buffer (obj, Qnil, w->frame);
2254
2255 /* If this window is dedicated, and in a frame of its own,
2256 kill the frame. */
2257 if (EQ (window, FRAME_ROOT_WINDOW (f))
2258 && !NILP (w->dedicated)
2259 && other_visible_frames (f))
2260 {
2261 /* Skip the other windows on this frame.
2262 There might be one, the minibuffer! */
2263 while (CONSP (XCDR (windows))
2264 && EQ (XWINDOW (XCAR (windows))->frame,
2265 XWINDOW (XCAR (XCDR (windows)))->frame))
2266 windows = XCDR (windows);
2267
2268 /* Now we can safely delete the frame. */
2269 Fdelete_frame (w->frame, Qnil);
2270 }
2271 else if (!NILP (w->dedicated) && !NILP (w->parent))
2272 {
2273 Lisp_Object window;
2274 XSETWINDOW (window, w);
2275 /* If this window is dedicated and not the only window
2276 in its frame, then kill it. */
2277 Fdelete_window (window);
2278 }
2279 else
2280 {
2281 /* Otherwise show a different buffer in the window. */
2282 w->dedicated = Qnil;
2283 Fset_window_buffer (window, buffer, Qnil);
2284 if (EQ (window, selected_window))
2285 Fset_buffer (w->buffer);
2286 }
2287 }
2288 break;
2289
2290 case REDISPLAY_BUFFER_WINDOWS:
2291 if (EQ (w->buffer, obj))
2292 {
2293 mark_window_display_accurate (window, 0);
2294 w->update_mode_line = Qt;
2295 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2296 ++update_mode_lines;
2297 best_window = window;
2298 }
2299 break;
2300
2301 /* Check for a window that has a killed buffer. */
2302 case CHECK_ALL_WINDOWS:
2303 if (! NILP (w->buffer)
2304 && NILP (XBUFFER (w->buffer)->name))
2305 abort ();
2306 break;
2307
2308 case WINDOW_LOOP_UNUSED:
2309 break;
2310 }
2311 }
2312
2313 UNGCPRO;
2314 return best_window;
2315 }
2316
2317 /* Used for debugging. Abort if any window has a dead buffer. */
2318
2319 void
2320 check_all_windows ()
2321 {
2322 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2323 }
2324
2325 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2326 doc: /* Return the window least recently selected or used for display.
2327 \(LRU means Least Recently Used.)
2328
2329 Return a full-width window if possible.
2330 A minibuffer window is never a candidate.
2331 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2332 so if all windows are dedicated, the value is nil.
2333 If optional argument FRAME is `visible', search all visible frames.
2334 If FRAME is 0, search all visible and iconified frames.
2335 If FRAME is t, search all frames.
2336 If FRAME is nil, search only the selected frame.
2337 If FRAME is a frame, search only that frame. */)
2338 (frame, dedicated)
2339 Lisp_Object frame, dedicated;
2340 {
2341 register Lisp_Object w;
2342 /* First try for a window that is full-width */
2343 w = window_loop (GET_LRU_WINDOW,
2344 NILP (dedicated) ? make_number (1) : make_number (3),
2345 0, frame);
2346 if (!NILP (w) && !EQ (w, selected_window))
2347 return w;
2348 /* If none of them, try the rest */
2349 return window_loop (GET_LRU_WINDOW,
2350 NILP (dedicated) ? make_number (0) : make_number (2),
2351 0, frame);
2352 }
2353
2354 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2355 doc: /* Return the largest window in area.
2356 A minibuffer window is never a candidate.
2357 A dedicated window is never a candidate unless DEDICATED is non-nil,
2358 so if all windows are dedicated, the value is nil.
2359 If optional argument FRAME is `visible', search all visible frames.
2360 If FRAME is 0, search all visible and iconified frames.
2361 If FRAME is t, search all frames.
2362 If FRAME is nil, search only the selected frame.
2363 If FRAME is a frame, search only that frame. */)
2364 (frame, dedicated)
2365 Lisp_Object frame, dedicated;
2366 {
2367 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2368 frame);
2369 }
2370
2371 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2372 doc: /* Return a window currently displaying BUFFER, or nil if none.
2373 BUFFER can be a buffer or a buffer name.
2374 If optional argument FRAME is `visible', search all visible frames.
2375 If optional argument FRAME is 0, search all visible and iconified frames.
2376 If FRAME is t, search all frames.
2377 If FRAME is nil, search only the selected frame.
2378 If FRAME is a frame, search only that frame. */)
2379 (buffer, frame)
2380 Lisp_Object buffer, frame;
2381 {
2382 buffer = Fget_buffer (buffer);
2383 if (BUFFERP (buffer))
2384 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2385 else
2386 return Qnil;
2387 }
2388
2389 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2390 0, 1, "",
2391 doc: /* Make WINDOW (or the selected window) fill its frame.
2392 Only the frame WINDOW is on is affected.
2393 This function tries to reduce display jumps
2394 by keeping the text previously visible in WINDOW
2395 in the same place on the frame. Doing this depends on
2396 the value of (window-start WINDOW), so if calling this function
2397 in a program gives strange scrolling, make sure the window-start
2398 value is reasonable when this function is called. */)
2399 (window)
2400 Lisp_Object window;
2401 {
2402 struct window *w;
2403 int startpos;
2404 int top, new_top;
2405
2406 if (NILP (window))
2407 window = selected_window;
2408 else
2409 CHECK_LIVE_WINDOW (window);
2410 w = XWINDOW (window);
2411
2412 startpos = marker_position (w->start);
2413 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2414
2415 if (MINI_WINDOW_P (w) && top > 0)
2416 error ("Can't expand minibuffer to full frame");
2417
2418 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2419
2420 /* Try to minimize scrolling, by setting the window start to the point
2421 will cause the text at the old window start to be at the same place
2422 on the frame. But don't try to do this if the window start is
2423 outside the visible portion (as might happen when the display is
2424 not current, due to typeahead). */
2425 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2426 if (new_top != top
2427 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2428 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2429 {
2430 struct position pos;
2431 struct buffer *obuf = current_buffer;
2432
2433 Fset_buffer (w->buffer);
2434 /* This computation used to temporarily move point, but that can
2435 have unwanted side effects due to text properties. */
2436 pos = *vmotion (startpos, -top, w);
2437
2438 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2439 w->window_end_valid = Qnil;
2440 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2441 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2442 : Qnil);
2443 /* We need to do this, so that the window-scroll-functions
2444 get called. */
2445 w->optional_new_start = Qt;
2446
2447 set_buffer_internal (obuf);
2448 }
2449
2450 return Qnil;
2451 }
2452
2453 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2454 1, 2, "bDelete windows on (buffer): ",
2455 doc: /* Delete all windows showing BUFFER.
2456 BUFFER must be a buffer or the name of an existing buffer.
2457 Optional second argument FRAME controls which frames are affected.
2458 If optional argument FRAME is `visible', search all visible frames.
2459 If FRAME is 0, search all visible and iconified frames.
2460 If FRAME is nil, search all frames.
2461 If FRAME is t, search only the selected frame.
2462 If FRAME is a frame, search only that frame. */)
2463 (buffer, frame)
2464 Lisp_Object buffer, frame;
2465 {
2466 /* FRAME uses t and nil to mean the opposite of what window_loop
2467 expects. */
2468 if (NILP (frame))
2469 frame = Qt;
2470 else if (EQ (frame, Qt))
2471 frame = Qnil;
2472
2473 if (!NILP (buffer))
2474 {
2475 buffer = Fget_buffer (buffer);
2476 CHECK_BUFFER (buffer);
2477 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2478 }
2479
2480 return Qnil;
2481 }
2482
2483 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2484 Sreplace_buffer_in_windows,
2485 1, 1, "bReplace buffer in windows: ",
2486 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2487 BUFFER may be a buffer or the name of an existing buffer. */)
2488 (buffer)
2489 Lisp_Object buffer;
2490 {
2491 if (!NILP (buffer))
2492 {
2493 buffer = Fget_buffer (buffer);
2494 CHECK_BUFFER (buffer);
2495 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2496 }
2497 return Qnil;
2498 }
2499
2500 /* Replace BUFFER with some other buffer in all windows
2501 of all frames, even those on other keyboards. */
2502
2503 void
2504 replace_buffer_in_all_windows (buffer)
2505 Lisp_Object buffer;
2506 {
2507 #ifdef MULTI_KBOARD
2508 Lisp_Object tail, frame;
2509
2510 /* A single call to window_loop won't do the job
2511 because it only considers frames on the current keyboard.
2512 So loop manually over frames, and handle each one. */
2513 FOR_EACH_FRAME (tail, frame)
2514 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2515 #else
2516 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2517 #endif
2518 }
2519 \f
2520 /* Set the height of WINDOW and all its inferiors. */
2521
2522 /* The smallest acceptable dimensions for a window. Anything smaller
2523 might crash Emacs. */
2524
2525 #define MIN_SAFE_WINDOW_WIDTH (2)
2526 #define MIN_SAFE_WINDOW_HEIGHT (1)
2527
2528 /* Make sure that window_min_height and window_min_width are
2529 not too small; if they are, set them to safe minima. */
2530
2531 static void
2532 check_min_window_sizes ()
2533 {
2534 /* Smaller values might permit a crash. */
2535 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2536 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2537 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2538 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2539 }
2540
2541 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2542 minimum allowable size. */
2543
2544 void
2545 check_frame_size (frame, rows, cols)
2546 FRAME_PTR frame;
2547 int *rows, *cols;
2548 {
2549 /* For height, we have to see:
2550 how many windows the frame has at minimum (one or two),
2551 and whether it has a menu bar or other special stuff at the top. */
2552 int min_height
2553 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2554 ? MIN_SAFE_WINDOW_HEIGHT
2555 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2556
2557 if (FRAME_TOP_MARGIN (frame) > 0)
2558 min_height += FRAME_TOP_MARGIN (frame);
2559
2560 if (*rows < min_height)
2561 *rows = min_height;
2562 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2563 *cols = MIN_SAFE_WINDOW_WIDTH;
2564 }
2565
2566 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2567 check if W's width can be changed, otherwise check W's height.
2568 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2569 siblings, too. If none of the siblings is resizable, WINDOW isn't
2570 either. */
2571
2572 static int
2573 window_fixed_size_p (w, width_p, check_siblings_p)
2574 struct window *w;
2575 int width_p, check_siblings_p;
2576 {
2577 int fixed_p;
2578 struct window *c;
2579
2580 if (!NILP (w->hchild))
2581 {
2582 c = XWINDOW (w->hchild);
2583
2584 if (width_p)
2585 {
2586 /* A horiz. combination is fixed-width if all of if its
2587 children are. */
2588 while (c && window_fixed_size_p (c, width_p, 0))
2589 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2590 fixed_p = c == NULL;
2591 }
2592 else
2593 {
2594 /* A horiz. combination is fixed-height if one of if its
2595 children is. */
2596 while (c && !window_fixed_size_p (c, width_p, 0))
2597 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2598 fixed_p = c != NULL;
2599 }
2600 }
2601 else if (!NILP (w->vchild))
2602 {
2603 c = XWINDOW (w->vchild);
2604
2605 if (width_p)
2606 {
2607 /* A vert. combination is fixed-width if one of if its
2608 children is. */
2609 while (c && !window_fixed_size_p (c, width_p, 0))
2610 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2611 fixed_p = c != NULL;
2612 }
2613 else
2614 {
2615 /* A vert. combination is fixed-height if all of if its
2616 children are. */
2617 while (c && window_fixed_size_p (c, width_p, 0))
2618 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2619 fixed_p = c == NULL;
2620 }
2621 }
2622 else if (BUFFERP (w->buffer))
2623 {
2624 struct buffer *old = current_buffer;
2625 Lisp_Object val;
2626
2627 current_buffer = XBUFFER (w->buffer);
2628 val = find_symbol_value (Qwindow_size_fixed);
2629 current_buffer = old;
2630
2631 fixed_p = 0;
2632 if (!EQ (val, Qunbound))
2633 {
2634 fixed_p = !NILP (val);
2635
2636 if (fixed_p
2637 && ((EQ (val, Qheight) && width_p)
2638 || (EQ (val, Qwidth) && !width_p)))
2639 fixed_p = 0;
2640 }
2641
2642 /* Can't tell if this one is resizable without looking at
2643 siblings. If all siblings are fixed-size this one is too. */
2644 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2645 {
2646 Lisp_Object child;
2647
2648 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2649 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2650 break;
2651
2652 if (NILP (child))
2653 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2654 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2655 break;
2656
2657 if (NILP (child))
2658 fixed_p = 1;
2659 }
2660 }
2661 else
2662 fixed_p = 1;
2663
2664 return fixed_p;
2665 }
2666
2667 /* Return the minimum size for leaf window W. WIDTH_P non-zero means
2668 take into account fringes and the scrollbar of W. WIDTH_P zero means
2669 take into account mode-line of W. Return 1 for the minibuffer. */
2670
2671 static int
2672 window_min_size_2 (w, width_p)
2673 struct window *w;
2674 int width_p;
2675 {
2676 int size;
2677
2678 if (width_p)
2679 size = max (window_min_width,
2680 (MIN_SAFE_WINDOW_WIDTH
2681 + WINDOW_FRINGE_COLS (w)
2682 + WINDOW_SCROLL_BAR_COLS (w)));
2683 else if (MINI_WINDOW_P (w))
2684 size = 1;
2685 else
2686 size = max (window_min_height,
2687 (MIN_SAFE_WINDOW_HEIGHT
2688 /* Don't count the header-line here. It would break
2689 splitting a window with a header-line when the new
2690 window shall have a height of two (calculator does
2691 that). */
2692 + (WINDOW_WANTS_MODELINE_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_terminal_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) */