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