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