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