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