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