(calendar-goto-today): Renamed from calendar-current-month.
[bpt/emacs.git] / src / window.c
CommitLineData
7ab12479
JB
1/* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
89bca612 3 Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
7ab12479
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
1113d9db 9the Free Software Foundation; either version 2, or (at your option)
7ab12479
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
18160b98 21#include <config.h>
7ab12479
JB
22#include "lisp.h"
23#include "buffer.h"
44fa5b1e 24#include "frame.h"
7ab12479
JB
25#include "window.h"
26#include "commands.h"
27#include "indent.h"
28#include "termchar.h"
29#include "disptab.h"
f8026fd8 30#include "keyboard.h"
7ab12479 31
806b4d9b 32Lisp_Object Qwindowp, Qwindow_live_p;
7ab12479
JB
33
34Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
35Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
36
fd482be5 37void delete_all_subwindows ();
7ab12479
JB
38static struct window *decode_window();
39
40/* This is the window in which the terminal's cursor should
41 be left when nothing is being done with it. This must
42 always be a leaf window, and its buffer is selected by
43 the top level editing loop at the end of each command.
44
45 This value is always the same as
44fa5b1e 46 FRAME_SELECTED_WINDOW (selected_frame). */
7ab12479
JB
47
48Lisp_Object selected_window;
49
44fa5b1e 50/* The minibuffer window of the selected frame.
7ab12479
JB
51 Note that you cannot test for minibufferness of an arbitrary window
52 by comparing against this; but you can test for minibufferness of
53 the selected window. */
54Lisp_Object minibuf_window;
55
56/* Non-nil means it is the window for C-M-v to scroll
57 when the minibuffer is selected. */
58Lisp_Object Vminibuf_scroll_window;
59
60/* Non-nil means this is the buffer whose window C-M-v should scroll. */
61Lisp_Object Vother_window_scroll_buffer;
62
7ab12479
JB
63/* Non-nil means it's function to call to display temp buffers. */
64Lisp_Object Vtemp_buffer_show_function;
65
66/* If a window gets smaller than either of these, it is removed. */
67int window_min_height;
68int window_min_width;
69
70/* Nonzero implies Fdisplay_buffer should create windows. */
71int pop_up_windows;
72
44fa5b1e
JB
73/* Nonzero implies make new frames for Fdisplay_buffer. */
74int pop_up_frames;
7ab12479
JB
75
76/* Non-nil means use this function instead of default */
44fa5b1e 77Lisp_Object Vpop_up_frame_function;
7ab12479
JB
78
79/* Function to call to handle Fdisplay_buffer. */
80Lisp_Object Vdisplay_buffer_function;
81
a90712c2
RS
82/* List of buffer *names* for buffers that should have their own frames. */
83Lisp_Object Vspecial_display_buffer_names;
84
85/* List of regexps for buffer names that should have their own frames. */
86Lisp_Object Vspecial_display_regexps;
87
88/* Function to pop up a special frame. */
89Lisp_Object Vspecial_display_function;
90
7ab12479
JB
91/* Fdisplay_buffer always splits the largest window
92 if that window is more than this high. */
93int split_height_threshold;
94
95/* Number of lines of continuity in scrolling by screenfuls. */
96int next_screen_context_lines;
97
98/* Incremented for each window created. */
99static int sequence_number;
100
101#define min(a, b) ((a) < (b) ? (a) : (b))
102\f
103DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
104 "Returns t if OBJ is a window.")
105 (obj)
106 Lisp_Object obj;
107{
108 return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
109}
110
806b4d9b 111DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
605be8af
JB
112 "Returns t if OBJ is a window which is currently visible.")
113 (obj)
114 Lisp_Object obj;
115{
116 return ((XTYPE (obj) == Lisp_Window
117 && ! NILP (XWINDOW (obj)->buffer))
118 ? Qt : Qnil);
119}
120
7ab12479
JB
121Lisp_Object
122make_window ()
123{
124 register Lisp_Object val;
125 register struct window *p;
126
127 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
128 includes the first element. */
129 val = Fmake_vector (
130 make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)
131 + sizeof (Lisp_Object))
132 / sizeof (Lisp_Object)),
133 Qnil);
134 XSETTYPE (val, Lisp_Window);
135 p = XWINDOW (val);
136 XFASTINT (p->sequence_number) = ++sequence_number;
137 XFASTINT (p->left) = XFASTINT (p->top)
138 = XFASTINT (p->height) = XFASTINT (p->width)
139 = XFASTINT (p->hscroll) = 0;
140 XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
141 p->start = Fmake_marker ();
142 p->pointm = Fmake_marker ();
143 XFASTINT (p->use_time) = 0;
44fa5b1e 144 p->frame = Qnil;
7ab12479
JB
145 p->display_table = Qnil;
146 p->dedicated = Qnil;
147 return val;
148}
149
150DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
151 "Return the window that the cursor now appears in and commands apply to.")
152 ()
153{
154 return selected_window;
155}
156
83762ba4
JB
157DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
158 "Return the window used now for minibuffers.\n\
159If the optional argument FRAME is specified, return the minibuffer window\n\
160used by that frame.")
161 (frame)
162 Lisp_Object frame;
7ab12479 163{
44fa5b1e 164#ifdef MULTI_FRAME
83762ba4
JB
165 if (NILP (frame))
166 XSET (frame, Lisp_Frame, selected_frame);
167 else
168 CHECK_LIVE_FRAME (frame, 0);
169#endif
170
171 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
7ab12479
JB
172}
173
605be8af 174DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
7ab12479
JB
175 "Returns non-nil if WINDOW is a minibuffer window.")
176 (window)
177 Lisp_Object window;
178{
179 struct window *w = decode_window (window);
180 return (MINI_WINDOW_P (w) ? Qt : Qnil);
181}
182
183DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
184 Spos_visible_in_window_p, 0, 2, 0,
44fa5b1e 185 "Return t if position POS is currently on the frame in WINDOW.\n\
7ab12479
JB
186Returns nil if that position is scrolled vertically out of view.\n\
187POS defaults to point; WINDOW, to the selected window.")
188 (pos, window)
189 Lisp_Object pos, window;
190{
191 register struct window *w;
192 register int top;
193 register int height;
194 register int posint;
195 register struct buffer *buf;
196 struct position posval;
afdb2485 197 int hscroll;
7ab12479 198
265a9e55 199 if (NILP (pos))
5ce7b543 200 posint = PT;
7ab12479
JB
201 else
202 {
203 CHECK_NUMBER_COERCE_MARKER (pos, 0);
204 posint = XINT (pos);
205 }
206
605be8af 207 w = decode_window (window);
7ab12479 208 top = marker_position (w->start);
afdb2485 209 hscroll = XINT (w->hscroll);
7ab12479
JB
210
211 if (posint < top)
212 return Qnil;
213
214 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
215
216 buf = XBUFFER (w->buffer);
217 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
218 {
44fa5b1e 219 /* If frame is up to date,
7ab12479
JB
220 use the info recorded about how much text fit on it. */
221 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
222 || (XFASTINT (w->window_end_vpos) < height))
223 return Qt;
224 return Qnil;
225 }
226 else
227 {
33eb4ede 228 if (posint > BUF_ZV (buf))
7ab12479
JB
229 return Qnil;
230
231 /* If that info is not correct, calculate afresh */
afdb2485
KH
232 posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0),
233 posint, height, 0,
535e0b8e 234 window_internal_width (w) - 1,
e37f06d7 235 hscroll, 0, w);
7ab12479
JB
236
237 return posval.vpos < height ? Qt : Qnil;
238 }
239}
240\f
241static struct window *
242decode_window (window)
243 register Lisp_Object window;
244{
265a9e55 245 if (NILP (window))
7ab12479
JB
246 return XWINDOW (selected_window);
247
605be8af 248 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
249 return XWINDOW (window);
250}
251
252DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
253 "Return the buffer that WINDOW is displaying.")
254 (window)
255 Lisp_Object window;
256{
257 return decode_window (window)->buffer;
258}
259
260DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
261 "Return the number of lines in WINDOW (including its mode line).")
262 (window)
263 Lisp_Object window;
264{
265 return decode_window (window)->height;
266}
267
268DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
3b5908ef
RS
269 "Return the number of display columns in WINDOW.\n\
270This is the width that is usable columns available for text in WINDOW.\n\
271If you want to find out how many columns WINDOW takes up,\n\
272use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
7ab12479
JB
273 (window)
274 Lisp_Object window;
275{
ee61d94e 276 return make_number (window_internal_width (decode_window (window)));
7ab12479
JB
277}
278
279DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
280 "Return the number of columns by which WINDOW is scrolled from left margin.")
281 (window)
282 Lisp_Object window;
283{
284 return decode_window (window)->hscroll;
285}
286
287DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
288 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
289NCOL should be zero or positive.")
290 (window, ncol)
291 register Lisp_Object window, ncol;
292{
293 register struct window *w;
294
295 CHECK_NUMBER (ncol, 1);
296 if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
297 if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
298 args_out_of_range (ncol, Qnil);
299 w = decode_window (window);
7f4161e0 300 if (XINT (w->hscroll) != XINT (ncol))
7ab12479
JB
301 clip_changed = 1; /* Prevent redisplay shortcuts */
302 w->hscroll = ncol;
303 return ncol;
304}
305
306DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
307 "Return a list of the edge coordinates of WINDOW.\n\
44fa5b1e 308\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
7ab12479
JB
309RIGHT is one more than the rightmost column used by WINDOW,\n\
310and BOTTOM is one more than the bottommost row used by WINDOW\n\
311 and its mode-line.")
312 (window)
313 Lisp_Object window;
314{
315 register struct window *w = decode_window (window);
316
317 return Fcons (w->left, Fcons (w->top,
318 Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
319 Fcons (make_number (XFASTINT (w->top)
320 + XFASTINT (w->height)),
321 Qnil))));
322}
323
d5783c40
JB
324/* Test if the character at column *x, row *y is within window *w.
325 If it is not, return 0;
326 if it is in the window's text area,
327 set *x and *y to its location relative to the upper left corner
328 of the window, and
329 return 1;
330 if it is on the window's modeline, return 2;
331 if it is on the border between the window and its right sibling,
332 return 3. */
333static int
334coordinates_in_window (w, x, y)
335 register struct window *w;
336 register int *x, *y;
337{
338 register int left = XINT (w->left);
339 register int width = XINT (w->width);
340 register int window_height = XINT (w->height);
341 register int top = XFASTINT (w->top);
342
343 if ( *x < left || *x >= left + width
344 || *y < top || *y >= top + window_height)
345 return 0;
346
347 /* Is the character is the mode line? */
348 if (*y == top + window_height - 1
05c2896a 349 && ! MINI_WINDOW_P (w))
d5783c40
JB
350 return 2;
351
352 /* Is the character in the right border? */
353 if (*x == left + width - 1
44fa5b1e 354 && left + width != FRAME_WIDTH (XFRAME (w->frame)))
d5783c40
JB
355 return 3;
356
357 *x -= left;
358 *y -= top;
359 return 1;
360}
361
362DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
363 Scoordinates_in_window_p, 2, 2, 0,
364 "Return non-nil if COORDINATES are in WINDOW.\n\
1113d9db 365COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
44fa5b1e 366measured in characters from the upper-left corner of the frame.\n\
1113d9db 367(0 . 0) denotes the character in the upper left corner of the\n\
44fa5b1e 368frame.\n\
d5783c40
JB
369If COORDINATES are in the text portion of WINDOW,\n\
370 the coordinates relative to the window are returned.\n\
e5d77022 371If they are in the mode line of WINDOW, `mode-line' is returned.\n\
d5783c40 372If they are on the border between WINDOW and its right sibling,\n\
e5d77022 373 `vertical-line' is returned.")
d5783c40
JB
374 (coordinates, window)
375 register Lisp_Object coordinates, window;
376{
377 int x, y;
378
605be8af 379 CHECK_LIVE_WINDOW (window, 0);
d5783c40
JB
380 CHECK_CONS (coordinates, 1);
381 x = XINT (Fcar (coordinates));
382 y = XINT (Fcdr (coordinates));
383
384 switch (coordinates_in_window (XWINDOW (window), &x, &y))
385 {
386 case 0: /* NOT in window at all. */
387 return Qnil;
388
389 case 1: /* In text part of window. */
390 return Fcons (x, y);
391
392 case 2: /* In mode line of window. */
393 return Qmode_line;
394
395 case 3: /* On right border of window. */
e5d77022 396 return Qvertical_line;
d5783c40
JB
397
398 default:
399 abort ();
400 }
401}
402
7ab12479 403/* Find the window containing column x, row y, and return it as a
d5783c40
JB
404 Lisp_Object. If x, y is on the window's modeline, set *part
405 to 1; if it is on the separating line between the window and its
406 right sibling, set it to 2; otherwise set it to 0. If there is no
407 window under x, y return nil and leave *part unmodified. */
7ab12479 408Lisp_Object
44fa5b1e
JB
409window_from_coordinates (frame, x, y, part)
410 FRAME_PTR frame;
7ab12479 411 int x, y;
d5783c40 412 int *part;
7ab12479
JB
413{
414 register Lisp_Object tem, first;
415
44fa5b1e 416 tem = first = FRAME_SELECTED_WINDOW (frame);
7ab12479 417
d5783c40 418 do
7ab12479
JB
419 {
420 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
421
422 if (found)
423 {
d5783c40 424 *part = found - 1;
7ab12479
JB
425 return tem;
426 }
427
d5783c40 428 tem = Fnext_window (tem, Qt, Qlambda);
7ab12479 429 }
d5783c40
JB
430 while (! EQ (tem, first));
431
432 return Qnil;
7ab12479
JB
433}
434
ab17c3f2 435DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
b0c33a94 436 "Return window containing coordinates X and Y on FRAME.\n\
44fa5b1e
JB
437If omitted, FRAME defaults to the currently selected frame.\n\
438The top left corner of the frame is considered to be row 0,\n\
95605e15 439column 0.")
b0c33a94
RS
440 (x, y, frame)
441 Lisp_Object x, y, frame;
7ab12479
JB
442{
443 int part;
444
4b206065 445#ifdef MULTI_FRAME
44fa5b1e
JB
446 if (NILP (frame))
447 XSET (frame, Lisp_Frame, selected_frame);
d5783c40 448 else
44fa5b1e 449 CHECK_LIVE_FRAME (frame, 2);
4b206065 450#endif
b0c33a94
RS
451 CHECK_NUMBER (x, 0);
452 CHECK_NUMBER (y, 1);
7ab12479 453
44fa5b1e 454 return window_from_coordinates (XFRAME (frame),
b0c33a94 455 XINT (x), XINT (y),
7ab12479
JB
456 &part);
457}
458
459DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
460 "Return current value of point in WINDOW.\n\
461For a nonselected window, this is the value point would have\n\
462if that window were selected.\n\
463\n\
464Note that, when WINDOW is the selected window and its buffer\n\
465is also currently selected, the value returned is the same as (point).\n\
466It would be more strictly correct to return the `top-level' value\n\
467of point, outside of any save-excursion forms.\n\
468But that is hard to define.")
469 (window)
470 Lisp_Object window;
471{
472 register struct window *w = decode_window (window);
473
474 if (w == XWINDOW (selected_window)
475 && current_buffer == XBUFFER (w->buffer))
476 return Fpoint ();
477 return Fmarker_position (w->pointm);
478}
479
480DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
481 "Return position at which display currently starts in WINDOW.")
482 (window)
483 Lisp_Object window;
484{
485 return Fmarker_position (decode_window (window)->start);
486}
487
488DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
489 "Return position at which display currently ends in WINDOW.")
490 (window)
491 Lisp_Object window;
492{
493 Lisp_Object value;
494 struct window *w = decode_window (window);
5a41ab94
RS
495 Lisp_Object buf;
496
497 buf = w->buffer;
498 CHECK_BUFFER (buf, 0);
499
7ab12479 500 XSET (value, Lisp_Int,
5a41ab94 501 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
7ab12479
JB
502
503 return value;
504}
505
506DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
507 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
508 (window, pos)
509 Lisp_Object window, pos;
510{
511 register struct window *w = decode_window (window);
512
513 CHECK_NUMBER_COERCE_MARKER (pos, 1);
514 if (w == XWINDOW (selected_window))
515 Fgoto_char (pos);
516 else
517 set_marker_restricted (w->pointm, pos, w->buffer);
518
519 return pos;
520}
521
522DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
523 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
524Optional third arg NOFORCE non-nil inhibits next redisplay\n\
525from overriding motion of point in order to display at this exact start.")
526 (window, pos, noforce)
527 Lisp_Object window, pos, noforce;
528{
529 register struct window *w = decode_window (window);
530
531 CHECK_NUMBER_COERCE_MARKER (pos, 1);
532 set_marker_restricted (w->start, pos, w->buffer);
533 /* this is not right, but much easier than doing what is right. */
534 w->start_at_line_beg = Qnil;
265a9e55 535 if (NILP (noforce))
7ab12479
JB
536 w->force_start = Qt;
537 w->update_mode_line = Qt;
538 XFASTINT (w->last_modified) = 0;
62c07cc7
JB
539 if (!EQ (window, selected_window))
540 windows_or_buffers_changed++;
7ab12479
JB
541 return pos;
542}
543
544DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
545 1, 1, 0,
546 "Return WINDOW's dedicated object, usually t or nil.\n\
1f18c48f 547See also `set-window-dedicated-p'.")
7ab12479
JB
548 (window)
549 Lisp_Object window;
550{
551 return decode_window (window)->dedicated;
552}
553
d207b766
RS
554DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
555 Sset_window_dedicated_p, 2, 2, 0,
556 "Control whether WINDOW is dedicated to the buffer it displays.\n\
557If it is dedicated, Emacs will not automatically change\n\
558which buffer appears in it.\n\
559The second argument is the new value for the dedication flag;\n\
560non-nil means yes.")
7ab12479
JB
561 (window, arg)
562 Lisp_Object window, arg;
563{
564 register struct window *w = decode_window (window);
565
265a9e55 566 if (NILP (arg))
7ab12479
JB
567 w->dedicated = Qnil;
568 else
d207b766 569 w->dedicated = Qt;
7ab12479
JB
570
571 return w->dedicated;
572}
573
574DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
575 0, 1, 0,
576 "Return the display-table that WINDOW is using.")
577 (window)
578 Lisp_Object window;
579{
580 return decode_window (window)->display_table;
581}
582
583/* Get the display table for use currently on window W.
584 This is either W's display table or W's buffer's display table.
585 Ignore the specified tables if they are not valid;
586 if no valid table is specified, return 0. */
587
588struct Lisp_Vector *
589window_display_table (w)
590 struct window *w;
591{
592 Lisp_Object tem;
593 tem = w->display_table;
594 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
595 return XVECTOR (tem);
596 tem = XBUFFER (w->buffer)->display_table;
597 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
598 return XVECTOR (tem);
599 tem = Vstandard_display_table;
600 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
601 return XVECTOR (tem);
602 return 0;
603}
604
3a2712f9 605DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
7ab12479
JB
606 "Set WINDOW's display-table to TABLE.")
607 (window, table)
608 register Lisp_Object window, table;
609{
610 register struct window *w;
611 register Lisp_Object z; /* Return value. */
612
613 w = decode_window (window);
614 w->display_table = table;
615 return table;
616}
617\f
618/* Record info on buffer window w is displaying
619 when it is about to cease to display that buffer. */
620static
621unshow_buffer (w)
622 register struct window *w;
623{
12cae7c0 624 Lisp_Object buf;
7ab12479 625
12cae7c0 626 buf = w->buffer;
7ab12479
JB
627 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
628 abort ();
629
573f41ab 630#if 0
7ab12479
JB
631 if (w == XWINDOW (selected_window)
632 || ! EQ (buf, XWINDOW (selected_window)->buffer))
633 /* Do this except when the selected window's buffer
634 is being removed from some other window. */
573f41ab
RS
635#endif
636 /* last_window_start records the start position that this buffer
637 had in the last window to be disconnected from it.
638 Now that this statement is unconditional,
639 it is possible for the buffer to be displayed in the
640 selected window, while last_window_start reflects another
641 window which was recently showing the same buffer.
642 Some people might say that might be a good thing. Let's see. */
7ab12479
JB
643 XBUFFER (buf)->last_window_start = marker_position (w->start);
644
645 /* Point in the selected window's buffer
646 is actually stored in that buffer, and the window's pointm isn't used.
647 So don't clobber point in that buffer. */
648 if (! EQ (buf, XWINDOW (selected_window)->buffer))
649 BUF_PT (XBUFFER (buf))
650 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
651 marker_position (w->pointm),
652 BUF_ZV (XBUFFER (buf)));
653}
654
655/* Put replacement into the window structure in place of old. */
656static
657replace_window (old, replacement)
658 Lisp_Object old, replacement;
659{
660 register Lisp_Object tem;
661 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
662
44fa5b1e
JB
663 /* If OLD is its frame's root_window, then replacement is the new
664 root_window for that frame. */
7ab12479 665
7f4161e0 666 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
44fa5b1e 667 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
7ab12479
JB
668
669 p->left = o->left;
670 p->top = o->top;
671 p->width = o->width;
672 p->height = o->height;
673
674 p->next = tem = o->next;
265a9e55 675 if (!NILP (tem))
7ab12479
JB
676 XWINDOW (tem)->prev = replacement;
677
678 p->prev = tem = o->prev;
265a9e55 679 if (!NILP (tem))
7ab12479
JB
680 XWINDOW (tem)->next = replacement;
681
682 p->parent = tem = o->parent;
265a9e55 683 if (!NILP (tem))
7ab12479
JB
684 {
685 if (EQ (XWINDOW (tem)->vchild, old))
686 XWINDOW (tem)->vchild = replacement;
687 if (EQ (XWINDOW (tem)->hchild, old))
688 XWINDOW (tem)->hchild = replacement;
689 }
690
691/*** Here, if replacement is a vertical combination
692and so is its new parent, we should make replacement's
693children be children of that parent instead. ***/
694}
695
696DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
697 "Remove WINDOW from the display. Default is selected window.")
698 (window)
699 register Lisp_Object window;
700{
701 register Lisp_Object tem, parent, sib;
702 register struct window *p;
703 register struct window *par;
704
605be8af
JB
705 /* Because this function is called by other C code on non-leaf
706 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
707 so we can't decode_window here. */
265a9e55 708 if (NILP (window))
7ab12479
JB
709 window = selected_window;
710 else
711 CHECK_WINDOW (window, 0);
7ab12479 712 p = XWINDOW (window);
605be8af
JB
713
714 /* It's okay to delete an already-deleted window. */
715 if (NILP (p->buffer)
716 && NILP (p->hchild)
717 && NILP (p->vchild))
718 return Qnil;
719
7ab12479 720 parent = p->parent;
265a9e55 721 if (NILP (parent))
7ab12479
JB
722 error ("Attempt to delete minibuffer or sole ordinary window");
723 par = XWINDOW (parent);
724
725 windows_or_buffers_changed++;
726
605be8af
JB
727 /* Are we trying to delete any frame's selected window? */
728 {
0def0403 729 Lisp_Object frame, pwindow;
605be8af 730
0def0403
RS
731 /* See if the frame's selected window is either WINDOW
732 or any subwindow of it, by finding all that window's parents
733 and comparing each one with WINDOW. */
734 frame = WINDOW_FRAME (XWINDOW (window));
735 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
736
737 while (!NILP (pwindow))
738 {
739 if (EQ (window, pwindow))
740 break;
741 pwindow = XWINDOW (pwindow)->parent;
742 }
743
744 if (EQ (window, pwindow))
605be8af 745 {
89bca612
RS
746 Lisp_Object alternative;
747 alternative = Fnext_window (window, Qlambda, Qnil);
605be8af
JB
748
749 /* If we're about to delete the selected window on the
750 selected frame, then we should use Fselect_window to select
751 the new window. On the other hand, if we're about to
752 delete the selected window on any other frame, we shouldn't do
753 anything but set the frame's selected_window slot. */
754 if (EQ (window, selected_window))
755 Fselect_window (alternative);
756 else
0def0403 757 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
605be8af
JB
758 }
759 }
7ab12479
JB
760
761 tem = p->buffer;
762 /* tem is null for dummy parent windows
763 (which have inferiors but not any contents themselves) */
265a9e55 764 if (!NILP (tem))
7ab12479
JB
765 {
766 unshow_buffer (p);
767 unchain_marker (p->pointm);
768 unchain_marker (p->start);
7ab12479
JB
769 }
770
771 tem = p->next;
265a9e55 772 if (!NILP (tem))
7ab12479
JB
773 XWINDOW (tem)->prev = p->prev;
774
775 tem = p->prev;
265a9e55 776 if (!NILP (tem))
7ab12479
JB
777 XWINDOW (tem)->next = p->next;
778
779 if (EQ (window, par->hchild))
780 par->hchild = p->next;
781 if (EQ (window, par->vchild))
782 par->vchild = p->next;
783
784 /* Find one of our siblings to give our space to. */
785 sib = p->prev;
265a9e55 786 if (NILP (sib))
7ab12479
JB
787 {
788 /* If p gives its space to its next sibling, that sibling needs
789 to have its top/left side pulled back to where p's is.
790 set_window_{height,width} will re-position the sibling's
791 children. */
792 sib = p->next;
7f4161e0
JB
793 XWINDOW (sib)->top = p->top;
794 XWINDOW (sib)->left = p->left;
7ab12479
JB
795 }
796
797 /* Stretch that sibling. */
265a9e55 798 if (!NILP (par->vchild))
7ab12479
JB
799 set_window_height (sib,
800 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
801 1);
265a9e55 802 if (!NILP (par->hchild))
7ab12479
JB
803 set_window_width (sib,
804 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
805 1);
806
807 /* If parent now has only one child,
808 put the child into the parent's place. */
7ab12479 809 tem = par->hchild;
265a9e55 810 if (NILP (tem))
7ab12479 811 tem = par->vchild;
265a9e55 812 if (NILP (XWINDOW (tem)->next))
7ab12479 813 replace_window (parent, tem);
605be8af
JB
814
815 /* Since we may be deleting combination windows, we must make sure that
816 not only p but all its children have been marked as deleted. */
817 if (! NILP (p->hchild))
818 delete_all_subwindows (XWINDOW (p->hchild));
819 else if (! NILP (p->vchild))
820 delete_all_subwindows (XWINDOW (p->vchild));
821
822 /* Mark this window as deleted. */
823 p->buffer = p->hchild = p->vchild = Qnil;
824
7ab12479
JB
825 return Qnil;
826}
827\f
7ab12479 828
44fa5b1e 829extern Lisp_Object next_frame (), prev_frame ();
7ab12479 830
26f6279d
JB
831/* This comment supplies the doc string for `next-window',
832 for make-docfile to see. We cannot put this in the real DEFUN
833 due to limits in the Unix cpp.
834
835DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
7ab12479 836 "Return next window after WINDOW in canonical ordering of windows.\n\
d5783c40
JB
837If omitted, WINDOW defaults to the selected window.\n\
838\n\
839Optional second arg MINIBUF t means count the minibuffer window even\n\
840if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
841it is active. MINIBUF neither t nor nil means not to count the\n\
842minibuffer even if it is active.\n\
843\n\
44fa5b1e
JB
844Several frames may share a single minibuffer; if the minibuffer\n\
845counts, all windows on all frames that share that minibuffer count\n\
ed160f1f 846too. Therefore, `next-window' can be used to iterate through the\n\
44fa5b1e
JB
847set of windows even when the minibuffer is on another frame. If the\n\
848minibuffer does not count, only windows from WINDOW's frame count.\n\
d5783c40 849\n\
44fa5b1e
JB
850Optional third arg ALL-FRAMES t means include windows on all frames.\n\
851ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
89bca612 852above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
f812f9c6 853ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
89bca612 854Anything else means restrict to WINDOW's frame.\n\
dbc4e1c1
JB
855\n\
856If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
857`next-window' to iterate through the entire cycle of acceptable\n\
858windows, eventually ending up back at the window you started with.\n\
859`previous-window' traverses the same cycle, in the reverse order.")
26f6279d
JB
860 (window, minibuf, all_frames) */
861
862DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
863 0)
44fa5b1e
JB
864 (window, minibuf, all_frames)
865 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
866{
867 register Lisp_Object tem;
d5783c40 868 Lisp_Object start_window;
7ab12479 869
265a9e55 870 if (NILP (window))
7ab12479
JB
871 window = selected_window;
872 else
605be8af 873 CHECK_LIVE_WINDOW (window, 0);
7ab12479 874
d5783c40
JB
875 start_window = window;
876
877 /* minibuf == nil may or may not include minibuffers.
878 Decide if it does. */
265a9e55 879 if (NILP (minibuf))
d5783c40
JB
880 minibuf = (minibuf_level ? Qt : Qlambda);
881
c6e73093 882#ifdef MULTI_FRAME
44fa5b1e
JB
883 /* all_frames == nil doesn't specify which frames to include.
884 Decide which frames it includes. */
885 if (NILP (all_frames))
886 all_frames = (EQ (minibuf, Qt)
887 ? (FRAME_MINIBUF_WINDOW
888 (XFRAME
889 (WINDOW_FRAME
d5783c40
JB
890 (XWINDOW (window)))))
891 : Qnil);
89bca612
RS
892 else if (EQ (all_frames, Qvisible))
893 ;
f812f9c6
RS
894 else if (XFASTINT (all_frames) == 0)
895 ;
44fa5b1e
JB
896 else if (! EQ (all_frames, Qt))
897 all_frames = Qnil;
644b477c
RS
898 /* Now all_frames is t meaning search all frames,
899 nil meaning search just current frame,
f812f9c6
RS
900 visible meaning search just visible frames,
901 0 meaning search visible and iconified frames,
644b477c 902 or a window, meaning search the frame that window belongs to. */
c6e73093 903#endif
7ab12479
JB
904
905 /* Do this loop at least once, to get the next window, and perhaps
906 again, if we hit the minibuffer and that is not acceptable. */
907 do
908 {
909 /* Find a window that actually has a next one. This loop
910 climbs up the tree. */
265a9e55
JB
911 while (tem = XWINDOW (window)->next, NILP (tem))
912 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 913 window = tem;
d5783c40 914 else
7ab12479 915 {
44fa5b1e
JB
916 /* We've reached the end of this frame.
917 Which other frames are acceptable? */
918 tem = WINDOW_FRAME (XWINDOW (window));
919#ifdef MULTI_FRAME
920 if (! NILP (all_frames))
921 tem = next_frame (tem, all_frames);
7ab12479 922#endif
44fa5b1e 923 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 924
7ab12479
JB
925 break;
926 }
927
928 window = tem;
d5783c40 929
7ab12479
JB
930 /* If we're in a combination window, find its first child and
931 recurse on that. Otherwise, we've found the window we want. */
932 while (1)
933 {
265a9e55 934 if (!NILP (XWINDOW (window)->hchild))
7ab12479 935 window = XWINDOW (window)->hchild;
265a9e55 936 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
937 window = XWINDOW (window)->vchild;
938 else break;
939 }
940 }
d5783c40
JB
941 /* Which windows are acceptible?
942 Exit the loop and accept this window if
7ab12479 943 this isn't a minibuffer window, or
d5783c40
JB
944 we're accepting minibuffer windows, or
945 we've come all the way around and we're back at the original window. */
7ab12479 946 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 947 && ! EQ (minibuf, Qt)
7f4161e0 948 && ! EQ (window, start_window));
7ab12479
JB
949
950 return window;
951}
952
26f6279d
JB
953/* This comment supplies the doc string for `previous-window',
954 for make-docfile to see. We cannot put this in the real DEFUN
955 due to limits in the Unix cpp.
956
957DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
d5783c40
JB
958 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
959If omitted, WINDOW defaults to the selected window.\n\
960\n\
961Optional second arg MINIBUF t means count the minibuffer window even\n\
962if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
963it is active. MINIBUF neither t nor nil means not to count the\n\
964minibuffer even if it is active.\n\
965\n\
44fa5b1e
JB
966Several frames may share a single minibuffer; if the minibuffer\n\
967counts, all windows on all frames that share that minibuffer count\n\
ed160f1f 968too. Therefore, `previous-window' can be used to iterate through\n\
44fa5b1e 969the set of windows even when the minibuffer is on another frame. If\n\
ed160f1f 970the minibuffer does not count, only windows from WINDOW's frame count\n\
d5783c40 971\n\
44fa5b1e
JB
972Optional third arg ALL-FRAMES t means include windows on all frames.\n\
973ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
89bca612 974above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
f812f9c6 975ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
89bca612 976Anything else means restrict to WINDOW's frame.\n\
dbc4e1c1
JB
977\n\
978If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
979`previous-window' to iterate through the entire cycle of acceptable\n\
980windows, eventually ending up back at the window you started with.\n\
981`next-window' traverses the same cycle, in the reverse order.")
26f6279d
JB
982 (window, minibuf, all_frames) */
983
984
985DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
986 0)
44fa5b1e
JB
987 (window, minibuf, all_frames)
988 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
989{
990 register Lisp_Object tem;
d5783c40 991 Lisp_Object start_window;
7ab12479 992
265a9e55 993 if (NILP (window))
7ab12479
JB
994 window = selected_window;
995 else
605be8af 996 CHECK_LIVE_WINDOW (window, 0);
7ab12479 997
d5783c40
JB
998 start_window = window;
999
1000 /* minibuf == nil may or may not include minibuffers.
1001 Decide if it does. */
265a9e55 1002 if (NILP (minibuf))
d5783c40
JB
1003 minibuf = (minibuf_level ? Qt : Qlambda);
1004
c6e73093 1005#ifdef MULTI_FRAME
44fa5b1e
JB
1006 /* all_frames == nil doesn't specify which frames to include.
1007 Decide which frames it includes. */
1008 if (NILP (all_frames))
1009 all_frames = (EQ (minibuf, Qt)
1010 ? (FRAME_MINIBUF_WINDOW
1011 (XFRAME
1012 (WINDOW_FRAME
d5783c40
JB
1013 (XWINDOW (window)))))
1014 : Qnil);
89bca612
RS
1015 else if (EQ (all_frames, Qvisible))
1016 ;
f812f9c6
RS
1017 else if (XFASTINT (all_frames) == 0)
1018 ;
44fa5b1e
JB
1019 else if (! EQ (all_frames, Qt))
1020 all_frames = Qnil;
644b477c
RS
1021 /* Now all_frames is t meaning search all frames,
1022 nil meaning search just current frame,
f812f9c6
RS
1023 visible meaning search just visible frames,
1024 0 meaning search visible and iconified frames,
644b477c 1025 or a window, meaning search the frame that window belongs to. */
c6e73093 1026#endif
7ab12479
JB
1027
1028 /* Do this loop at least once, to get the previous window, and perhaps
1029 again, if we hit the minibuffer and that is not acceptable. */
1030 do
1031 {
1032 /* Find a window that actually has a previous one. This loop
1033 climbs up the tree. */
265a9e55
JB
1034 while (tem = XWINDOW (window)->prev, NILP (tem))
1035 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 1036 window = tem;
d5783c40 1037 else
7ab12479 1038 {
44fa5b1e
JB
1039 /* We have found the top window on the frame.
1040 Which frames are acceptable? */
1041 tem = WINDOW_FRAME (XWINDOW (window));
1042#ifdef MULTI_FRAME
1043 if (! NILP (all_frames))
dbc4e1c1
JB
1044 /* It's actually important that we use prev_frame here,
1045 rather than next_frame. All the windows acceptable
1046 according to the given parameters should form a ring;
1047 Fnext_window and Fprevious_window should go back and
1048 forth around the ring. If we use next_frame here,
1049 then Fnext_window and Fprevious_window take different
1050 paths through the set of acceptable windows.
1051 window_loop assumes that these `ring' requirement are
1052 met. */
1053 tem = prev_frame (tem, all_frames);
7ab12479 1054#endif
644b477c
RS
1055 /* If this frame has a minibuffer, find that window first,
1056 because it is conceptually the last window in that frame. */
5e12e32f
JB
1057 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1058 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1059 else
644b477c 1060 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 1061
7ab12479
JB
1062 break;
1063 }
1064
1065 window = tem;
1066 /* If we're in a combination window, find its last child and
1067 recurse on that. Otherwise, we've found the window we want. */
1068 while (1)
1069 {
265a9e55 1070 if (!NILP (XWINDOW (window)->hchild))
7ab12479 1071 window = XWINDOW (window)->hchild;
265a9e55 1072 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
1073 window = XWINDOW (window)->vchild;
1074 else break;
265a9e55 1075 while (tem = XWINDOW (window)->next, !NILP (tem))
7ab12479
JB
1076 window = tem;
1077 }
1078 }
d5783c40
JB
1079 /* Which windows are acceptable?
1080 Exit the loop and accept this window if
7ab12479 1081 this isn't a minibuffer window, or
d5783c40
JB
1082 we're accepting minibuffer windows, or
1083 we've come all the way around and we're back at the original window. */
7ab12479 1084 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 1085 && !EQ (minibuf, Qt)
7f4161e0 1086 && !EQ (window, start_window));
7ab12479
JB
1087
1088 return window;
1089}
1090
62c07cc7 1091DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
44fa5b1e
JB
1092 "Select the ARG'th different window on this frame.\n\
1093All windows on current frame are arranged in a cyclic order.\n\
7ab12479
JB
1094This command selects the window ARG steps away in that order.\n\
1095A negative ARG moves in the opposite order. If the optional second\n\
44fa5b1e
JB
1096argument ALL_FRAMES is non-nil, cycle through all frames.")
1097 (n, all_frames)
1098 register Lisp_Object n, all_frames;
7ab12479
JB
1099{
1100 register int i;
1101 register Lisp_Object w;
1102
1103 CHECK_NUMBER (n, 0);
1104 w = selected_window;
1105 i = XINT (n);
1106
1107 while (i > 0)
1108 {
44fa5b1e 1109 w = Fnext_window (w, Qnil, all_frames);
7ab12479
JB
1110 i--;
1111 }
1112 while (i < 0)
1113 {
44fa5b1e 1114 w = Fprevious_window (w, Qnil, all_frames);
7ab12479
JB
1115 i++;
1116 }
1117 Fselect_window (w);
1118 return Qnil;
1119}
1120\f
1121/* Look at all windows, performing an operation specified by TYPE
1122 with argument OBJ.
75d8f668 1123 If FRAMES is Qt, look at all frames;
75d8f668 1124 Qnil, look at just the selected frame;
89bca612 1125 Qvisible, look at visible frames;
75d8f668 1126 a frame, just look at windows on that frame.
7ab12479
JB
1127 If MINI is non-zero, perform the operation on minibuffer windows too.
1128*/
1129
1130enum window_loop
1131{
1132 WINDOW_LOOP_UNUSED,
1133 GET_BUFFER_WINDOW, /* Arg is buffer */
1134 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1135 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1136 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1137 GET_LARGEST_WINDOW,
a68c0d3b 1138 UNSHOW_BUFFER /* Arg is buffer */
7ab12479
JB
1139};
1140
1141static Lisp_Object
44fa5b1e 1142window_loop (type, obj, mini, frames)
7ab12479 1143 enum window_loop type;
44fa5b1e 1144 register Lisp_Object obj, frames;
7ab12479
JB
1145 int mini;
1146{
1147 register Lisp_Object w;
1148 register Lisp_Object best_window;
1149 register Lisp_Object next_window;
4b206065 1150 register Lisp_Object last_window;
44fa5b1e 1151 FRAME_PTR frame;
89bca612
RS
1152 Lisp_Object frame_arg;
1153 frame_arg = Qt;
44fa5b1e 1154
4b206065 1155#ifdef MULTI_FRAME
44fa5b1e
JB
1156 /* If we're only looping through windows on a particular frame,
1157 frame points to that frame. If we're looping through windows
1158 on all frames, frame is 0. */
1159 if (FRAMEP (frames))
1160 frame = XFRAME (frames);
1161 else if (NILP (frames))
1162 frame = selected_frame;
7ab12479 1163 else
44fa5b1e 1164 frame = 0;
89bca612
RS
1165 if (frame)
1166 frame_arg = Qlambda;
f812f9c6
RS
1167 else if (XFASTINT (frames) == 0)
1168 frame_arg = frames;
89bca612
RS
1169 else if (EQ (frames, Qvisible))
1170 frame_arg = frames;
4b206065
JB
1171#else
1172 frame = 0;
1173#endif
7ab12479 1174
89bca612
RS
1175 /* frame_arg is Qlambda to stick to one frame,
1176 Qvisible to consider all visible frames,
1177 or Qt otherwise. */
1178
7ab12479
JB
1179 /* Pick a window to start with. */
1180 if (XTYPE (obj) == Lisp_Window)
4b206065 1181 w = obj;
44fa5b1e 1182 else if (frame)
4b206065 1183 w = FRAME_SELECTED_WINDOW (frame);
7ab12479 1184 else
4b206065
JB
1185 w = FRAME_SELECTED_WINDOW (selected_frame);
1186
1187 /* Figure out the last window we're going to mess with. Since
1188 Fnext_window, given the same options, is guaranteed to go in a
1189 ring, we can just use Fprevious_window to find the last one.
1190
1191 We can't just wait until we hit the first window again, because
1192 it might be deleted. */
1193
89bca612 1194 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1195
7ab12479 1196 best_window = Qnil;
4b206065 1197 for (;;)
7ab12479 1198 {
75d8f668
JB
1199 FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1200
7ab12479
JB
1201 /* Pick the next window now, since some operations will delete
1202 the current window. */
89bca612 1203 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1204
d29a5631
RS
1205 /* Note that we do not pay attention here to whether
1206 the frame is visible, since Fnext_window skips non-visible frames
1207 if that is desired, under the control of frame_arg. */
75d8f668 1208 if (! MINI_WINDOW_P (XWINDOW (w))
7ab12479
JB
1209 || (mini && minibuf_level > 0))
1210 switch (type)
1211 {
1212 case GET_BUFFER_WINDOW:
7ab12479
JB
1213 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1214 return w;
1215 break;
1216
1217 case GET_LRU_WINDOW:
1218 /* t as arg means consider only full-width windows */
e5d77022 1219 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
a2db42d6 1220 != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
7ab12479 1221 break;
7ab12479
JB
1222 /* Ignore dedicated windows and minibuffers. */
1223 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1224 || !NILP (XWINDOW (w)->dedicated))
7ab12479 1225 break;
265a9e55 1226 if (NILP (best_window)
7ab12479
JB
1227 || (XFASTINT (XWINDOW (best_window)->use_time)
1228 > XFASTINT (XWINDOW (w)->use_time)))
1229 best_window = w;
1230 break;
1231
1232 case DELETE_OTHER_WINDOWS:
1233 if (XWINDOW (w) != XWINDOW (obj))
1234 Fdelete_window (w);
1235 break;
1236
1237 case DELETE_BUFFER_WINDOWS:
1238 if (EQ (XWINDOW (w)->buffer, obj))
1239 {
1240 /* If we're deleting the buffer displayed in the only window
44fa5b1e 1241 on the frame, find a new buffer to display there. */
265a9e55 1242 if (NILP (XWINDOW (w)->parent))
7ab12479 1243 {
12cae7c0
KH
1244 Lisp_Object new_buffer;
1245 new_buffer = Fother_buffer (obj, Qnil);
265a9e55 1246 if (NILP (new_buffer))
7ab12479
JB
1247 new_buffer
1248 = Fget_buffer_create (build_string ("*scratch*"));
1249 Fset_window_buffer (w, new_buffer);
d895abb0
RS
1250 if (EQ (w, selected_window))
1251 Fset_buffer (XWINDOW (w)->buffer);
7ab12479
JB
1252 }
1253 else
1254 Fdelete_window (w);
1255 }
1256 break;
1257
1258 case GET_LARGEST_WINDOW:
7ab12479
JB
1259 /* Ignore dedicated windows and minibuffers. */
1260 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1261 || !NILP (XWINDOW (w)->dedicated))
7ab12479
JB
1262 break;
1263 {
1264 struct window *best_window_ptr = XWINDOW (best_window);
1265 struct window *w_ptr = XWINDOW (w);
6b54027b
RS
1266 if (NILP (best_window)
1267 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
1268 > (XFASTINT (best_window_ptr->height)
1269 * XFASTINT (best_window_ptr->width))))
7ab12479
JB
1270 best_window = w;
1271 }
1272 break;
1273
1274 case UNSHOW_BUFFER:
1275 if (EQ (XWINDOW (w)->buffer, obj))
1276 {
1277 /* Find another buffer to show in this window. */
12cae7c0 1278 Lisp_Object another_buffer;
38ab08d1 1279 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
12cae7c0 1280 another_buffer = Fother_buffer (obj, Qnil);
265a9e55 1281 if (NILP (another_buffer))
7ab12479
JB
1282 another_buffer
1283 = Fget_buffer_create (build_string ("*scratch*"));
38ab08d1
RS
1284#ifdef MULTI_FRAME
1285 /* If this window is dedicated, and in a frame of its own,
1286 kill the frame. */
1287 if (EQ (w, FRAME_ROOT_WINDOW (f))
596122a7 1288 && !NILP (XWINDOW (w)->dedicated)
38ab08d1
RS
1289 && other_visible_frames (f))
1290 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1291 else
1292#endif
1293 {
1294 /* Otherwise show a different buffer in the window. */
1295 XWINDOW (w)->dedicated = Qnil;
1296 Fset_window_buffer (w, another_buffer);
1297 if (EQ (w, selected_window))
1298 Fset_buffer (XWINDOW (w)->buffer);
1299 }
7ab12479
JB
1300 }
1301 break;
1302 }
4b206065
JB
1303
1304 if (EQ (w, last_window))
1305 break;
1306
7ab12479
JB
1307 w = next_window;
1308 }
7ab12479
JB
1309
1310 return best_window;
1311}
605be8af 1312
7ab12479
JB
1313DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1314 "Return the window least recently selected or used for display.\n\
89bca612
RS
1315If optional argument FRAME is `visible', search all visible frames.\n\
1316If FRAME is t, search all frames.\n\
1317If FRAME is nil, search only the selected frame.\n\
1318If FRAME is a frame, search only that frame.")
1319 (frame)
1320 Lisp_Object frame;
7ab12479
JB
1321{
1322 register Lisp_Object w;
1323 /* First try for a window that is full-width */
89bca612 1324 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
265a9e55 1325 if (!NILP (w) && !EQ (w, selected_window))
7ab12479
JB
1326 return w;
1327 /* If none of them, try the rest */
89bca612 1328 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
7ab12479
JB
1329}
1330
1331DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1332 "Return the largest window in area.\n\
89bca612
RS
1333If optional argument FRAME is `visible', search all visible frames.\n\
1334If FRAME is t, search all frames.\n\
1335If FRAME is nil, search only the selected frame.\n\
1336If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1337 (frame)
1338 Lisp_Object frame;
7ab12479
JB
1339{
1340 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
44fa5b1e 1341 frame);
7ab12479
JB
1342}
1343
1344DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1345 "Return a window currently displaying BUFFER, or nil if none.\n\
89bca612 1346If optional argument FRAME is `visible', search all visible frames.\n\
f812f9c6 1347If optional argument FRAME is 0, search all visible and iconified frames.\n\
89bca612 1348If FRAME is t, search all frames.\n\
1bc981d2 1349If FRAME is nil, search only the selected frame.\n\
89bca612 1350If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1351 (buffer, frame)
1352 Lisp_Object buffer, frame;
7ab12479
JB
1353{
1354 buffer = Fget_buffer (buffer);
1355 if (XTYPE (buffer) == Lisp_Buffer)
44fa5b1e 1356 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
7ab12479
JB
1357 else
1358 return Qnil;
1359}
1360
1361DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1362 0, 1, "",
44fa5b1e 1363 "Make WINDOW (or the selected window) fill its frame.\n\
f16a1ed3
RS
1364Only the frame WINDOW is on is affected.\n\
1365This function tries to reduce display jumps\n\
1366by keeping the text previously visible in WINDOW\n\
1367in the same place on the frame. Doing this depends on\n\
1368the value of (window-start WINDOW), so if calling this function\n\
1369in a program gives strange scrolling, make sure the window-start\n\
1370value is reasonable when this function is called.")
7ab12479
JB
1371 (window)
1372 Lisp_Object window;
1373{
1374 struct window *w;
00d3d838 1375 int startpos;
7ab12479
JB
1376 int top;
1377
265a9e55 1378 if (NILP (window))
7ab12479
JB
1379 window = selected_window;
1380 else
605be8af 1381 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1382
1383 w = XWINDOW (window);
00d3d838
KH
1384 startpos = marker_position (w->start);
1385 top = XFASTINT (w->top) - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)));
7ab12479 1386
70728a80 1387 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
7ab12479 1388
00d3d838
KH
1389 /* Try to minimize scrolling, by setting the window start to the point
1390 will cause the text at the old window start to be at the same place
1391 on the frame. But don't try to do this if the window start is
1392 outside the visible portion (as might happen when the display is
1393 not current, due to typeahead). */
1394 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1395 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1396 {
1397 struct position pos;
1398 struct buffer *obuf = current_buffer;
1399
1400 Fset_buffer (w->buffer);
1401 /* This computation used to temporarily move point, but that can
1402 have unwanted side effects due to text properties. */
1403 pos = *vmotion (startpos, -top, window_internal_width (w) - 1,
1404 XINT (w->hscroll), window);
1405 Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
1406 w->start_at_line_beg = ((pos.bufpos == BEGV
1407 || FETCH_CHAR (pos.bufpos - 1) == '\n') ? Qt
1408 : Qnil);
1409
1410 set_buffer_internal (obuf);
1411 }
7ab12479
JB
1412 return Qnil;
1413}
1414
1415DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
3cbbb729 1416 1, 2, "bDelete windows on (buffer): ",
26f6279d
JB
1417 "Delete all windows showing BUFFER.\n\
1418Optional second argument FRAME controls which frames are affected.\n\
1419If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1420If t, delete only windows showing BUFFER in the selected frame.\n\
89bca612 1421If `visible', delete all windows showing BUFFER in any visible frame.\n\
26f6279d
JB
1422If a frame, delete only windows showing BUFFER in that frame.")
1423 (buffer, frame)
1424 Lisp_Object buffer, frame;
7ab12479 1425{
26f6279d
JB
1426#ifdef MULTI_FRAME
1427 /* FRAME uses t and nil to mean the opposite of what window_loop
1428 expects. */
1429 if (! FRAMEP (frame))
1430 frame = NILP (frame) ? Qt : Qnil;
1431#else
1432 frame = Qt;
1433#endif
1434
265a9e55 1435 if (!NILP (buffer))
7ab12479
JB
1436 {
1437 buffer = Fget_buffer (buffer);
1438 CHECK_BUFFER (buffer, 0);
26f6279d 1439 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
7ab12479
JB
1440 }
1441 return Qnil;
1442}
1443
1444DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1445 Sreplace_buffer_in_windows,
1446 1, 1, "bReplace buffer in windows: ",
1447 "Replace BUFFER with some other buffer in all windows showing it.")
1448 (buffer)
1449 Lisp_Object buffer;
1450{
265a9e55 1451 if (!NILP (buffer))
7ab12479
JB
1452 {
1453 buffer = Fget_buffer (buffer);
1454 CHECK_BUFFER (buffer, 0);
1455 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1456 }
1457 return Qnil;
1458}
1459\f
1460/* Set the height of WINDOW and all its inferiors. */
a481b3ea
JB
1461
1462/* The smallest acceptable dimensions for a window. Anything smaller
1463 might crash Emacs. */
1464#define MIN_SAFE_WINDOW_WIDTH (2)
1465#define MIN_SAFE_WINDOW_HEIGHT (2)
1466
1467/* Make sure that window_min_height and window_min_width are
1468 not too small; if they are, set them to safe minima. */
1469
1470static void
1471check_min_window_sizes ()
1472{
1473 /* Smaller values might permit a crash. */
1474 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1475 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1476 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1477 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1478}
1479
1480/* If *ROWS or *COLS are too small a size for FRAME, set them to the
1481 minimum allowable size. */
605be8af 1482void
a481b3ea 1483check_frame_size (frame, rows, cols)
605be8af
JB
1484 FRAME_PTR frame;
1485 int *rows, *cols;
a481b3ea 1486{
628df3bf
JB
1487 /* For height, we have to see:
1488 whether the frame has a minibuffer,
1489 whether it wants a mode line, and
1490 whether it has a menu bar. */
a481b3ea 1491 int min_height =
79f92720
JB
1492 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1493 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
a481b3ea 1494 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
628df3bf
JB
1495 if (FRAME_MENU_BAR_LINES (frame) > 0)
1496 min_height += FRAME_MENU_BAR_LINES (frame);
a481b3ea
JB
1497
1498 if (*rows < min_height)
1499 *rows = min_height;
1500 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1501 *cols = MIN_SAFE_WINDOW_WIDTH;
1502}
1503
7ab12479
JB
1504/* Normally the window is deleted if it gets too small.
1505 nodelete nonzero means do not do this.
1506 (The caller should check later and do so if appropriate) */
1507
1508set_window_height (window, height, nodelete)
1509 Lisp_Object window;
1510 int height;
1511 int nodelete;
1512{
1513 register struct window *w = XWINDOW (window);
1514 register struct window *c;
1515 int oheight = XFASTINT (w->height);
1516 int top, pos, lastbot, opos, lastobot;
1517 Lisp_Object child;
1518
a481b3ea
JB
1519 check_min_window_sizes ();
1520
7ab12479 1521 if (!nodelete
265a9e55 1522 && ! NILP (w->parent)
7ab12479
JB
1523 && height < window_min_height)
1524 {
1525 Fdelete_window (window);
1526 return;
1527 }
1528
1529 XFASTINT (w->last_modified) = 0;
1530 windows_or_buffers_changed++;
1531 XFASTINT (w->height) = height;
265a9e55 1532 if (!NILP (w->hchild))
7ab12479 1533 {
265a9e55 1534 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1535 {
1536 XWINDOW (child)->top = w->top;
1537 set_window_height (child, height, nodelete);
1538 }
1539 }
265a9e55 1540 else if (!NILP (w->vchild))
7ab12479
JB
1541 {
1542 lastbot = top = XFASTINT (w->top);
1543 lastobot = 0;
265a9e55 1544 for (child = w->vchild; !NILP (child); child = c->next)
7ab12479
JB
1545 {
1546 c = XWINDOW (child);
1547
1548 opos = lastobot + XFASTINT (c->height);
1549
1550 XFASTINT (c->top) = lastbot;
1551
1552 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1553
1554 /* Avoid confusion: inhibit deletion of child if becomes too small */
1555 set_window_height (child, pos + top - lastbot, 1);
1556
1557 /* Now advance child to next window,
1558 and set lastbot if child was not just deleted. */
1559 lastbot = pos + top;
1560 lastobot = opos;
1561 }
1562 /* Now delete any children that became too small. */
1563 if (!nodelete)
265a9e55 1564 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1565 {
1566 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1567 }
1568 }
1569}
1570
1571/* Recursively set width of WINDOW and its inferiors. */
1572
1573set_window_width (window, width, nodelete)
1574 Lisp_Object window;
1575 int width;
1576 int nodelete;
1577{
1578 register struct window *w = XWINDOW (window);
1579 register struct window *c;
1580 int owidth = XFASTINT (w->width);
1581 int left, pos, lastright, opos, lastoright;
1582 Lisp_Object child;
1583
abdced83 1584 if (!nodelete && width < window_min_width && !NILP (w->parent))
7ab12479
JB
1585 {
1586 Fdelete_window (window);
1587 return;
1588 }
1589
1590 XFASTINT (w->last_modified) = 0;
1591 windows_or_buffers_changed++;
1592 XFASTINT (w->width) = width;
265a9e55 1593 if (!NILP (w->vchild))
7ab12479 1594 {
265a9e55 1595 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1596 {
1597 XWINDOW (child)->left = w->left;
1598 set_window_width (child, width, nodelete);
1599 }
1600 }
265a9e55 1601 else if (!NILP (w->hchild))
7ab12479
JB
1602 {
1603 lastright = left = XFASTINT (w->left);
1604 lastoright = 0;
265a9e55 1605 for (child = w->hchild; !NILP (child); child = c->next)
7ab12479
JB
1606 {
1607 c = XWINDOW (child);
1608
1609 opos = lastoright + XFASTINT (c->width);
1610
1611 XFASTINT (c->left) = lastright;
1612
1613 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1614
1615 /* Inhibit deletion for becoming too small */
1616 set_window_width (child, pos + left - lastright, 1);
1617
1618 /* Now advance child to next window,
1619 and set lastright if child was not just deleted. */
1620 lastright = pos + left, lastoright = opos;
1621 }
1622 /* Delete children that became too small */
1623 if (!nodelete)
265a9e55 1624 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1625 {
1626 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1627 }
1628 }
1629}
1630\f
1d8d96fa 1631int window_select_count;
7ab12479
JB
1632
1633DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1634 "Make WINDOW display BUFFER as its contents.\n\
1635BUFFER can be a buffer or buffer name.")
1636 (window, buffer)
1637 register Lisp_Object window, buffer;
1638{
1639 register Lisp_Object tem;
1640 register struct window *w = decode_window (window);
1641
1642 buffer = Fget_buffer (buffer);
1643 CHECK_BUFFER (buffer, 1);
1644
265a9e55 1645 if (NILP (XBUFFER (buffer)->name))
7ab12479
JB
1646 error ("Attempt to display deleted buffer");
1647
1648 tem = w->buffer;
265a9e55 1649 if (NILP (tem))
7ab12479
JB
1650 error ("Window is deleted");
1651 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1652 is first being set up. */
1653 {
265a9e55 1654 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3cf85532
RS
1655 error ("Window is dedicated to `%s'",
1656 XSTRING (XBUFFER (tem)->name)->data);
7ab12479
JB
1657
1658 unshow_buffer (w);
1659 }
1660
1661 w->buffer = buffer;
5a41ab94
RS
1662 w->window_end_pos = 0;
1663 w->window_end_valid = Qnil;
270967b2 1664 w->hscroll = 0;
7ab12479
JB
1665 Fset_marker (w->pointm,
1666 make_number (BUF_PT (XBUFFER (buffer))),
1667 buffer);
1668 set_marker_restricted (w->start,
1669 make_number (XBUFFER (buffer)->last_window_start),
1670 buffer);
1671 w->start_at_line_beg = Qnil;
e36ab06b 1672 w->force_start = Qnil;
7ab12479
JB
1673 XFASTINT (w->last_modified) = 0;
1674 windows_or_buffers_changed++;
1675 if (EQ (window, selected_window))
1676 Fset_buffer (buffer);
1677
1678 return Qnil;
1679}
1680
1681DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1682 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1683The main editor command loop selects the buffer of the selected window\n\
1684before each command.")
1685 (window)
1686 register Lisp_Object window;
1687{
1688 register struct window *w;
1689 register struct window *ow = XWINDOW (selected_window);
1690
605be8af 1691 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1692
1693 w = XWINDOW (window);
1694
265a9e55 1695 if (NILP (w->buffer))
7ab12479
JB
1696 error ("Trying to select deleted window or non-leaf window");
1697
1698 XFASTINT (w->use_time) = ++window_select_count;
1699 if (EQ (window, selected_window))
1700 return window;
1701
1702 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1703 ow->buffer);
1704
1705 selected_window = window;
44fa5b1e
JB
1706#ifdef MULTI_FRAME
1707 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
7ab12479 1708 {
44fa5b1e 1709 XFRAME (WINDOW_FRAME (w))->selected_window = window;
147a6615
RS
1710 /* Use this rather than Fhandle_switch_frame
1711 so that FRAME_FOCUS_FRAME is moved appropriately as we
1712 move around in the state where a minibuffer in a separate
1713 frame is active. */
1714 Fselect_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
1715 }
1716 else
44fa5b1e 1717 selected_frame->selected_window = window;
7ab12479
JB
1718#endif
1719
1720 record_buffer (w->buffer);
1721 Fset_buffer (w->buffer);
1722
1723 /* Go to the point recorded in the window.
1724 This is important when the buffer is in more
1725 than one window. It also matters when
1726 redisplay_window has altered point after scrolling,
1727 because it makes the change only in the window. */
1728 {
1729 register int new_point = marker_position (w->pointm);
1730 if (new_point < BEGV)
1731 SET_PT (BEGV);
a9c95e08 1732 else if (new_point > ZV)
7ab12479
JB
1733 SET_PT (ZV);
1734 else
1735 SET_PT (new_point);
1736 }
1737
1738 windows_or_buffers_changed++;
1739 return window;
1740}
1741
35aaf00c 1742DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
6648f23a 1743 "BDisplay buffer: \nP",
7ab12479
JB
1744 "Make BUFFER appear in some window but don't select it.\n\
1745BUFFER can be a buffer or a buffer name.\n\
1746If BUFFER is shown already in some window, just use that one,\n\
1747unless the window is the selected window and the optional second\n\
46d3268a 1748argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
5141b901 1749If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
7ab12479
JB
1750Returns the window displaying BUFFER.")
1751 (buffer, not_this_window)
1752 register Lisp_Object buffer, not_this_window;
1753{
a90712c2 1754 register Lisp_Object window, tem;
7ab12479
JB
1755
1756 buffer = Fget_buffer (buffer);
1757 CHECK_BUFFER (buffer, 0);
1758
265a9e55 1759 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
1760 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1761
265a9e55 1762 if (NILP (not_this_window)
7ab12479
JB
1763 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1764 return selected_window;
1765
c6e73093 1766#ifdef MULTI_FRAME
e8edb3ae 1767 /* If pop_up_frames,
f812f9c6
RS
1768 look for a window showing BUFFER on any visible or iconified frame. */
1769 window = Fget_buffer_window (buffer, pop_up_frames ? make_number (0) : Qnil);
c6e73093
KH
1770#else
1771 window = Fget_buffer_window (buffer, Qnil);
1772#endif
265a9e55
JB
1773 if (!NILP (window)
1774 && (NILP (not_this_window) || !EQ (window, selected_window)))
f812f9c6 1775 {
7cab5d2c 1776#ifdef MULTI_FRAME
f812f9c6
RS
1777 if (FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (window)))))
1778 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
7cab5d2c 1779#endif
f812f9c6
RS
1780 return window;
1781 }
7ab12479 1782
a90712c2
RS
1783 /* Certain buffer names get special handling. */
1784 if (! NILP (Vspecial_display_function))
1785 {
1786 tem = Fmember (XBUFFER (buffer)->name, Vspecial_display_buffer_names);
1787 if (!NILP (tem))
1788 return call1 (Vspecial_display_function, buffer);
1789
1790 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
1791 if (fast_string_match (XCONS (tem)->car, XBUFFER (buffer)->name) >= 0)
1792 return call1 (Vspecial_display_function, buffer);
1793 }
1794
44fa5b1e
JB
1795#ifdef MULTI_FRAME
1796 /* If there are no frames open that have more than a minibuffer,
1797 we need to create a new frame. */
1798 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479 1799 {
a90712c2 1800 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479 1801 Fset_window_buffer (window, buffer);
7ab12479
JB
1802 return window;
1803 }
44fa5b1e 1804#endif /* MULTI_FRAME */
7ab12479 1805
43bad991 1806 if (pop_up_windows
44fa5b1e
JB
1807#ifdef MULTI_FRAME
1808 || FRAME_MINIBUF_ONLY_P (selected_frame)
43bad991
JB
1809#endif
1810 )
7ab12479 1811 {
12cae7c0
KH
1812 Lisp_Object frames;
1813
1814 frames = Qnil;
44fa5b1e
JB
1815#ifdef MULTI_FRAME
1816 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1817 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
7ab12479
JB
1818#endif
1819 /* Don't try to create a window if would get an error */
1820 if (split_height_threshold < window_min_height << 1)
1821 split_height_threshold = window_min_height << 1;
1822
44fa5b1e 1823 window = Fget_largest_window (frames);
7ab12479 1824
265a9e55 1825 if (!NILP (window)
7ab12479 1826 && window_height (window) >= split_height_threshold
535e0b8e
JB
1827 && (XFASTINT (XWINDOW (window)->width)
1828 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
7ab12479
JB
1829 window = Fsplit_window (window, Qnil, Qnil);
1830 else
1831 {
44fa5b1e 1832 window = Fget_lru_window (frames);
7ab12479
JB
1833 if ((EQ (window, selected_window)
1834 || EQ (XWINDOW (window)->parent, Qnil))
1835 && window_height (window) >= window_min_height << 1)
1836 window = Fsplit_window (window, Qnil, Qnil);
1837 }
1838 }
1839 else
1840 window = Fget_lru_window (Qnil);
1841
1842 Fset_window_buffer (window, buffer);
1843 return window;
1844}
1845
1846void
1847temp_output_buffer_show (buf)
1848 register Lisp_Object buf;
1849{
1850 register struct buffer *old = current_buffer;
1851 register Lisp_Object window;
1852 register struct window *w;
1853
1854 Fset_buffer (buf);
1855 XBUFFER (buf)->save_modified = MODIFF;
1856 BEGV = BEG;
1857 ZV = Z;
1858 SET_PT (BEG);
1859 clip_changed = 1;
1860 set_buffer_internal (old);
1861
1862 if (!EQ (Vtemp_buffer_show_function, Qnil))
1863 call1 (Vtemp_buffer_show_function, buf);
1864 else
1865 {
1866 window = Fdisplay_buffer (buf, Qnil);
1867
44fa5b1e
JB
1868#ifdef MULTI_FRAME
1869 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1870 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1871#endif /* MULTI_FRAME */
7ab12479
JB
1872 Vminibuf_scroll_window = window;
1873 w = XWINDOW (window);
1874 XFASTINT (w->hscroll) = 0;
1875 set_marker_restricted (w->start, make_number (1), buf);
1876 set_marker_restricted (w->pointm, make_number (1), buf);
1877 }
1878}
1879\f
1880static
1881make_dummy_parent (window)
1882 Lisp_Object window;
1883{
1884 register Lisp_Object old, new;
1885 register struct window *o, *p;
1886
1887 old = window;
1888 XSETTYPE (old, Lisp_Vector);
1889 new = Fcopy_sequence (old);
1890 XSETTYPE (new, Lisp_Window);
1891
1892 o = XWINDOW (old);
1893 p = XWINDOW (new);
1894 XFASTINT (p->sequence_number) = ++sequence_number;
1895
1896 /* Put new into window structure in place of window */
1897 replace_window (window, new);
1898
1899 o->next = Qnil;
1900 o->prev = Qnil;
1901 o->vchild = Qnil;
1902 o->hchild = Qnil;
1903 o->parent = new;
1904
1905 p->start = Qnil;
1906 p->pointm = Qnil;
1907 p->buffer = Qnil;
1908}
1909
1910DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1911 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1912WINDOW defaults to selected one and SIZE to half its size.\n\
1913If optional third arg HOR-FLAG is non-nil, split side by side\n\
1914and put SIZE columns in the first of the pair.")
1915 (window, chsize, horflag)
1916 Lisp_Object window, chsize, horflag;
1917{
1918 register Lisp_Object new;
1919 register struct window *o, *p;
1920 register int size;
1921
265a9e55 1922 if (NILP (window))
7ab12479
JB
1923 window = selected_window;
1924 else
605be8af 1925 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1926
1927 o = XWINDOW (window);
1928
265a9e55 1929 if (NILP (chsize))
7ab12479 1930 {
265a9e55 1931 if (!NILP (horflag))
7ab12479
JB
1932 /* Round odd size up, since this is for the left-hand window,
1933 and it will lose a column for the separators. */
1934 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1935 else
1936 size = XFASTINT (o->height) >> 1;
1937 }
1938 else
1939 {
1940 CHECK_NUMBER (chsize, 1);
1941 size = XINT (chsize);
1942 }
1943
1944 if (MINI_WINDOW_P (o))
1945 error ("Attempt to split minibuffer window");
44fa5b1e
JB
1946 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1947 error ("Attempt to split unsplittable frame");
7ab12479 1948
a481b3ea 1949 check_min_window_sizes ();
7ab12479 1950
265a9e55 1951 if (NILP (horflag))
7ab12479
JB
1952 {
1953 if (size < window_min_height
1954 || size + window_min_height > XFASTINT (o->height))
1955 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1956 if (NILP (o->parent)
1957 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
1958 {
1959 make_dummy_parent (window);
1960 new = o->parent;
1961 XWINDOW (new)->vchild = window;
1962 }
1963 }
1964 else
1965 {
1966 if (size < window_min_width
1967 || size + window_min_width > XFASTINT (o->width))
1968 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1969 if (NILP (o->parent)
1970 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
1971 {
1972 make_dummy_parent (window);
1973 new = o->parent;
1974 XWINDOW (new)->hchild = window;
1975 }
1976 }
1977
1978 /* Now we know that window's parent is a vertical combination
1979 if we are dividing vertically, or a horizontal combination
1980 if we are making side-by-side windows */
1981
1982 windows_or_buffers_changed++;
1983 new = make_window ();
1984 p = XWINDOW (new);
1985
44fa5b1e 1986 p->frame = o->frame;
7ab12479 1987 p->next = o->next;
265a9e55 1988 if (!NILP (p->next))
7ab12479
JB
1989 XWINDOW (p->next)->prev = new;
1990 p->prev = window;
1991 o->next = new;
1992 p->parent = o->parent;
1993 p->buffer = Qt;
1994
1995 Fset_window_buffer (new, o->buffer);
1996
44fa5b1e 1997 /* Apportion the available frame space among the two new windows */
7ab12479 1998
265a9e55 1999 if (!NILP (horflag))
7ab12479
JB
2000 {
2001 p->height = o->height;
2002 p->top = o->top;
2003 XFASTINT (p->width) = XFASTINT (o->width) - size;
2004 XFASTINT (o->width) = size;
2005 XFASTINT (p->left) = XFASTINT (o->left) + size;
2006 }
2007 else
2008 {
2009 p->left = o->left;
2010 p->width = o->width;
2011 XFASTINT (p->height) = XFASTINT (o->height) - size;
2012 XFASTINT (o->height) = size;
2013 XFASTINT (p->top) = XFASTINT (o->top) + size;
2014 }
2015
2016 return new;
2017}
2018\f
2019DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
2020 "Make current window ARG lines bigger.\n\
2021From program, optional second arg non-nil means grow sideways ARG columns.")
2022 (n, side)
2023 register Lisp_Object n, side;
2024{
2025 CHECK_NUMBER (n, 0);
265a9e55 2026 change_window_height (XINT (n), !NILP (side));
7ab12479
JB
2027 return Qnil;
2028}
2029
2030DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
2031 "Make current window ARG lines smaller.\n\
2032From program, optional second arg non-nil means shrink sideways ARG columns.")
2033 (n, side)
2034 register Lisp_Object n, side;
2035{
2036 CHECK_NUMBER (n, 0);
265a9e55 2037 change_window_height (-XINT (n), !NILP (side));
7ab12479
JB
2038 return Qnil;
2039}
2040
2041int
2042window_height (window)
2043 Lisp_Object window;
2044{
2045 register struct window *p = XWINDOW (window);
2046 return XFASTINT (p->height);
2047}
2048
2049int
2050window_width (window)
2051 Lisp_Object window;
2052{
2053 register struct window *p = XWINDOW (window);
2054 return XFASTINT (p->width);
2055}
2056
05c2896a
JB
2057#define MINSIZE(w) \
2058 (widthflag \
2059 ? window_min_width \
2060 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
7ab12479
JB
2061
2062#define CURBEG(w) \
05c2896a 2063 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
2064
2065#define CURSIZE(w) \
05c2896a 2066 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479
JB
2067
2068/* Unlike set_window_height, this function
2069 also changes the heights of the siblings so as to
2070 keep everything consistent. */
2071
2072change_window_height (delta, widthflag)
2073 register int delta;
2074 int widthflag;
2075{
2076 register Lisp_Object parent;
2077 Lisp_Object window;
2078 register struct window *p;
2079 int *sizep;
2080 int (*sizefun) () = widthflag ? window_width : window_height;
2081 register int (*setsizefun) () = (widthflag
2082 ? set_window_width
2083 : set_window_height);
2084
a481b3ea 2085 check_min_window_sizes ();
7ab12479
JB
2086
2087 window = selected_window;
2088 while (1)
2089 {
2090 p = XWINDOW (window);
2091 parent = p->parent;
265a9e55 2092 if (NILP (parent))
7ab12479
JB
2093 {
2094 if (widthflag)
2095 error ("No other window to side of this one");
2096 break;
2097 }
265a9e55
JB
2098 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2099 : !NILP (XWINDOW (parent)->vchild))
7ab12479
JB
2100 break;
2101 window = parent;
2102 }
2103
05c2896a 2104 sizep = &CURSIZE (window);
7ab12479 2105
7ab12479
JB
2106 {
2107 register int maxdelta;
7ab12479 2108
265a9e55
JB
2109 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2110 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2111 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
44fa5b1e
JB
2112 /* This is a frame with only one window, a minibuffer-only
2113 or a minibufferless frame. */
d5783c40 2114 : (delta = 0));
7ab12479
JB
2115
2116 if (delta > maxdelta)
2117 /* This case traps trying to make the minibuffer
44fa5b1e
JB
2118 the full frame, or make the only window aside from the
2119 minibuffer the full frame. */
7ab12479 2120 delta = maxdelta;
6b54027b 2121 }
d5783c40 2122
6b54027b
RS
2123 if (*sizep + delta < MINSIZE (window))
2124 {
2125 Fdelete_window (window);
d5783c40 2126 return;
6b54027b
RS
2127 }
2128
2129 if (delta == 0)
2130 return;
7ab12479 2131
6b54027b
RS
2132 if (!NILP (p->next)
2133 && (*sizefun) (p->next) - delta >= MINSIZE (p->next))
7ab12479
JB
2134 {
2135 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
2136 (*setsizefun) (window, *sizep + delta, 0);
05c2896a 2137 CURBEG (p->next) += delta;
7ab12479
JB
2138 /* This does not change size of p->next,
2139 but it propagates the new top edge to its children */
2140 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
2141 }
6b54027b
RS
2142 else if (!NILP (p->prev)
2143 && (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
7ab12479
JB
2144 {
2145 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
05c2896a 2146 CURBEG (window) -= delta;
7ab12479
JB
2147 (*setsizefun) (window, *sizep + delta, 0);
2148 }
2149 else
2150 {
2151 register int delta1;
2152 register int opht = (*sizefun) (parent);
2153
2154 /* If trying to grow this window to or beyond size of the parent,
2155 make delta1 so big that, on shrinking back down,
2156 all the siblings end up with less than one line and are deleted. */
2157 if (opht <= *sizep + delta)
2158 delta1 = opht * opht * 2;
2159 /* Otherwise, make delta1 just right so that if we add delta1
2160 lines to this window and to the parent, and then shrink
2161 the parent back to its original size, the new proportional
2162 size of this window will increase by delta. */
2163 else
2164 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2165
2166 /* Add delta1 lines or columns to this window, and to the parent,
2167 keeping things consistent while not affecting siblings. */
05c2896a 2168 CURSIZE (parent) = opht + delta1;
7ab12479
JB
2169 (*setsizefun) (window, *sizep + delta1, 0);
2170
2171 /* Squeeze out delta1 lines or columns from our parent,
2172 shriking this window and siblings proportionately.
2173 This brings parent back to correct size.
2174 Delta1 was calculated so this makes this window the desired size,
2175 taking it all out of the siblings. */
2176 (*setsizefun) (parent, opht, 0);
2177 }
2178
2179 XFASTINT (p->last_modified) = 0;
2180}
2181#undef MINSIZE
2182#undef CURBEG
2183#undef CURSIZE
2184
2185\f
2186/* Return number of lines of text (not counting mode line) in W. */
2187
2188int
2189window_internal_height (w)
2190 struct window *w;
2191{
2192 int ht = XFASTINT (w->height);
2193
2194 if (MINI_WINDOW_P (w))
2195 return ht;
2196
265a9e55
JB
2197 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2198 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 2199 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
2200 return ht - 1;
2201
2202 return ht;
2203}
2204
535e0b8e
JB
2205
2206/* Return the number of columns in W.
a3c87d4e 2207 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e
JB
2208 separating W from the sibling to its right. */
2209int
2210window_internal_width (w)
2211 struct window *w;
2212{
2213 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2214 int left = XINT (w->left);
2215 int width = XINT (w->width);
2216
2217 /* If this window is flush against the right edge of the frame, its
2218 internal width is its full width. */
2219 if (left + width >= FRAME_WIDTH (f))
2220 return width;
2221
2222 /* If we are not flush right, then our rightmost columns are
2223 occupied by some sort of separator. */
2224
a3c87d4e
JB
2225 /* Scroll bars occupy a few columns. */
2226 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2227 return width - VERTICAL_SCROLL_BAR_WIDTH;
535e0b8e
JB
2228
2229 /* The column of `|' characters separating side-by-side windows
2230 occupies one column only. */
2231 return width - 1;
2232}
2233
2234
7ab12479
JB
2235/* Scroll contents of window WINDOW up N lines. */
2236
2237void
f8026fd8 2238window_scroll (window, n, noerror)
7ab12479
JB
2239 Lisp_Object window;
2240 int n;
f8026fd8 2241 int noerror;
7ab12479
JB
2242{
2243 register struct window *w = XWINDOW (window);
5ce7b543 2244 register int opoint = PT;
7ab12479
JB
2245 register int pos;
2246 register int ht = window_internal_height (w);
2247 register Lisp_Object tem;
2248 int lose;
2249 Lisp_Object bolp, nmoved;
2250
5ce7b543 2251 XFASTINT (tem) = PT;
7ab12479
JB
2252 tem = Fpos_visible_in_window_p (tem, window);
2253
265a9e55 2254 if (NILP (tem))
7ab12479 2255 {
cd2be1dd 2256 Fvertical_motion (make_number (- (ht / 2)), window);
5ce7b543 2257 XFASTINT (tem) = PT;
7ab12479
JB
2258 Fset_marker (w->start, tem, w->buffer);
2259 w->force_start = Qt;
2260 }
2261
2262 SET_PT (marker_position (w->start));
5ce7b543 2263 lose = n < 0 && PT == BEGV;
540b6aa0 2264 Fvertical_motion (make_number (n), window);
5ce7b543 2265 pos = PT;
7ab12479
JB
2266 bolp = Fbolp ();
2267 SET_PT (opoint);
2268
2269 if (lose)
f8026fd8
JB
2270 {
2271 if (noerror)
2272 return;
2273 else
2274 Fsignal (Qbeginning_of_buffer, Qnil);
2275 }
7ab12479
JB
2276
2277 if (pos < ZV)
7ab12479
JB
2278 {
2279 set_marker_restricted (w->start, make_number (pos), w->buffer);
2280 w->start_at_line_beg = bolp;
2281 w->update_mode_line = Qt;
2282 XFASTINT (w->last_modified) = 0;
2283 if (pos > opoint)
2284 SET_PT (pos);
2285 if (n < 0)
2286 {
2287 SET_PT (pos);
540b6aa0 2288 tem = Fvertical_motion (make_number (ht), window);
5ce7b543 2289 if (PT > opoint || XFASTINT (tem) < ht)
7ab12479
JB
2290 SET_PT (opoint);
2291 else
540b6aa0 2292 Fvertical_motion (make_number (-1), window);
7ab12479
JB
2293 }
2294 }
2295 else
f8026fd8
JB
2296 {
2297 if (noerror)
2298 return;
2299 else
2300 Fsignal (Qend_of_buffer, Qnil);
2301 }
7ab12479
JB
2302}
2303\f
2304/* This is the guts of Fscroll_up and Fscroll_down. */
2305
2306static void
2307scroll_command (n, direction)
2308 register Lisp_Object n;
2309 int direction;
2310{
2311 register int defalt;
2312 int count = specpdl_ptr - specpdl;
2313
95605e15
JB
2314 /* If selected window's buffer isn't current, make it current for the moment.
2315 But don't screw up if window_scroll gets an error. */
7ab12479 2316 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
2317 {
2318 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2319 Fset_buffer (XWINDOW (selected_window)->buffer);
2320 }
7ab12479
JB
2321
2322 defalt = (window_internal_height (XWINDOW (selected_window))
2323 - next_screen_context_lines);
2324 defalt = direction * (defalt < 1 ? 1 : defalt);
2325
265a9e55 2326 if (NILP (n))
f8026fd8 2327 window_scroll (selected_window, defalt, 0);
7ab12479 2328 else if (EQ (n, Qminus))
f8026fd8 2329 window_scroll (selected_window, - defalt, 0);
7ab12479
JB
2330 else
2331 {
2332 n = Fprefix_numeric_value (n);
f8026fd8 2333 window_scroll (selected_window, XINT (n) * direction, 0);
7ab12479 2334 }
95605e15
JB
2335
2336 unbind_to (count, Qnil);
7ab12479
JB
2337}
2338
2339DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2340 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2341A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2342Negative ARG means scroll downward.\n\
7ab12479
JB
2343When calling from a program, supply a number as argument or nil.")
2344 (n)
2345 Lisp_Object n;
2346{
2347 scroll_command (n, 1);
2348 return Qnil;
2349}
2350
2351DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2352 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2353A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2354Negative ARG means scroll upward.\n\
7ab12479
JB
2355When calling from a program, supply a number as argument or nil.")
2356 (n)
2357 Lisp_Object n;
2358{
2359 scroll_command (n, -1);
2360 return Qnil;
2361}
ccd0664b
RS
2362\f
2363DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
2364 "Return the other window for \"other window scroll\" commands.\n\
77b24de6 2365If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
ccd0664b
RS
2366specifies the window.\n\
2367If `other-window-scroll-buffer' is non-nil, a window\n\
2368showing that buffer is used.")
eb16ec06 2369 ()
7ab12479 2370{
ccd0664b 2371 Lisp_Object window;
7ab12479
JB
2372
2373 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 2374 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
2375 window = Vminibuf_scroll_window;
2376 /* If buffer is specified, scroll that buffer. */
265a9e55 2377 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
2378 {
2379 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 2380 if (NILP (window))
7ab12479
JB
2381 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2382 }
2383 else
dbc4e1c1
JB
2384 {
2385 /* Nothing specified; look for a neighboring window on the same
2386 frame. */
2387 window = Fnext_window (selected_window, Qnil, Qnil);
2388
2389 if (EQ (window, selected_window))
2390 /* That didn't get us anywhere; look for a window on another
2391 visible frame. */
2392 do
2393 window = Fnext_window (window, Qnil, Qt);
2394 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2395 && ! EQ (window, selected_window));
2396 }
2397
605be8af 2398 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2399
2400 if (EQ (window, selected_window))
2401 error ("There is no other window");
2402
ccd0664b
RS
2403 return window;
2404}
2405
2406DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2407 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2408The next window is the one below the current one; or the one at the top\n\
2409if the current one is at the bottom. Negative ARG means scroll downward.\n\
2410When calling from a program, supply a number as argument or nil.\n\
2411\n\
2412If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2413specifies the window to scroll.\n\
2414If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2415showing that buffer, popping the buffer up if necessary.")
2416 (n)
2417 register Lisp_Object n;
2418{
2419 register Lisp_Object window;
2420 register int ht;
2421 register struct window *w;
2422 register int count = specpdl_ptr - specpdl;
2423
2424 window = Fother_window_for_scrolling ();
2425
7ab12479
JB
2426 w = XWINDOW (window);
2427 ht = window_internal_height (w);
2428
2429 /* Don't screw up if window_scroll gets an error. */
2430 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2431
2432 Fset_buffer (w->buffer);
2433 SET_PT (marker_position (w->pointm));
2434
265a9e55 2435 if (NILP (n))
f8026fd8 2436 window_scroll (window, ht - next_screen_context_lines, 1);
7ab12479 2437 else if (EQ (n, Qminus))
f8026fd8 2438 window_scroll (window, next_screen_context_lines - ht, 1);
7ab12479
JB
2439 else
2440 {
2441 if (XTYPE (n) == Lisp_Cons)
2442 n = Fcar (n);
2443 CHECK_NUMBER (n, 0);
f8026fd8 2444 window_scroll (window, XINT (n), 1);
7ab12479
JB
2445 }
2446
5ce7b543 2447 Fset_marker (w->pointm, make_number (PT), Qnil);
f4e7b2c2 2448 unbind_to (count, Qnil);
7ab12479
JB
2449
2450 return Qnil;
2451}
2452\f
644b477c 2453DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
2454 "Scroll selected window display ARG columns left.\n\
2455Default for ARG is window width minus 2.")
2456 (arg)
2457 register Lisp_Object arg;
2458{
2459
265a9e55 2460 if (NILP (arg))
b8baad40 2461 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2462 else
2463 arg = Fprefix_numeric_value (arg);
2464
2465 return
2466 Fset_window_hscroll (selected_window,
2467 make_number (XINT (XWINDOW (selected_window)->hscroll)
2468 + XINT (arg)));
2469}
2470
644b477c 2471DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
2472 "Scroll selected window display ARG columns right.\n\
2473Default for ARG is window width minus 2.")
2474 (arg)
2475 register Lisp_Object arg;
2476{
265a9e55 2477 if (NILP (arg))
b8baad40 2478 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2479 else
2480 arg = Fprefix_numeric_value (arg);
2481
2482 return
2483 Fset_window_hscroll (selected_window,
2484 make_number (XINT (XWINDOW (selected_window)->hscroll)
2485 - XINT (arg)));
2486}
2487
2488DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 2489 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 2490The desired position of point is always relative to the current window.\n\
44fa5b1e
JB
2491Just C-u as prefix means put point in the center of the window.\n\
2492No arg (i.e., it is nil) erases the entire frame and then\n\
2493redraws with point in the center of the current window.")
7ab12479
JB
2494 (n)
2495 register Lisp_Object n;
2496{
2497 register struct window *w = XWINDOW (selected_window);
2498 register int ht = window_internal_height (w);
5ce7b543 2499 register int opoint = PT;
540b6aa0 2500 Lisp_Object window;
7ab12479 2501
265a9e55 2502 if (NILP (n))
7ab12479 2503 {
44fa5b1e 2504 extern int frame_garbaged;
7ab12479 2505
44fa5b1e 2506 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
7ab12479
JB
2507 XFASTINT (n) = ht / 2;
2508 }
2509 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2510 {
2511 XFASTINT (n) = ht / 2;
2512 }
2513 else
2514 {
2515 n = Fprefix_numeric_value (n);
2516 CHECK_NUMBER (n, 0);
2517 }
2518
2519 if (XINT (n) < 0)
2520 XSETINT (n, XINT (n) + ht);
2521
2522 XSETINT (n, - XINT (n));
2523
540b6aa0
RS
2524 XSET (window, Lisp_Window, w);
2525 Fvertical_motion (n, window);
5ce7b543 2526 Fset_marker (w->start, make_number (PT), w->buffer);
7ab12479
JB
2527 w->start_at_line_beg = Fbolp ();
2528
2529 SET_PT (opoint);
2530 w->force_start = Qt;
2531
2532 return Qnil;
2533}
2534\f
2535DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2536 1, 1, "P",
2537 "Position point relative to window.\n\
2538With no argument, position text at center of window.\n\
44fa5b1e 2539An argument specifies frame line; zero means top of window,\n\
7ab12479
JB
2540negative means relative to bottom of window.")
2541 (arg)
2542 register Lisp_Object arg;
2543{
2544 register struct window *w = XWINDOW (selected_window);
2545 register int height = window_internal_height (w);
2546 register int start;
540b6aa0 2547 Lisp_Object window;
7ab12479 2548
265a9e55 2549 if (NILP (arg))
7ab12479
JB
2550 XFASTINT (arg) = height / 2;
2551 else
2552 {
2553 arg = Fprefix_numeric_value (arg);
2554 if (XINT (arg) < 0)
2555 XSETINT (arg, XINT (arg) + height);
2556 }
2557
2558 start = marker_position (w->start);
540b6aa0 2559 XSET (window, Lisp_Window, w);
7ab12479
JB
2560 if (start < BEGV || start > ZV)
2561 {
cd2be1dd 2562 Fvertical_motion (make_number (- (height / 2)), window);
5ce7b543 2563 Fset_marker (w->start, make_number (PT), w->buffer);
7ab12479
JB
2564 w->start_at_line_beg = Fbolp ();
2565 w->force_start = Qt;
2566 }
2567 else
2568 SET_PT (start);
2569
540b6aa0 2570 return Fvertical_motion (arg, window);
7ab12479
JB
2571}
2572\f
2573struct save_window_data
2574 {
2575 int size_from_Lisp_Vector_struct;
2576 struct Lisp_Vector *next_from_Lisp_Vector_struct;
8f6ea2e9 2577 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
bdc727bf 2578 Lisp_Object selected_frame;
7ab12479
JB
2579 Lisp_Object current_window;
2580 Lisp_Object current_buffer;
2581 Lisp_Object minibuf_scroll_window;
2582 Lisp_Object root_window;
bdc727bf 2583 Lisp_Object focus_frame;
7ab12479
JB
2584 /* A vector, interpreted as a struct saved_window */
2585 Lisp_Object saved_windows;
2586 };
ff06df24
JB
2587
2588/* Arg to Fmake_vector */
2589#define SAVE_WINDOW_DATA_SIZE \
2590 ((sizeof (struct save_window_data) \
2591 - (sizeof (struct Lisp_Vector) \
2592 /* Don't count the contents member of the struct Lisp_Vector */ \
2593 - sizeof (Lisp_Object))) \
2594 / sizeof (Lisp_Object))
7ab12479
JB
2595
2596/* This is saved as a Lisp_Vector */
2597struct saved_window
2598 {
2599 /* these first two must agree with struct Lisp_Vector in lisp.h */
2600 int size_from_Lisp_Vector_struct;
2601 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2602
2603 Lisp_Object window;
2604 Lisp_Object buffer, start, pointm, mark;
2605 Lisp_Object left, top, width, height, hscroll;
2606 Lisp_Object parent, prev;
2607 Lisp_Object start_at_line_beg;
2608 Lisp_Object display_table;
2609 };
2610#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2611
2612#define SAVED_WINDOW_N(swv,n) \
2613 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2614
2615DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2616 "T if OBJECT is a window-configration object.")
2617 (obj)
2618 Lisp_Object obj;
2619{
2620 if (XTYPE (obj) == Lisp_Window_Configuration)
2621 return Qt;
2622 return Qnil;
2623}
2624
2625
d5b2799e
RS
2626DEFUN ("set-window-configuration", Fset_window_configuration,
2627 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
2628 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2629CONFIGURATION must be a value previously returned\n\
2630by `current-window-configuration' (which see).")
2f83aebe
JB
2631 (configuration)
2632 Lisp_Object configuration;
7ab12479 2633{
7ab12479
JB
2634 register struct save_window_data *data;
2635 struct Lisp_Vector *saved_windows;
7ab12479 2636 Lisp_Object new_current_buffer;
fd482be5 2637 Lisp_Object frame;
44fa5b1e 2638 FRAME_PTR f;
7ab12479 2639
2f83aebe 2640 while (XTYPE (configuration) != Lisp_Window_Configuration)
7ab12479 2641 {
2f83aebe
JB
2642 configuration = wrong_type_argument (intern ("window-configuration-p"),
2643 configuration);
7ab12479
JB
2644 }
2645
2f83aebe 2646 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
2647 saved_windows = XVECTOR (data->saved_windows);
2648
7ab12479 2649 new_current_buffer = data->current_buffer;
265a9e55 2650 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479
JB
2651 new_current_buffer = Qnil;
2652
fd482be5
JB
2653 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2654 f = XFRAME (frame);
9ace597f 2655
fd482be5
JB
2656 /* If f is a dead frame, don't bother rebuilding its window tree.
2657 However, there is other stuff we should still try to do below. */
2658 if (FRAME_LIVE_P (f))
7ab12479 2659 {
fd482be5
JB
2660 register struct window *w;
2661 register struct saved_window *p;
2662 int k;
2663
2664 /* If the frame has been resized since this window configuration was
2665 made, we change the frame to the size specified in the
2666 configuration, restore the configuration, and then resize it
2667 back. We keep track of the prevailing height in these variables. */
2668 int previous_frame_height = FRAME_HEIGHT (f);
2669 int previous_frame_width = FRAME_WIDTH (f);
8f6ea2e9 2670 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
fd482be5
JB
2671
2672 if (XFASTINT (data->frame_height) != previous_frame_height
2673 || XFASTINT (data->frame_width) != previous_frame_width)
2674 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
217f2871 2675#ifdef HAVE_X_WINDOWS
8f6ea2e9
KH
2676 if (XFASTINT (data->frame_menu_bar_lines)
2677 != previous_frame_menu_bar_lines)
2678 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
217f2871 2679#endif
fd482be5
JB
2680
2681 windows_or_buffers_changed++;
2682
2683 /* Kludge Alert!
2684 Mark all windows now on frame as "deleted".
2685 Restoring the new configuration "undeletes" any that are in it.
2686
2687 Save their current buffers in their height fields, since we may
2688 need it later, if a buffer saved in the configuration is now
2689 dead. */
2690 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2691
2692 for (k = 0; k < saved_windows->size; k++)
2693 {
2694 p = SAVED_WINDOW_N (saved_windows, k);
2695 w = XWINDOW (p->window);
2696 w->next = Qnil;
7ab12479 2697
fd482be5
JB
2698 if (!NILP (p->parent))
2699 w->parent = SAVED_WINDOW_N (saved_windows,
2700 XFASTINT (p->parent))->window;
2701 else
2702 w->parent = Qnil;
7ab12479 2703
fd482be5 2704 if (!NILP (p->prev))
7ab12479 2705 {
fd482be5
JB
2706 w->prev = SAVED_WINDOW_N (saved_windows,
2707 XFASTINT (p->prev))->window;
2708 XWINDOW (w->prev)->next = p->window;
2709 }
2710 else
2711 {
2712 w->prev = Qnil;
2713 if (!NILP (w->parent))
2714 {
2715 if (EQ (p->width, XWINDOW (w->parent)->width))
2716 {
2717 XWINDOW (w->parent)->vchild = p->window;
2718 XWINDOW (w->parent)->hchild = Qnil;
2719 }
2720 else
2721 {
2722 XWINDOW (w->parent)->hchild = p->window;
2723 XWINDOW (w->parent)->vchild = Qnil;
2724 }
2725 }
2726 }
2727
2728 /* If we squirreled away the buffer in the window's height,
2729 restore it now. */
2730 if (XTYPE (w->height) == Lisp_Buffer)
2731 w->buffer = w->height;
2732 w->left = p->left;
2733 w->top = p->top;
2734 w->width = p->width;
2735 w->height = p->height;
2736 w->hscroll = p->hscroll;
2737 w->display_table = p->display_table;
2738 XFASTINT (w->last_modified) = 0;
2739
2740 /* Reinstall the saved buffer and pointers into it. */
2741 if (NILP (p->buffer))
2742 w->buffer = p->buffer;
2743 else
2744 {
2745 if (!NILP (XBUFFER (p->buffer)->name))
2746 /* If saved buffer is alive, install it. */
2747 {
2748 w->buffer = p->buffer;
2749 w->start_at_line_beg = p->start_at_line_beg;
2750 set_marker_restricted (w->start,
2751 Fmarker_position (p->start),
2752 w->buffer);
2753 set_marker_restricted (w->pointm,
2754 Fmarker_position (p->pointm),
2755 w->buffer);
2756 Fset_marker (XBUFFER (w->buffer)->mark,
2757 Fmarker_position (p->mark), w->buffer);
2758
2759 /* As documented in Fcurrent_window_configuration, don't
2760 save the location of point in the buffer which was current
2761 when the window configuration was recorded. */
6b54027b
RS
2762 if (!EQ (p->buffer, new_current_buffer)
2763 && XBUFFER (p->buffer) == current_buffer)
fd482be5
JB
2764 Fgoto_char (w->pointm);
2765 }
52a68e98
RS
2766 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
2767 /* Else unless window has a live buffer, get one. */
7ab12479 2768 {
fd482be5
JB
2769 w->buffer = Fcdr (Fcar (Vbuffer_alist));
2770 /* This will set the markers to beginning of visible
2771 range. */
2772 set_marker_restricted (w->start, make_number (0), w->buffer);
2773 set_marker_restricted (w->pointm, make_number (0),w->buffer);
2774 w->start_at_line_beg = Qt;
7ab12479
JB
2775 }
2776 else
fd482be5 2777 /* Keeping window's old buffer; make sure the markers
52a68e98 2778 are real. */
7ab12479 2779 {
fd482be5
JB
2780 /* Set window markers at start of visible range. */
2781 if (XMARKER (w->start)->buffer == 0)
2782 set_marker_restricted (w->start, make_number (0),
2783 w->buffer);
2784 if (XMARKER (w->pointm)->buffer == 0)
2785 set_marker_restricted (w->pointm,
2786 (make_number
2787 (BUF_PT (XBUFFER (w->buffer)))),
2788 w->buffer);
2789 w->start_at_line_beg = Qt;
7ab12479
JB
2790 }
2791 }
2792 }
9ace597f 2793
fd482be5
JB
2794 FRAME_ROOT_WINDOW (f) = data->root_window;
2795 Fselect_window (data->current_window);
7ab12479 2796
fd482be5 2797#ifdef MULTI_FRAME
db269683
JB
2798 if (NILP (data->focus_frame)
2799 || (XTYPE (data->focus_frame) == Lisp_Frame
2800 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
2801 Fredirect_frame_focus (frame, data->focus_frame);
fd482be5 2802#endif
7ab12479 2803
fd482be5
JB
2804#if 0 /* I don't understand why this is needed, and it causes problems
2805 when the frame's old selected window has been deleted. */
2806#ifdef MULTI_FRAME
2807 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
d5b2799e 2808 Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
fd482be5
JB
2809#endif
2810#endif
2811
2812 /* Set the screen height to the value it had before this function. */
2813 if (previous_frame_height != FRAME_HEIGHT (f)
2814 || previous_frame_width != FRAME_WIDTH (f))
2815 change_frame_size (f, previous_frame_height, previous_frame_width,
2816 0, 0);
217f2871 2817#ifdef HAVE_X_WINDOWS
8f6ea2e9
KH
2818 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
2819 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
217f2871 2820#endif
fd482be5 2821 }
bdc727bf 2822
ad854249 2823#ifdef MULTI_FRAME
bdc727bf 2824 /* Fselect_window will have made f the selected frame, so we
d5b2799e 2825 reselect the proper frame here. Fhandle_switch_frame will change the
bdc727bf
JB
2826 selected window too, but that doesn't make the call to
2827 Fselect_window above totally superfluous; it still sets f's
2828 selected window. */
fd482be5 2829 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
d5b2799e 2830 Fhandle_switch_frame (data->selected_frame, Qnil);
ad854249 2831#endif
bdc727bf
JB
2832
2833 if (!NILP (new_current_buffer))
2834 Fset_buffer (new_current_buffer);
2835
7ab12479
JB
2836 Vminibuf_scroll_window = data->minibuf_scroll_window;
2837 return (Qnil);
2838}
2839
44fa5b1e 2840/* Mark all windows now on frame as deleted
7ab12479
JB
2841 by setting their buffers to nil. */
2842
fd482be5 2843void
7ab12479
JB
2844delete_all_subwindows (w)
2845 register struct window *w;
2846{
265a9e55 2847 if (!NILP (w->next))
7ab12479 2848 delete_all_subwindows (XWINDOW (w->next));
265a9e55 2849 if (!NILP (w->vchild))
7ab12479 2850 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 2851 if (!NILP (w->hchild))
7ab12479 2852 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
2853
2854 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
2855
2856 /* We set all three of these fields to nil, to make sure that we can
2857 distinguish this dead window from any live window. Live leaf
2858 windows will have buffer set, and combination windows will have
2859 vchild or hchild set. */
2860 w->buffer = Qnil;
2861 w->vchild = Qnil;
2862 w->hchild = Qnil;
7ab12479
JB
2863}
2864\f
2865static int
2866count_windows (window)
2867 register struct window *window;
2868{
2869 register int count = 1;
265a9e55 2870 if (!NILP (window->next))
7ab12479 2871 count += count_windows (XWINDOW (window->next));
265a9e55 2872 if (!NILP (window->vchild))
7ab12479 2873 count += count_windows (XWINDOW (window->vchild));
265a9e55 2874 if (!NILP (window->hchild))
7ab12479
JB
2875 count += count_windows (XWINDOW (window->hchild));
2876 return count;
2877}
2878
2879static int
2880save_window_save (window, vector, i)
2881 Lisp_Object window;
2882 struct Lisp_Vector *vector;
2883 int i;
2884{
2885 register struct saved_window *p;
2886 register struct window *w;
2887 register Lisp_Object tem;
2888
265a9e55 2889 for (;!NILP (window); window = w->next)
7ab12479
JB
2890 {
2891 p = SAVED_WINDOW_N (vector, i);
2892 w = XWINDOW (window);
2893
2894 XFASTINT (w->temslot) = i++;
2895 p->window = window;
2896 p->buffer = w->buffer;
2897 p->left = w->left;
2898 p->top = w->top;
2899 p->width = w->width;
2900 p->height = w->height;
2901 p->hscroll = w->hscroll;
2902 p->display_table = w->display_table;
265a9e55 2903 if (!NILP (w->buffer))
7ab12479
JB
2904 {
2905 /* Save w's value of point in the window configuration.
2906 If w is the selected window, then get the value of point
2907 from the buffer; pointm is garbage in the selected window. */
2908 if (EQ (window, selected_window))
2909 {
2910 p->pointm = Fmake_marker ();
2911 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
2912 w->buffer);
2913 }
2914 else
2915 p->pointm = Fcopy_marker (w->pointm);
2916
2917 p->start = Fcopy_marker (w->start);
2918 p->start_at_line_beg = w->start_at_line_beg;
2919
2920 tem = XBUFFER (w->buffer)->mark;
2921 p->mark = Fcopy_marker (tem);
2922 }
2923 else
2924 {
2925 p->pointm = Qnil;
2926 p->start = Qnil;
2927 p->mark = Qnil;
2928 p->start_at_line_beg = Qnil;
2929 }
2930
265a9e55 2931 if (NILP (w->parent))
7ab12479
JB
2932 p->parent = Qnil;
2933 else
2934 p->parent = XWINDOW (w->parent)->temslot;
2935
265a9e55 2936 if (NILP (w->prev))
7ab12479
JB
2937 p->prev = Qnil;
2938 else
2939 p->prev = XWINDOW (w->prev)->temslot;
2940
265a9e55 2941 if (!NILP (w->vchild))
7ab12479 2942 i = save_window_save (w->vchild, vector, i);
265a9e55 2943 if (!NILP (w->hchild))
7ab12479
JB
2944 i = save_window_save (w->hchild, vector, i);
2945 }
2946
2947 return i;
2948}
2949
2950DEFUN ("current-window-configuration",
43bad991 2951 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
2952 "Return an object representing the current window configuration of FRAME.\n\
2953If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
2954This describes the number of windows, their sizes and current buffers,\n\
2955and for each displayed buffer, where display starts, and the positions of\n\
2956point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
2957its value is -not- saved.\n\
2958This also records the currently selected frame, and FRAME's focus\n\
2959redirection (see `redirect-frame-focus').")
44fa5b1e
JB
2960 (frame)
2961 Lisp_Object frame;
7ab12479
JB
2962{
2963 register Lisp_Object tem;
2964 register int n_windows;
2965 register struct save_window_data *data;
2966 register int i;
44fa5b1e 2967 FRAME_PTR f;
43bad991 2968
44fa5b1e
JB
2969 if (NILP (frame))
2970 f = selected_frame;
43bad991
JB
2971 else
2972 {
44fa5b1e
JB
2973 CHECK_LIVE_FRAME (frame, 0);
2974 f = XFRAME (frame);
43bad991 2975 }
7ab12479 2976
44fa5b1e 2977 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
7ab12479
JB
2978 data = (struct save_window_data *)
2979 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2980 Qnil));
44fa5b1e
JB
2981 XFASTINT (data->frame_width) = FRAME_WIDTH (f);
2982 XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
8f6ea2e9 2983 XFASTINT (data->frame_menu_bar_lines) = FRAME_MENU_BAR_LINES (f);
ad854249 2984#ifdef MULTI_FRAME
bdc727bf 2985 XSET (data->selected_frame, Lisp_Frame, selected_frame);
ad854249 2986#endif
44fa5b1e 2987 data->current_window = FRAME_SELECTED_WINDOW (f);
7ab12479
JB
2988 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2989 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 2990 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 2991 data->focus_frame = FRAME_FOCUS_FRAME (f);
7ab12479
JB
2992 tem = Fmake_vector (make_number (n_windows), Qnil);
2993 data->saved_windows = tem;
2994 for (i = 0; i < n_windows; i++)
2995 XVECTOR (tem)->contents[i]
2996 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 2997 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479
JB
2998 XVECTOR (tem), 0);
2999 XSET (tem, Lisp_Window_Configuration, data);
3000 return (tem);
3001}
3002
3003DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
3004 0, UNEVALLED, 0,
3005 "Execute body, preserving window sizes and contents.\n\
eb16ec06
RS
3006Restore which buffer appears in which window, where display starts,\n\
3007and the value of point and mark for each window.\n\
3008Also restore which buffer is current.\n\
3009But do not preserve point in the current buffer.\n\
7ab12479
JB
3010Does not restore the value of point in current buffer.")
3011 (args)
3012 Lisp_Object args;
3013{
3014 register Lisp_Object val;
3015 register int count = specpdl_ptr - specpdl;
3016
3017 record_unwind_protect (Fset_window_configuration,
43bad991 3018 Fcurrent_window_configuration (Qnil));
7ab12479
JB
3019 val = Fprogn (args);
3020 return unbind_to (count, val);
3021}
3022\f
3023init_window_once ()
3024{
44fa5b1e
JB
3025#ifdef MULTI_FRAME
3026 selected_frame = make_terminal_frame ();
3027 minibuf_window = selected_frame->minibuffer_window;
3028 selected_window = selected_frame->selected_window;
3029 last_nonminibuf_frame = selected_frame;
3030#else /* not MULTI_FRAME */
7ab12479
JB
3031 extern Lisp_Object get_minibuffer ();
3032
95605e15 3033 minibuf_window = make_window ();
4b206065 3034 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
7ab12479 3035
44fa5b1e
JB
3036 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
3037 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
4b206065 3038 XWINDOW (minibuf_window)->mini_p = Qt;
7ab12479
JB
3039
3040 /* These values 9 and 10 are arbitrary,
3041 just so that there is "something there."
3042 Correct values are put in in init_xdisp */
3043
44fa5b1e 3044 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
7ab12479
JB
3045 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
3046
44fa5b1e 3047 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
7ab12479
JB
3048 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
3049 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
3050
3051 /* Prevent error in Fset_window_buffer. */
44fa5b1e 3052 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
7ab12479
JB
3053 XWINDOW (minibuf_window)->buffer = Qt;
3054
3055 /* Now set them up for real. */
44fa5b1e 3056 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
e5d77022 3057 Fcurrent_buffer ());
7ab12479
JB
3058 Fset_window_buffer (minibuf_window, get_minibuffer (0));
3059
44fa5b1e 3060 selected_window = FRAME_ROOT_WINDOW (selected_frame);
1d8d96fa
JB
3061 /* Make sure this window seems more recently used than
3062 a newly-created, never-selected window. Increment
3063 window_select_count so the first selection ever will get
3064 something newer than this. */
3065 XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
44fa5b1e 3066#endif /* not MULTI_FRAME */
7ab12479
JB
3067}
3068
3069syms_of_window ()
3070{
3071 Qwindowp = intern ("windowp");
3072 staticpro (&Qwindowp);
3073
806b4d9b
JB
3074 Qwindow_live_p = intern ("window-live-p");
3075 staticpro (&Qwindow_live_p);
605be8af 3076
2f83aebe 3077#ifndef MULTI_FRAME
7ab12479
JB
3078 /* Make sure all windows get marked */
3079 staticpro (&minibuf_window);
2f83aebe 3080#endif
7ab12479
JB
3081
3082 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
3083 "Non-nil means call as function to display a help buffer.\n\
3084Used by `with-output-to-temp-buffer'.");
3085 Vtemp_buffer_show_function = Qnil;
3086
3087 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
3088 "If non-nil, function to call to handle `display-buffer'.\n\
3089It will receive two args, the buffer and a flag which if non-nil means\n\
3090 that the currently selected window is not acceptable.\n\
3091Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3092work using this function.");
3093 Vdisplay_buffer_function = Qnil;
3094
7ab12479
JB
3095 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3096 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3097 Vminibuf_scroll_window = Qnil;
3098
3099 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3100 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3101 Vother_window_scroll_buffer = Qnil;
3102
44fa5b1e 3103 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 3104 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 3105 pop_up_frames = 0;
7ab12479 3106
44fa5b1e 3107 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
a90712c2 3108 "Function to call to handle automatic new frame creation.\n\
44fa5b1e 3109It is called with no arguments and should return a newly created frame.\n\
7ab12479 3110\n\
44fa5b1e
JB
3111A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3112where `pop-up-frame-alist' would hold the default frame parameters.");
3113 Vpop_up_frame_function = Qnil;
7ab12479 3114
a90712c2
RS
3115 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
3116 "*List of buffer names that should have their own special frames.\n\
3117Displaying a buffer whose name is in this list makes a special frame for it\n\
3118using `special-display-function'. See also `special-display-regexps'.");
3119 Vspecial_display_buffer_names = Qnil;
3120
3121 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
3122 "*List of regexps saying which buffers should have their own special frames.\n\
3123If a buffer name matches one of these regexps, it gets its own frame.\n\
3124Displaying a buffer whose name is in this list makes a special frame for it\n\
3125using `special-display-function'. See also `special-display-buffer-names'.");
3126 Vspecial_display_regexps = Qnil;
3127
3128 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
3129 "Function to call to make a new frame for a special buffer.\n\
3130It is called with one argument, the buffer,\n\
3131and should return a window displaying that buffer.\n\
3132The default value makes a separate frame for the buffer,\n\
3133using `special-display-alist' to specify the frame parameters.\n\
3134\n\
3135A buffer is special if its is listed in `special-display-buffer-names'\n\
3136or matches a regexp in `special-display-regexps'.");
3137 Vspecial_display_function = Qnil;
3138
7ab12479
JB
3139 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3140 "*Non-nil means display-buffer should make new windows.");
3141 pop_up_windows = 1;
3142
3143 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3144 "*Number of lines of continuity when scrolling by screenfuls.");
3145 next_screen_context_lines = 2;
3146
3147 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3148 "*display-buffer would prefer to split the largest window if this large.\n\
3149If there is only one window, it is split regardless of this value.");
3150 split_height_threshold = 500;
3151
3152 DEFVAR_INT ("window-min-height", &window_min_height,
3153 "*Delete any window less than this tall (including its mode line).");
3154 window_min_height = 4;
3155
3156 DEFVAR_INT ("window-min-width", &window_min_width,
3157 "*Delete any window less than this wide.");
3158 window_min_width = 10;
3159
3160 defsubr (&Sselected_window);
3161 defsubr (&Sminibuffer_window);
3162 defsubr (&Swindow_minibuffer_p);
3163 defsubr (&Swindowp);
806b4d9b 3164 defsubr (&Swindow_live_p);
7ab12479
JB
3165 defsubr (&Spos_visible_in_window_p);
3166 defsubr (&Swindow_buffer);
3167 defsubr (&Swindow_height);
3168 defsubr (&Swindow_width);
3169 defsubr (&Swindow_hscroll);
3170 defsubr (&Sset_window_hscroll);
3171 defsubr (&Swindow_edges);
d5783c40
JB
3172 defsubr (&Scoordinates_in_window_p);
3173 defsubr (&Swindow_at);
7ab12479
JB
3174 defsubr (&Swindow_point);
3175 defsubr (&Swindow_start);
3176 defsubr (&Swindow_end);
3177 defsubr (&Sset_window_point);
3178 defsubr (&Sset_window_start);
3179 defsubr (&Swindow_dedicated_p);
d207b766 3180 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
3181 defsubr (&Swindow_display_table);
3182 defsubr (&Sset_window_display_table);
3183 defsubr (&Snext_window);
3184 defsubr (&Sprevious_window);
3185 defsubr (&Sother_window);
3186 defsubr (&Sget_lru_window);
3187 defsubr (&Sget_largest_window);
3188 defsubr (&Sget_buffer_window);
3189 defsubr (&Sdelete_other_windows);
3190 defsubr (&Sdelete_windows_on);
3191 defsubr (&Sreplace_buffer_in_windows);
3192 defsubr (&Sdelete_window);
3193 defsubr (&Sset_window_buffer);
3194 defsubr (&Sselect_window);
3195 defsubr (&Sdisplay_buffer);
3196 defsubr (&Ssplit_window);
3197 defsubr (&Senlarge_window);
3198 defsubr (&Sshrink_window);
3199 defsubr (&Sscroll_up);
3200 defsubr (&Sscroll_down);
3201 defsubr (&Sscroll_left);
3202 defsubr (&Sscroll_right);
ccd0664b 3203 defsubr (&Sother_window_for_scrolling);
7ab12479
JB
3204 defsubr (&Sscroll_other_window);
3205 defsubr (&Srecenter);
3206 defsubr (&Smove_to_window_line);
3207 defsubr (&Swindow_configuration_p);
3208 defsubr (&Sset_window_configuration);
3209 defsubr (&Scurrent_window_configuration);
3210 defsubr (&Ssave_window_excursion);
3211}
3212
3213keys_of_window ()
3214{
3215 initial_define_key (control_x_map, '1', "delete-other-windows");
3216 initial_define_key (control_x_map, '2', "split-window");
3217 initial_define_key (control_x_map, '0', "delete-window");
3218 initial_define_key (control_x_map, 'o', "other-window");
3219 initial_define_key (control_x_map, '^', "enlarge-window");
3220 initial_define_key (control_x_map, '<', "scroll-left");
3221 initial_define_key (control_x_map, '>', "scroll-right");
3222
3223 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3224 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3225 initial_define_key (meta_map, 'v', "scroll-down");
3226
3227 initial_define_key (global_map, Ctl('L'), "recenter");
3228 initial_define_key (meta_map, 'r', "move-to-window-line");
3229}