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