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