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