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