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