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