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