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