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