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