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