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