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