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