1 /* Window creation, deletion and examination for XEmacs.
2 Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1996 Chuck Thompson.
7 This file is part of XEmacs.
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
24 /* Synched up with: FSF 19.30. */
25 /* Beginning to diverge significantly. */
27 /* This file has been Mule-ized. */
37 #include "redisplay.h"
43 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
44 Lisp_Object Qscroll_up, Qscroll_down, Qdisplay_buffer;
46 #ifdef MEMORY_USAGE_STATS
47 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
48 #ifdef HAVE_SCROLLBARS
49 Lisp_Object Qscrollbar_instances;
53 EXFUN (Fnext_window, 4);
55 static int window_pixel_width_to_char_width (struct window *w,
57 int include_margins_p);
58 static int window_char_width_to_pixel_width (struct window *w,
60 int include_margins_p);
61 static int window_pixel_height_to_char_height (struct window *w,
63 int include_gutters_p);
64 static int window_char_height_to_pixel_height (struct window *w,
66 int include_gutters_p);
67 static void change_window_height (struct window *w, int delta, int widthflag,
70 /* Thickness of shadow border around 3d modelines. */
71 Lisp_Object Vmodeline_shadow_thickness;
73 /* Whether vertical dividers are draggable and displayed */
74 Lisp_Object Vvertical_divider_always_visible_p;
76 /* Whether a modeline should be displayed. */
77 Lisp_Object Vhas_modeline_p;
79 /* Thickness of shadow border around vertical dividers. */
80 Lisp_Object Vvertical_divider_shadow_thickness;
82 /* Divider surface width (not counting 3-d borders) */
83 Lisp_Object Vvertical_divider_line_width;
85 /* Spacing between outer egde of divider border and window edge */
86 Lisp_Object Vvertical_divider_spacing;
88 /* Scroll if point lands on the bottom line and that line is partially
90 int scroll_on_clipped_lines;
92 /* The minibuffer window of the selected frame.
93 Note that you cannot test for minibufferness of an arbitrary window
94 by comparing against this; but you can test for minibufferness of
95 the selected window. */
96 Lisp_Object minibuf_window;
98 /* Non-nil means it is the window for C-M-v to scroll
99 when the minibuffer is selected. */
100 Lisp_Object Vminibuffer_scroll_window;
102 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
103 Lisp_Object Vother_window_scroll_buffer;
105 /* Non-nil means it's the function to call to display temp buffers. */
106 Lisp_Object Vtemp_buffer_show_function;
108 Lisp_Object Vtemp_buffer_show_hook;
110 /* If a window gets smaller than either of these, it is removed. */
111 int window_min_height;
112 int window_min_width;
114 /* Hook run at end of temp_output_buffer_show. */
115 Lisp_Object Qtemp_buffer_show_hook;
117 /* Number of lines of continuity in scrolling by screenfuls. */
118 int next_screen_context_lines;
120 /* List of freed window configurations with 1 - 10 windows. */
121 Lisp_Object Vwindow_configuration_free_list[10];
123 #define SET_LAST_MODIFIED(w, cache_too) \
125 (w)->last_modified[CURRENT_DISP] = Qzero; \
126 (w)->last_modified[DESIRED_DISP] = Qzero; \
127 (w)->last_modified[CMOTION_DISP] = Qzero; \
129 (w)->line_cache_last_updated = Qzero; \
132 #define SET_LAST_FACECHANGE(w) \
134 (w)->last_facechange[CURRENT_DISP] = Qzero; \
135 (w)->last_facechange[DESIRED_DISP] = Qzero; \
136 (w)->last_facechange[CMOTION_DISP] = Qzero; \
140 #define MARK_DISP_VARIABLE(field) \
141 markobj (window->field[CURRENT_DISP]); \
142 markobj (window->field[DESIRED_DISP]); \
143 markobj (window->field[CMOTION_DISP]);
146 mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object))
148 struct window *window = XWINDOW (obj);
149 markobj (window->frame);
150 markobj (window->mini_p);
151 markobj (window->next);
152 markobj (window->prev);
153 markobj (window->hchild);
154 markobj (window->vchild);
155 markobj (window->parent);
156 markobj (window->buffer);
157 MARK_DISP_VARIABLE (start);
158 MARK_DISP_VARIABLE (pointm);
159 markobj (window->sb_point); /* #### move to scrollbar.c? */
160 markobj (window->use_time);
161 MARK_DISP_VARIABLE (last_modified);
162 MARK_DISP_VARIABLE (last_point);
163 MARK_DISP_VARIABLE (last_start);
164 MARK_DISP_VARIABLE (last_facechange);
165 markobj (window->line_cache_last_updated);
166 markobj (window->redisplay_end_trigger);
167 markobj (window->subwindow_instance_cache);
169 mark_face_cachels (window->face_cachels, markobj);
170 mark_glyph_cachels (window->glyph_cachels, markobj);
172 #define WINDOW_SLOT(slot, compare) ((void) (markobj (window->slot)))
173 #include "winslots.h"
179 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
184 error ("printing unreadable object #<window 0x%x>",
185 XWINDOW (obj)->header.uid);
187 write_c_string ("#<window", printcharfun);
188 if (!NILP (XWINDOW (obj)->buffer))
190 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
191 write_c_string (" on ", printcharfun);
192 print_internal (name, printcharfun, 1);
194 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
195 write_c_string (buf, printcharfun);
199 finalize_window (void *header, int for_disksave)
201 struct window *w = (struct window *) header;
203 if (w->line_start_cache)
205 Dynarr_free (w->line_start_cache);
206 w->line_start_cache = 0;
213 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
215 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
216 if (cachel->merged_faces)
218 Dynarr_free (cachel->merged_faces);
219 cachel->merged_faces = 0;
222 Dynarr_free (w->face_cachels);
226 if (w->glyph_cachels)
228 Dynarr_free (w->glyph_cachels);
229 w->glyph_cachels = 0;
233 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
234 mark_window, print_window, finalize_window,
235 0, 0, 0, struct window);
238 #define INIT_DISP_VARIABLE(field, initialization) \
239 p->field[CURRENT_DISP] = initialization; \
240 p->field[DESIRED_DISP] = initialization; \
241 p->field[CMOTION_DISP] = initialization;
243 /* We have an implicit assertion that the first two elements (default
244 and modeline faces) are always present in the face_element_cache.
245 Normally redisplay ensures this. However, it is possible for a
246 window to get created and functions which reference these values
247 called before redisplay works with the window for the first time.
248 All callers of allocate_window should therefore call
249 reset_face_cachels on the created window. We can't do it
250 here because the window must have its frame pointer set or
251 reset_face_cachels will fail. */
253 allocate_window (void)
256 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
270 INIT_DISP_VARIABLE (start, Fmake_marker ());
271 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
272 p->sb_point = Fmake_marker ();
274 INIT_DISP_VARIABLE (last_modified, Qzero);
275 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
276 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
277 INIT_DISP_VARIABLE (last_facechange, Qzero);
278 p->face_cachels = Dynarr_new (face_cachel);
279 p->glyph_cachels = Dynarr_new (glyph_cachel);
280 p->line_start_cache = Dynarr_new (line_start_cache);
281 p->subwindow_instance_cache = make_lisp_hash_table (10,
284 p->line_cache_last_updated = Qzero;
285 INIT_DISP_VARIABLE (last_point_x, 0);
286 INIT_DISP_VARIABLE (last_point_y, 0);
287 INIT_DISP_VARIABLE (window_end_pos, 0);
288 p->redisplay_end_trigger = Qnil;
290 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
291 #include "winslots.h"
293 p->windows_changed = 1;
294 p->shadow_thickness_changed = 1;
298 #undef INIT_DISP_VARIABLE
301 * The redisplay structures used to be stored with each window. While
302 * they are logically something associated with frames they can't be
303 * stored there with a redisplay which handles variable height lines.
304 * Lines in horizontally split windows might not line up. So they get
305 * stored with the windows.
307 * The problem with this is window configurations. When restoring a
308 * window configuration it now becomes problematic to do an
309 * incremental redisplay. The solution is to store the redisplay
310 * structures with the frame as they should be but laid out in the
311 * same manner as the window structure. Thus is born the window
314 * It also becomes a convenient place to stick scrollbar instances
315 * since they extrapolate out to having the same problem described for
316 * the display structures.
319 /* Create a new window mirror structure and associated redisplay
321 static struct window_mirror *
322 new_window_mirror (struct frame *f)
324 struct window_mirror *t = xnew_and_zero (struct window_mirror);
328 t->current_display_lines = Dynarr_new (display_line);
329 t->desired_display_lines = Dynarr_new (display_line);
332 #ifdef HAVE_SCROLLBARS
333 t->scrollbar_vertical_instance = NULL;
334 t->scrollbar_horizontal_instance = NULL;
340 /* Synchronize the mirror structure with a given window structure.
341 This is normally called from update_frame_window_mirror with a
342 starting window of f->root_window. */
343 static struct window_mirror *
344 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
350 free_window_mirror (mir);
357 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
359 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
360 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
361 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
364 * If the redisplay structs are not empty and the mirror has
365 * children, then this mirror structure was formerly being used for
366 * display but is no longer. Reset its current display structs so
367 * that redisplay doesn't accidentally think they are accurate if it
368 * is later used for display purposes once again. Also, mark the
369 * scrollbar instance as not active.
371 if (mir->vchild || mir->hchild)
373 /* The redisplay structures are big. Leaving them around in
374 non-leaf windows can add up to a lot of wasted space. So
376 free_display_structs (mir);
377 mir->current_display_lines = Dynarr_new (display_line);
378 mir->desired_display_lines = Dynarr_new (display_line);
380 #ifdef HAVE_SCROLLBARS
381 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
389 /* Given a window mirror, determine which real window it contains the
390 redisplay structures for. */
392 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
393 struct window_mirror *mir)
395 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
399 if (!NILP (XWINDOW (win)->vchild))
402 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
406 if (!NILP (XWINDOW (win)->hchild))
409 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
418 /* Given a real window, find the mirror structure which contains its
419 redisplay structures. */
420 static struct window_mirror *
421 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
424 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
426 if (w == XWINDOW (win))
429 if (!NILP (XWINDOW (win)->vchild))
431 struct window_mirror *retval =
432 find_window_mirror_internal (XWINDOW (win)->vchild,
434 if (retval) return retval;
437 if (!NILP (XWINDOW (win)->hchild))
439 struct window_mirror *retval =
440 find_window_mirror_internal (XWINDOW (win)->hchild,
442 if (retval) return retval;
449 /* Update the mirror structure for the given frame. */
451 update_frame_window_mirror (struct frame *f)
453 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
457 /* Free a given mirror structure along with all of its children as
458 well as their associated display structures. */
460 free_window_mirror (struct window_mirror *mir)
464 struct window_mirror *prev = mir;
465 if (mir->hchild) free_window_mirror (mir->hchild);
466 if (mir->vchild) free_window_mirror (mir->vchild);
467 #ifdef HAVE_SCROLLBARS
468 release_window_mirror_scrollbars (mir);
470 free_display_structs (mir);
476 /* Given a mirror structure, return the window it mirrors. Calls
477 real_window_internal to do most of the work. */
479 real_window (struct window_mirror *mir, int no_abort)
481 Lisp_Object retval = real_window_internal (mir->frame->root_window,
482 mir->frame->root_mirror, mir);
483 if (NILP (retval) && !no_abort)
489 /* Given a real window, return its mirror structure. Calls
490 find_window_mirror_internal to do all of the work. */
491 struct window_mirror *
492 find_window_mirror (struct window *w)
494 struct frame *f = XFRAME (w->frame);
496 update_frame_window_mirror (f);
497 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
500 /*****************************************************************************
501 find_window_by_pixel_pos
503 Given a pixel position relative to a frame, find the window at that
505 ****************************************************************************/
507 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
512 for (; !NILP (win); win = XWINDOW (win)->next)
516 if (!NILP (XWINDOW (win)->vchild))
518 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
521 if (!NILP (XWINDOW (win)->hchild))
523 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
527 if (pix_x >= WINDOW_LEFT (w)
528 && pix_x <= WINDOW_RIGHT (w)
529 && pix_y >= WINDOW_TOP (w)
530 && pix_y <= WINDOW_BOTTOM (w))
536 /* Return a pointer to the display structures for the given window. */
537 display_line_dynarr *
538 window_display_lines (struct window *w, int which)
540 struct window_mirror *t;
542 if (XFRAME (w->frame)->mirror_dirty)
543 update_frame_window_mirror (XFRAME (w->frame));
544 t = find_window_mirror (w);
548 if (which == CURRENT_DISP)
549 return t->current_display_lines;
550 else if (which == DESIRED_DISP)
551 return t->desired_display_lines;
552 else if (which == CMOTION_DISP)
553 /* The CMOTION_DISP display lines are global. */
554 return cmotion_display_lines;
558 return 0; /* shut up compiler */
562 window_display_buffer (struct window *w)
564 struct window_mirror *t;
566 if (XFRAME (w->frame)->mirror_dirty)
567 update_frame_window_mirror (XFRAME (w->frame));
568 t = find_window_mirror (w);
576 set_window_display_buffer (struct window *w, struct buffer *b)
578 struct window_mirror *t;
580 if (XFRAME (w->frame)->mirror_dirty)
581 update_frame_window_mirror (XFRAME (w->frame));
582 t = find_window_mirror (w);
590 /* Determining a window's position based solely on its pixel
591 positioning doesn't work. Instead, we do it the intelligent way,
592 by checking its positioning in the window hierarchy. */
594 window_is_leftmost (struct window *w)
596 Lisp_Object parent, current_ancestor, window;
598 XSETWINDOW (window, w);
600 parent = XWINDOW (window)->parent;
601 current_ancestor = window;
603 while (!NILP (parent))
605 if (!NILP (XWINDOW (parent)->hchild) &&
606 !EQ (XWINDOW (parent)->hchild, current_ancestor))
609 current_ancestor = parent;
610 parent = XWINDOW (parent)->parent;
617 window_is_rightmost (struct window *w)
619 Lisp_Object parent, current_ancestor, window;
621 XSETWINDOW (window, w);
623 parent = XWINDOW (window)->parent;
624 current_ancestor = window;
626 while (!NILP (parent))
628 if (!NILP (XWINDOW (parent)->hchild)
629 && !NILP (XWINDOW (current_ancestor)->next))
632 current_ancestor = parent;
633 parent = XWINDOW (parent)->parent;
640 window_full_width_p (struct window *w)
642 return window_is_leftmost (w) && window_is_rightmost (w);
646 window_is_highest (struct window *w)
648 Lisp_Object parent, current_ancestor, window;
650 XSETWINDOW (window, w);
652 parent = XWINDOW (window)->parent;
653 current_ancestor = window;
655 while (!NILP (parent))
657 if (!NILP (XWINDOW (parent)->vchild) &&
658 !EQ (XWINDOW (parent)->vchild, current_ancestor))
661 current_ancestor = parent;
662 parent = XWINDOW (parent)->parent;
665 /* This is really to catch the minibuffer but we make it generic in
666 case we ever change things around to let the minibuffer be on top. */
667 if (NILP (XWINDOW (current_ancestor)->prev))
674 window_is_lowest (struct window *w)
676 Lisp_Object parent, current_ancestor, window;
678 XSETWINDOW (window, w);
680 parent = XWINDOW (window)->parent;
681 current_ancestor = window;
683 while (!NILP (parent))
685 if (!NILP (XWINDOW (parent)->vchild)
686 && !NILP (XWINDOW (current_ancestor)->next))
689 current_ancestor = parent;
690 parent = XWINDOW (parent)->parent;
696 #if 0 /* not currently used */
699 window_full_height_p (struct window *w)
701 return window_is_highest (w) && window_is_lowest (w);
707 window_truncation_on (struct window *w)
709 /* Horizontally scrolled windows are truncated. */
713 /* If truncate_partial_width_windows is true and the window is not
714 the full width of the frame it is truncated. */
715 if (truncate_partial_width_windows
716 && !(window_is_leftmost (w) && window_is_rightmost (w)))
719 /* If the window's buffer's value of truncate_lines is non-nil, then
720 the window is truncated. */
721 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
728 have_undivided_common_edge (struct window *w_right, void *closure)
730 struct window *w_left = (struct window *) closure;
731 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
732 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
733 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
734 #ifdef HAVE_SCROLLBARS
735 && (NILP (w_right->scrollbar_on_left_p)
736 || NILP (w_right->vertical_scrollbar_visible_p)
737 || ZEROP (w_right->scrollbar_width))
743 window_needs_vertical_divider_1 (struct window *w)
745 /* Never if we're on the right */
746 if (window_is_rightmost (w))
749 /* Always if draggable */
750 if (!NILP (w->vertical_divider_always_visible_p))
753 #ifdef HAVE_SCROLLBARS
754 /* Our right scrollbar is enough to separate us at the right */
755 if (NILP (w->scrollbar_on_left_p)
756 && !NILP (w->vertical_scrollbar_visible_p)
757 && !ZEROP (w->scrollbar_width))
761 /* Ok. to determine whether we need a divider on the left, we must
762 check that our right neighbor windows have scrollbars on their
763 left sides. We must check all such windows which have common
764 left edge with our window's right edge. */
765 return map_windows (XFRAME (WINDOW_FRAME (w)),
766 have_undivided_common_edge, (void*)w);
770 window_needs_vertical_divider (struct window *w)
772 if (!w->need_vertical_divider_valid_p)
774 w->need_vertical_divider_p =
775 window_needs_vertical_divider_1 (w);
776 w->need_vertical_divider_valid_p = 1;
778 return w->need_vertical_divider_p;
781 /* Called from invalidate_vertical_divider_cache_in_frame */
783 invalidate_vertical_divider_cache_in_window (struct window *w,
786 w->need_vertical_divider_valid_p = 0;
790 /* Calculate width of vertical divider, including its shadows
791 and spacing. The returned value is effectively the distance
792 between adjacent window edges. This function does not check
793 whether a window needs a vertical divider, so the returned
794 value is a "theoretical" one */
796 window_divider_width (struct window *w)
798 /* the shadow thickness can be negative. This means that the divider
799 will have a depressed look */
801 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
803 XINT (w->vertical_divider_line_width)
804 + 2 * XINT (w->vertical_divider_spacing)
805 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
807 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
811 window_scrollbar_width (struct window *w)
813 #ifdef HAVE_SCROLLBARS
814 if (!WINDOW_WIN_P (w)
817 || NILP (w->vertical_scrollbar_visible_p))
818 /* #### when does NILP (w->buffer) happen? */
821 return XINT (w->scrollbar_width);
824 #endif /* HAVE_SCROLLBARS */
827 /* Horizontal scrollbars are only active on windows with truncation
830 window_scrollbar_height (struct window *w)
832 #ifdef HAVE_SCROLLBARS
833 if (!WINDOW_WIN_P (w)
836 || NILP (w->horizontal_scrollbar_visible_p)
837 || !window_truncation_on (w))
840 return XINT (w->scrollbar_height);
843 #endif /* HAVE_SCROLLBARS */
847 window_modeline_height (struct window *w)
849 struct frame *f = XFRAME (w->frame);
852 if (MINI_WINDOW_P (w) || NILP (w->buffer))
856 else if (!WINDOW_HAS_MODELINE_P (w))
858 if (window_scrollbar_height (w))
862 modeline_height = FRAMEMETH (f, divider_height, ());
864 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
865 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
874 display_line_dynarr *dla;
876 /* We don't force a regeneration of the modeline here.
877 Instead it is now a precondition that any function calling
878 this should make sure that one of these structures is
879 up-to-date. In practice this only affects two internal
880 redisplay functions, regenerate_window and
881 regenerate_window_point_center. */
882 /* We check DESIRED_DISP because if it is valid it is more
883 up-to-date than CURRENT_DISP. For calls to this outside
884 of redisplay it doesn't matter which structure we check
885 since there is a redisplay condition that these
886 structures be identical outside of redisplay. */
887 dla = window_display_lines (w, DESIRED_DISP);
888 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
889 modeline_height = (Dynarr_atp (dla, 0)->ascent +
890 Dynarr_atp (dla, 0)->descent);
893 dla = window_display_lines (w, CURRENT_DISP);
894 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
895 modeline_height = (Dynarr_atp (dla, 0)->ascent +
896 Dynarr_atp (dla, 0)->descent);
898 /* This should be an abort except I'm not yet 100%
899 confident that it won't ever get hit (though I
900 haven't been able to trigger it). It is extremely
901 unlikely to cause any noticeable problem and even if
902 it does it will be a minor display glitch. */
903 /* #### Bullshit alert. It does get hit and it causes
904 noticeable glitches. real_current_modeline_height
905 is a kludge to fix this for 19.14. */
906 modeline_height = real_current_modeline_height (w);
909 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
910 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
914 return modeline_height;
917 /*****************************************************************************
918 margin_width_internal
920 For a given window, return the width in pixels of the specified margin.
921 ****************************************************************************/
923 margin_width_internal (struct window *w, int left_margin)
926 int window_cwidth = window_char_width (w, 1);
931 /* We might be getting called on a non-leaf. */
932 if (NILP (w->buffer))
935 /* The minibuffer never has margins. */
936 if (MINI_WINDOW_P (w))
939 XSETWINDOW (window, w);
940 b = XBUFFER (w->buffer);
941 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
942 XINT (w->right_margin_width));
944 default_face_height_and_width (window, 0, &font_width);
946 /* The left margin takes precedence over the right margin so we
947 subtract its width from the space available for the right
950 window_cwidth -= XINT (w->left_margin_width);
952 /* The margin cannot be wider than the window is. We allow the
953 value to be bigger since it is possible for the user to enlarge
954 the window such that the left margin value would no longer be too
955 big, but we won't return a value that is larger. */
956 if (margin_cwidth > window_cwidth)
957 margin_cwidth = window_cwidth;
959 /* At the user level the margin is always specified in characters.
960 Internally however it is manipulated in terms of pixels. */
961 return margin_cwidth * font_width;
965 window_left_margin_width (struct window *w)
967 return margin_width_internal (w, 1);
971 window_right_margin_width (struct window *w)
973 return margin_width_internal (w, 0);
976 /*****************************************************************************
979 The gutters of a window are those areas in the boundary defined by
980 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
981 do not contain text. Items which may be in the gutters include
982 scrollbars, toolbars and modelines. The margin areas are not
983 included. This is an exception made because redisplay special cases
984 the handling of those areas in many places in such a way that
985 including them in the gutter area would make life difficult.
987 The size functions refer to height for the bottom and top gutters and
988 width for the left and right gutters. The starting position
989 functions refer to the Y coord for bottom and top gutters and the X
990 coord for left and right gutters. All starting positions are
991 relative to the frame, not the window.
992 ****************************************************************************/
995 window_top_gutter_height (struct window *w)
997 int gutter = WINDOW_REAL_TOP_GUTTER_BOUNDS (w);
999 if (!NILP (w->hchild) || !NILP (w->vchild))
1002 #ifdef HAVE_SCROLLBARS
1003 if (!NILP (w->scrollbar_on_top_p))
1004 return window_scrollbar_height (w) + gutter;
1011 window_bottom_gutter_height (struct window *w)
1013 int gutter = WINDOW_REAL_BOTTOM_GUTTER_BOUNDS (w);
1015 if (!NILP (w->hchild) || !NILP (w->vchild))
1018 gutter += window_modeline_height (w);
1020 #ifdef HAVE_SCROLLBARS
1021 if (NILP (w->scrollbar_on_top_p))
1022 return window_scrollbar_height (w) + gutter;
1029 window_left_gutter_width (struct window *w, int modeline)
1031 int gutter = WINDOW_REAL_LEFT_GUTTER_BOUNDS (w);
1033 if (!NILP (w->hchild) || !NILP (w->vchild))
1036 #ifdef HAVE_SCROLLBARS
1037 if (!modeline && !NILP (w->scrollbar_on_left_p))
1038 gutter += window_scrollbar_width (w);
1045 window_right_gutter_width (struct window *w, int modeline)
1047 int gutter = WINDOW_REAL_RIGHT_GUTTER_BOUNDS (w);
1049 if (!NILP (w->hchild) || !NILP (w->vchild))
1052 #ifdef HAVE_SCROLLBARS
1053 if (!modeline && NILP (w->scrollbar_on_left_p))
1054 gutter += window_scrollbar_width (w);
1057 if (window_needs_vertical_divider (w))
1058 gutter += window_divider_width (w);
1064 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1065 Return t if OBJ is a window.
1069 return WINDOWP (obj) ? Qt : Qnil;
1072 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1073 Return t if OBJ is a window which is currently visible.
1077 return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
1080 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1081 Return the window that the cursor now appears in and commands apply to.
1082 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1083 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1084 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1085 is a console, the selected frame on that console's selected device will
1086 be used. Otherwise, the selected frame is used.
1090 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1091 return Qnil; /* happens at startup */
1094 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1095 return FRAME_SELECTED_WINDOW (f);
1099 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1100 Return the window used now for minibuffers.
1101 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1102 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1103 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1104 is a console, the selected frame on that console's selected device will
1105 be used. Otherwise, the selected frame is used.
1109 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1112 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 1, 1, 0, /*
1113 Return non-nil if WINDOW is a minibuffer window.
1117 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1120 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1121 Return the first horizontal child of WINDOW, or nil.
1125 return decode_window (window)->hchild;
1128 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1129 Return the first vertical child of WINDOW, or nil.
1133 return decode_window (window)->vchild;
1136 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1137 Return the next window on the same level as WINDOW, or nil.
1141 return decode_window (window)->next;
1144 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1145 Return the previous window on the same level as WINDOW, or nil.
1149 return decode_window (window)->prev;
1152 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1153 Return the parent of WINDOW, or nil.
1157 return decode_window (window)->parent;
1160 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1161 Return non-nil if WINDOW is along the bottom of its frame.
1165 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1168 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1169 Return non-nil if WINDOW is along the top of its frame.
1173 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1176 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1177 Return non-nil if WINDOW is along the left edge of its frame.
1181 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1184 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1185 Return non-nil if WINDOW is along the right edge of its frame.
1189 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1192 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1193 Return t if position POS is currently on the frame in WINDOW.
1194 Returns nil if that position is scrolled vertically out of view.
1195 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1199 struct window *w = decode_window (window);
1200 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1202 struct buffer *buf = XBUFFER (w->buffer);
1205 posint = BUF_PT (buf);
1208 CHECK_INT_COERCE_MARKER (pos);
1209 posint = XINT (pos);
1212 if (posint < top || posint > BUF_ZV (buf))
1215 /* w->start can be out of range. If it is, do something reasonable. */
1216 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1219 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1224 decode_window (Lisp_Object window)
1227 return XWINDOW (Fselected_window (Qnil));
1229 CHECK_LIVE_WINDOW (window);
1230 return XWINDOW (window);
1233 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1234 Return the buffer that WINDOW is displaying.
1238 return decode_window (window)->buffer;
1241 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1242 Return the frame that window WINDOW is on.
1246 return decode_window (window)->frame;
1249 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1250 Return the number of default lines in WINDOW.
1251 This actually works by dividing the window's pixel height (including
1252 the modeline and horizontal scrollbar, if any) by the height of the
1253 default font; therefore, the number of displayed lines will probably
1255 Use `window-height' to get consistent results in geometry calculations.
1256 Use `window-displayed-height' to get the actual number of lines
1257 currently displayed in a window.
1261 return make_int (window_char_height (decode_window (window), 1));
1264 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1265 Return the number of lines currently displayed in WINDOW.
1266 This counts the actual number of lines displayed in WINDOW
1267 \(as opposed to `window-height'). The modeline and horizontal
1268 scrollbar do not count as lines. If there is some blank space
1269 between the end of the buffer and the end of the window, this
1270 function pretends that there are lines of text in the default
1275 return make_int (window_displayed_height (decode_window (window)));
1278 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1279 Return the height of WINDOW in pixels. Defaults to current window.
1280 This includes the window's modeline and horizontal scrollbar (if any).
1284 return make_int (decode_window (window)->pixel_height);
1287 DEFUN ("window-text-area-pixel-height",
1288 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1289 Return the height in pixels of the text-displaying portion of WINDOW.
1290 Unlike `window-pixel-height', the space occupied by the modeline and
1291 horizontal scrollbar, if any, is not counted.
1295 struct window *w = decode_window (window);
1297 return make_int (WINDOW_TEXT_HEIGHT (w));
1300 DEFUN ("window-displayed-text-pixel-height",
1301 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1302 Return the height in pixels of the text displayed in WINDOW.
1303 Unlike `window-text-area-pixel-height', any blank space below the
1304 end of the buffer is not included. If optional argument NOCLIPPED
1305 is non-nil, do not include space occupied by clipped lines.
1307 (window, noclipped))
1310 Bufpos start, eobuf;
1312 int hlimit, height, prev_height = -1;
1316 line_start_cache_dynarr *cache;
1319 window = Fselected_window (Qnil);
1321 CHECK_LIVE_WINDOW (window);
1322 w = XWINDOW (window);
1324 start = marker_position (w->start[CURRENT_DISP]);
1325 hlimit = WINDOW_TEXT_HEIGHT (w);
1326 eobuf = BUF_ZV (XBUFFER (w->buffer));
1328 default_face_height_and_width (window, &defheight, NULL);
1330 /* guess lines needed in line start cache + a few extra */
1331 needed = (hlimit + defheight-1) / defheight + 3;
1334 elt = point_in_line_start_cache (w, start, needed);
1335 assert (elt >= 0); /* in the cache */
1337 cache = w->line_start_cache;
1338 nelt = Dynarr_length (cache);
1341 for (i = elt; i < nelt; i++) {
1342 line = Dynarr_atp (cache, i)->height;
1344 if (height + line > hlimit)
1345 return make_int (!NILP (noclipped) ? height : hlimit);
1349 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1350 return make_int (height);
1353 /* get here => need more cache lines. try again. */
1354 assert(height > prev_height); /* progress? */
1355 prev_height = height;
1357 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1360 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1363 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1364 Return the number of display columns in WINDOW.
1365 This is the width that is usable columns available for text in WINDOW.
1369 return make_int (window_char_width (decode_window (window), 0));
1372 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1373 Return the width of WINDOW in pixels. Defaults to current window.
1377 return make_int (decode_window (window)->pixel_width);
1380 DEFUN ("window-text-area-pixel-width",
1381 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1382 Return the width in pixels of the text-displaying portion of WINDOW.
1383 Unlike `window-pixel-width', the space occupied by the vertical
1384 scrollbar or divider, if any, is not counted.
1388 struct window *w = decode_window (window);
1390 return make_int (WINDOW_TEXT_WIDTH (w));
1393 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1394 Return the number of columns by which WINDOW is scrolled from left margin.
1398 return make_int (decode_window (window)->hscroll);
1401 #ifdef MODELINE_IS_SCROLLABLE
1402 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1403 Return the number of columns by which WINDOW's modeline is scrolled from
1404 left margin. If the window has no modeline, return nil.
1408 struct window *w = decode_window (window);
1410 return (WINDOW_HAS_MODELINE_P (w)) ? make_int (w->modeline_hscroll) : Qnil;
1413 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1414 Set number of columns WINDOW's modeline is scrolled from left margin to NCOL.
1415 NCOL should be zero or positive. If NCOL is negative, it will be forced to 0.
1416 If the window has no modeline, do nothing and return nil.
1420 struct window *w = decode_window (window);
1422 if (WINDOW_HAS_MODELINE_P (w))
1426 ncols = XINT (ncol);
1427 if (ncols < 0) ncols = 0;
1428 if (w->modeline_hscroll != ncols)
1429 MARK_MODELINE_CHANGED;
1430 w->modeline_hscroll = ncols;
1435 #endif /* MODELINE_IS_SCROLLABLE */
1437 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1438 Set number of columns WINDOW is scrolled from left margin to NCOL.
1439 NCOL should be zero or positive.
1447 ncols = XINT (ncol);
1448 if (ncols < 0) ncols = 0;
1449 w = decode_window (window);
1450 if (w->hscroll != ncols)
1451 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1456 #if 0 /* bogus FSF crock */
1458 xxDEFUN ("window-redisplay-end-trigger",
1459 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1460 Return WINDOW's redisplay end trigger value.
1461 See `set-window-redisplay-end-trigger' for more information.
1465 return decode_window (window)->redisplay_end_trigger;
1468 xxDEFUN ("set-window-redisplay-end-trigger",
1469 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1470 Set WINDOW's redisplay end trigger value to VALUE.
1471 VALUE should be a buffer position (typically a marker) or nil.
1472 If it is a buffer position, then if redisplay in WINDOW reaches a position
1473 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1474 with two arguments: WINDOW, and the end trigger value.
1475 Afterwards the end-trigger value is reset to nil.
1479 return (decode_window (window)->redisplay_end_trigger = value);
1484 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1485 Return a list of the pixel edge coordinates of WINDOW.
1486 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1487 The frame toolbars and menubars are considered to be outside of this area.
1491 struct window *w = decode_window (window);
1492 struct frame *f = XFRAME (w->frame);
1494 int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
1495 int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
1497 return list4 (make_int (left),
1499 make_int (left + w->pixel_width),
1500 make_int (top + w->pixel_height));
1503 DEFUN ("window-text-area-pixel-edges",
1504 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1505 Return a list of the pixel edge coordinates of the text area of WINDOW.
1506 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1507 top left corner of the window.
1511 struct window *w = decode_window (window);
1513 int left = window_left_gutter_width (w, /* modeline = */ 0);
1514 int top = window_top_gutter_height (w);
1515 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1516 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1518 return list4 (make_int (left),
1524 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1525 Return current value of point in WINDOW.
1526 For a nonselected window, this is the value point would have
1527 if that window were selected.
1529 Note that, when WINDOW is the selected window and its buffer
1530 is also currently selected, the value returned is the same as (point).
1531 It would be more strictly correct to return the `top-level' value
1532 of point, outside of any save-excursion forms.
1533 But that is hard to define.
1537 struct window *w = decode_window (window);
1539 /* The special check for current buffer is necessary for this
1540 function to work as defined when called within an excursion. */
1541 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1542 && current_buffer == XBUFFER (w->buffer))
1543 return Fpoint (Qnil);
1544 return Fmarker_position (w->pointm[CURRENT_DISP]);
1547 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1548 Return position at which display currently starts in WINDOW.
1549 This is updated by redisplay or by calling `set-window-start'.
1553 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1556 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1557 Return position at which display currently ends in WINDOW.
1558 This is updated by redisplay, when it runs to completion.
1559 Simply changing the buffer text or setting `window-start'
1560 does not update this value.
1561 If GUARANTEE is non-nil, then the return value is guaranteed to be
1562 the value of window-end at the end of the next full redisplay assuming
1563 nothing else changes in the meantime. This function is potentially much
1564 slower with this flag set.
1566 (window, guarantee))
1568 struct window *w = decode_window (window);
1570 if (NILP (guarantee))
1575 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1579 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1580 return make_int (end_of_last_line (w, startp));
1584 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1585 Make point value in WINDOW be at position POS in WINDOW's buffer.
1589 struct window *w = decode_window (window);
1591 CHECK_INT_COERCE_MARKER (pos);
1592 if (w == XWINDOW (Fselected_window (Qnil)))
1593 Fgoto_char (pos, Qnil);
1595 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1601 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1602 Make display in WINDOW start at position POS in WINDOW's buffer.
1603 Optional third arg NOFORCE non-nil inhibits next redisplay
1604 from overriding motion of point in order to display at this exact start.
1606 (window, pos, noforce))
1608 struct window *w = decode_window (window);
1610 CHECK_INT_COERCE_MARKER (pos);
1611 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1612 /* this is not right, but much easier than doing what is right. */
1613 /* w->start_at_line_beg = 0; */
1614 /* WTF is the above supposed to mean? GE */
1615 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1616 marker_position (w->start[CURRENT_DISP]));
1619 w->redo_modeline = 1;
1620 SET_LAST_MODIFIED (w, 0);
1621 SET_LAST_FACECHANGE (w);
1623 MARK_WINDOWS_CHANGED (w);
1628 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1629 Return WINDOW's dedicated object, usually t or nil.
1630 See also `set-window-dedicated-p'.
1634 return decode_window (window)->dedicated;
1637 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1638 Control whether WINDOW is dedicated to the buffer it displays.
1639 If it is dedicated, Emacs will not automatically change
1640 which buffer appears in it.
1641 The second argument is the new value for the dedication flag;
1646 struct window *w = decode_window (window);
1648 w->dedicated = NILP (arg) ? Qnil : Qt;
1650 return w->dedicated;
1653 /* FSFmacs has window-display-table here. We have display table as a
1657 /* Record info on buffer window w is displaying
1658 when it is about to cease to display that buffer. */
1660 unshow_buffer (struct window *w)
1662 Lisp_Object buf = w->buffer;
1664 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1667 /* FSF disables this check, so I'll do it too. I hope it won't
1668 break things. --ben */
1670 if (w == XWINDOW (Fselected_window (Qnil))
1671 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1672 /* Do this except when the selected window's buffer
1673 is being removed from some other window. */
1675 /* last_window_start records the start position that this buffer
1676 had in the last window to be disconnected from it.
1677 Now that this statement is unconditional,
1678 it is possible for the buffer to be displayed in the
1679 selected window, while last_window_start reflects another
1680 window which was recently showing the same buffer.
1681 Some people might say that might be a good thing. Let's see. */
1682 XBUFFER (buf)->last_window_start =
1683 marker_position (w->start[CURRENT_DISP]);
1685 /* Point in the selected window's buffer
1686 is actually stored in that buffer, and the window's pointm isn't used.
1687 So don't clobber point in that buffer. */
1688 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1690 struct buffer *b= XBUFFER (buf);
1691 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1692 marker_position (w->pointm[CURRENT_DISP]),
1697 /* Put REPLACEMENT into the window structure in place of OLD. */
1699 replace_window (Lisp_Object old, Lisp_Object replacement)
1702 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1704 /* If OLD is its frame's root_window, then replacement is the new
1705 root_window for that frame. */
1707 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1708 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1710 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1711 WINDOW_TOP (p) = WINDOW_TOP (o);
1712 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1713 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1715 p->next = tem = o->next;
1717 XWINDOW (tem)->prev = replacement;
1719 p->prev = tem = o->prev;
1721 XWINDOW (tem)->next = replacement;
1723 p->parent = tem = o->parent;
1726 if (EQ (XWINDOW (tem)->vchild, old))
1727 XWINDOW (tem)->vchild = replacement;
1728 if (EQ (XWINDOW (tem)->hchild, old))
1729 XWINDOW (tem)->hchild = replacement;
1732 /* #### Here, if replacement is a vertical combination
1733 and so is its new parent, we should make replacement's
1734 children be children of that parent instead. */
1737 /* we're deleting W; set the structure of W to indicate this. */
1740 mark_window_as_deleted (struct window *w)
1743 (while t (split-window) (delete-window))
1744 we end up with a tree of deleted windows which are all connected
1745 through the `next' slot. This might not seem so bad, as they're
1746 deleted, and will presumably be GCed - but if even *one* of those
1747 windows is still being pointed to, by the user, or by a window
1748 configuration, then *all* of those windows stick around.
1750 Since the window-configuration code doesn't need any of the
1751 pointers to other windows (they are all recreated from the
1752 window-config data), we set them all to nil so that we
1753 are able to collect more actual garbage.
1763 /* Free the extra data structures attached to windows immediately so
1764 they don't sit around consuming excess space. They will be
1765 reinitialized by the window-configuration code as necessary. */
1766 finalize_window ((void *) w, 0);
1769 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1770 Remove WINDOW from the display. Default is selected window.
1771 If window is the only one on the frame, the frame is destroyed.
1772 Normally, you cannot delete the last non-minibuffer-only frame (you must
1773 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1774 second argument FORCE is non-nil, you can delete the last frame. (This
1775 will automatically call `save-buffers-kill-emacs'.)
1779 /* This function can GC if this is the only window in the frame */
1787 /* Note: this function is called by other C code on non-leaf
1790 /* Do the equivalent of decode_window() but don't error out on
1791 deleted window; it's OK to delete an already-deleted window. */
1793 window = Fselected_window (Qnil);
1795 CHECK_WINDOW (window);
1796 w = XWINDOW (window);
1798 /* It's okay to delete an already-deleted window. */
1799 if (! WINDOW_LIVE_P (w))
1802 frame = WINDOW_FRAME (w);
1804 d = XDEVICE (FRAME_DEVICE (f));
1806 if (TOP_LEVEL_WINDOW_P (w))
1808 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1809 /* this frame isn't fully initialized yet; don't blow up. */
1812 if (MINI_WINDOW_P (XWINDOW (window)))
1813 error ("Attempt to delete the minibuffer window");
1815 /* It has been suggested that it's a good thing for C-x 0 to have this
1816 behavior, but not such a good idea for #'delete-window to have it.
1817 Maybe C-x 0 should be bound to something else, or maybe frame
1818 deletion should only happen when this is called interactively.
1820 delete_frame_internal (f, !NILP (force), 0, 0);
1824 /* At this point, we know the window has a parent. */
1826 par = XWINDOW (parent);
1828 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1830 /* Are we trying to delete any frame's selected window?
1831 Note that we could be dealing with a non-leaf window
1832 where the selected window is one of our children.
1833 So, we check by scanning all the ancestors of the
1834 frame's selected window and comparing each one with
1837 Lisp_Object pwindow;
1839 pwindow = FRAME_SELECTED_WINDOW (f);
1841 while (!NILP (pwindow))
1843 if (EQ (window, pwindow))
1845 pwindow = XWINDOW (pwindow)->parent;
1848 if (EQ (window, pwindow))
1850 /* OK, we found it. */
1851 Lisp_Object alternative;
1852 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1854 /* If we're about to delete the selected window on the
1855 selected frame, then we should use Fselect_window to select
1856 the new window. On the other hand, if we're about to
1857 delete the selected window on any other frame, we shouldn't do
1858 anything but set the frame's selected_window slot. */
1859 if (EQ (frame, Fselected_frame (Qnil)))
1860 Fselect_window (alternative, Qnil);
1862 set_frame_selected_window (f, alternative);
1866 /* w->buffer is nil in a non-leaf window; in this case,
1867 get rid of the markers we maintain that point into that buffer. */
1868 if (!NILP (w->buffer))
1871 unchain_marker (w->pointm[CURRENT_DISP]);
1872 unchain_marker (w->pointm[DESIRED_DISP]);
1873 unchain_marker (w->pointm[CMOTION_DISP]);
1874 unchain_marker (w->start[CURRENT_DISP]);
1875 unchain_marker (w->start[DESIRED_DISP]);
1876 unchain_marker (w->start[CMOTION_DISP]);
1877 unchain_marker (w->sb_point);
1878 /* This breaks set-window-configuration if windows in the saved
1879 configuration get deleted and multiple frames are in use. */
1880 /* w->buffer = Qnil; */
1883 /* close up the hole in the sibling list */
1884 if (!NILP (w->next))
1885 XWINDOW (w->next)->prev = w->prev;
1886 if (!NILP (w->prev))
1887 XWINDOW (w->prev)->next = w->next;
1888 if (EQ (window, par->hchild))
1889 par->hchild = w->next;
1890 if (EQ (window, par->vchild))
1891 par->vchild = w->next;
1893 /* Find one of our siblings to give our space to. */
1895 Lisp_Object sib = w->prev;
1898 /* If w gives its space to its next sibling, that sibling needs
1899 to have its top/left side pulled back to where w's is.
1900 set_window_{height,width} will re-position the sibling's
1903 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1904 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1907 /* Stretch that sibling. */
1908 if (!NILP (par->vchild))
1909 set_window_pixheight
1910 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1911 if (!NILP (par->hchild))
1913 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1916 /* If parent now has only one child,
1917 put the child into the parent's place. */
1919 Lisp_Object parchild = par->hchild;
1920 if (NILP (parchild))
1921 parchild = par->vchild;
1922 if (NILP (XWINDOW (parchild)->next))
1924 replace_window (parent, parchild);
1925 mark_window_as_deleted (XWINDOW (parent));
1929 /* Since we may be deleting combination windows, we must make sure that
1930 not only W but all its children have been marked as deleted. */
1931 if (!NILP (w->hchild))
1932 delete_all_subwindows (XWINDOW (w->hchild));
1933 else if (!NILP (w->vchild))
1934 delete_all_subwindows (XWINDOW (w->vchild));
1936 mark_window_as_deleted (w);
1938 f->mirror_dirty = 1;
1943 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1944 Return next window after WINDOW in canonical ordering of windows.
1945 If omitted, WINDOW defaults to the selected window.
1947 Optional second arg MINIBUF t means count the minibuffer window even
1948 if not active. MINIBUF nil or omitted means count the minibuffer iff
1949 it is active. MINIBUF neither t nor nil means not to count the
1950 minibuffer even if it is active.
1952 Several frames may share a single minibuffer; if the minibuffer
1953 counts, all windows on all frames that share that minibuffer count
1954 too. Therefore, `next-window' can be used to iterate through the
1955 set of windows even when the minibuffer is on another frame. If the
1956 minibuffer does not count, only windows from WINDOW's frame count.
1958 Optional third arg ALL-FRAMES t means include windows on all frames.
1959 ALL-FRAMES nil or omitted means cycle within the frames as specified
1960 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1961 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1962 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1963 Anything else means restrict to WINDOW's frame.
1965 Optional fourth argument CONSOLE controls which consoles or devices the
1966 returned window may be on. If CONSOLE is a console, return windows only
1967 on that console. If CONSOLE is a device, return windows only on that
1968 device. If CONSOLE is a console type, return windows only on consoles
1969 of that type. If CONSOLE is 'window-system, return any windows on any
1970 window-system consoles. If CONSOLE is nil or omitted, return windows only
1971 on WINDOW's console. Otherwise, all windows are considered.
1973 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
1974 can use `next-window' to iterate through the entire cycle of acceptable
1975 windows, eventually ending up back at the window you started with.
1976 `previous-window' traverses the same cycle, in the reverse order.
1978 (window, minibuf, all_frames, console))
1981 Lisp_Object start_window;
1984 window = Fselected_window (Qnil);
1986 CHECK_LIVE_WINDOW (window);
1988 start_window = window;
1990 /* minibuf == nil may or may not include minibuffers.
1991 Decide if it does. */
1993 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1994 else if (! EQ (minibuf, Qt))
1996 /* Now minibuf can be t => count all minibuffer windows,
1997 lambda => count none of them,
1998 or a specific minibuffer window (the active one) to count. */
2000 /* all_frames == nil doesn't specify which frames to include. */
2001 if (NILP (all_frames))
2002 all_frames = (! EQ (minibuf, Qlambda)
2003 ? (FRAME_MINIBUF_WINDOW
2006 (XWINDOW (window)))))
2008 else if (EQ (all_frames, Qvisible))
2010 else if (ZEROP (all_frames))
2012 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2013 /* If all_frames is a frame and window arg isn't on that frame, just
2014 return the first window on the frame. */
2015 return frame_first_window (XFRAME (all_frames));
2016 else if (! EQ (all_frames, Qt))
2018 /* Now all_frames is t meaning search all frames,
2019 nil meaning search just current frame,
2020 visible meaning search just visible frames,
2021 0 meaning search visible and iconified frames,
2022 or a window, meaning search the frame that window belongs to. */
2024 /* Do this loop at least once, to get the next window, and perhaps
2025 again, if we hit the minibuffer and that is not acceptable. */
2028 /* Find a window that actually has a next one. This loop
2029 climbs up the tree. */
2030 while (tem = XWINDOW (window)->next, NILP (tem))
2031 if (tem = XWINDOW (window)->parent, !NILP (tem))
2033 else /* window must be minibuffer window now */
2035 /* We've reached the end of this frame.
2036 Which other frames are acceptable? */
2037 tem = WINDOW_FRAME (XWINDOW (window));
2039 if (! NILP (all_frames))
2044 tem = next_frame (tem, all_frames, console);
2045 /* In the case where the minibuffer is active,
2046 and we include its frame as well as the selected one,
2047 next_frame may get stuck in that frame.
2048 If that happens, go back to the selected frame
2049 so we can complete the cycle. */
2051 XSETFRAME (tem, selected_frame ());
2054 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2060 /* If we're in a combination window, find its first child and
2061 recurse on that. Otherwise, we've found the window we want. */
2064 if (!NILP (XWINDOW (window)->hchild))
2065 window = XWINDOW (window)->hchild;
2066 else if (!NILP (XWINDOW (window)->vchild))
2067 window = XWINDOW (window)->vchild;
2071 /* "acceptable" is the correct spelling. */
2072 /* Which windows are acceptable?
2073 Exit the loop and accept this window if
2074 this isn't a minibuffer window,
2075 or we're accepting all minibuffer windows,
2076 or this is the active minibuffer and we are accepting that one, or
2077 we've come all the way around and we're back at the original window. */
2078 while (MINI_WINDOW_P (XWINDOW (window))
2079 && ! EQ (minibuf, Qt)
2080 && ! EQ (minibuf, window)
2081 && ! EQ (window, start_window));
2086 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2087 Return the window preceding WINDOW in canonical ordering of windows.
2088 If omitted, WINDOW defaults to the selected window.
2090 Optional second arg MINIBUF t means count the minibuffer window even
2091 if not active. MINIBUF nil or omitted means count the minibuffer iff
2092 it is active. MINIBUF neither t nor nil means not to count the
2093 minibuffer even if it is active.
2095 Several frames may share a single minibuffer; if the minibuffer
2096 counts, all windows on all frames that share that minibuffer count
2097 too. Therefore, `previous-window' can be used to iterate through
2098 the set of windows even when the minibuffer is on another frame. If
2099 the minibuffer does not count, only windows from WINDOW's frame count
2101 If optional third arg ALL-FRAMES t means include windows on all frames.
2102 ALL-FRAMES nil or omitted means cycle within the frames as specified
2103 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2104 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2105 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2106 Anything else means restrict to WINDOW's frame.
2108 Optional fourth argument CONSOLE controls which consoles or devices the
2109 returned window may be on. If CONSOLE is a console, return windows only
2110 on that console. If CONSOLE is a device, return windows only on that
2111 device. If CONSOLE is a console type, return windows only on consoles
2112 of that type. If CONSOLE is 'window-system, return any windows on any
2113 window-system consoles. If CONSOLE is nil or omitted, return windows only
2114 on WINDOW's console. Otherwise, all windows are considered.
2116 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2117 can use `previous-window' to iterate through the entire cycle of acceptable
2118 windows, eventually ending up back at the window you started with.
2119 `next-window' traverses the same cycle, in the reverse order.
2121 (window, minibuf, all_frames, console))
2124 Lisp_Object start_window;
2127 window = Fselected_window (Qnil);
2129 CHECK_LIVE_WINDOW (window);
2131 start_window = window;
2133 /* minibuf == nil may or may not include minibuffers.
2134 Decide if it does. */
2136 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2137 else if (! EQ (minibuf, Qt))
2139 /* Now minibuf can be t => count all minibuffer windows,
2140 lambda => count none of them,
2141 or a specific minibuffer window (the active one) to count. */
2143 /* all_frames == nil doesn't specify which frames to include.
2144 Decide which frames it includes. */
2145 if (NILP (all_frames))
2146 all_frames = (! EQ (minibuf, Qlambda)
2147 ? (FRAME_MINIBUF_WINDOW
2150 (XWINDOW (window)))))
2152 else if (EQ (all_frames, Qvisible))
2154 else if (ZEROP (all_frames))
2156 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2157 /* If all_frames is a frame and window arg isn't on that frame, just
2158 return the first window on the frame. */
2159 return frame_first_window (XFRAME (all_frames));
2160 else if (! EQ (all_frames, Qt))
2162 /* Now all_frames is t meaning search all frames,
2163 nil meaning search just current frame,
2164 visible meaning search just visible frames,
2165 0 meaning search visible and iconified frames,
2166 or a window, meaning search the frame that window belongs to. */
2168 /* Do this loop at least once, to get the next window, and perhaps
2169 again, if we hit the minibuffer and that is not acceptable. */
2172 /* Find a window that actually has a next one. This loop
2173 climbs up the tree. */
2174 while (tem = XWINDOW (window)->prev, NILP (tem))
2175 if (tem = XWINDOW (window)->parent, !NILP (tem))
2177 else /* window must be minibuffer window now */
2179 /* We have found the top window on the frame.
2180 Which frames are acceptable? */
2181 tem = WINDOW_FRAME (XWINDOW (window));
2183 if (! NILP (all_frames))
2184 /* It's actually important that we use prev_frame here,
2185 rather than next_frame. All the windows acceptable
2186 according to the given parameters should form a ring;
2187 Fnext_window and Fprevious_window should go back and
2188 forth around the ring. If we use next_frame here,
2189 then Fnext_window and Fprevious_window take different
2190 paths through the set of acceptable windows.
2191 window_loop assumes that these `ring' requirement are
2197 tem = prev_frame (tem, all_frames, console);
2198 /* In the case where the minibuffer is active,
2199 and we include its frame as well as the selected one,
2200 next_frame may get stuck in that frame.
2201 If that happens, go back to the selected frame
2202 so we can complete the cycle. */
2204 XSETFRAME (tem, selected_frame ());
2207 /* If this frame has a minibuffer, find that window first,
2208 because it is conceptually the last window in that frame. */
2209 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2210 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2212 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2219 /* If we're in a combination window, find its first child and
2220 recurse on that. Otherwise, we've found the window we want. */
2223 if (!NILP (XWINDOW (window)->hchild))
2224 window = XWINDOW (window)->hchild;
2225 else if (!NILP (XWINDOW (window)->vchild))
2226 window = XWINDOW (window)->vchild;
2228 while (tem = XWINDOW (window)->next, !NILP (tem))
2232 /* Which windows are acceptable?
2233 Exit the loop and accept this window if
2234 this isn't a minibuffer window,
2235 or we're accepting all minibuffer windows,
2236 or this is the active minibuffer and we are accepting that one, or
2237 we've come all the way around and we're back at the original window. */
2238 while (MINI_WINDOW_P (XWINDOW (window))
2239 && ! EQ (minibuf, Qt)
2240 && ! EQ (minibuf, window)
2241 && ! EQ (window, start_window));
2246 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2247 Return the next window which is vertically after WINDOW.
2252 struct window *w = decode_window (window);
2253 XSETWINDOW (window, w);
2255 if (MINI_WINDOW_P (XWINDOW (window)))
2258 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2260 if (EQ (window, root))
2263 if (!NILP (XWINDOW (window)->hchild))
2264 window = XWINDOW (window)->hchild;
2265 else if (!NILP (XWINDOW (window)->vchild))
2266 window = XWINDOW (window)->vchild;
2273 if (!NILP (XWINDOW (window)->parent) &&
2274 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2276 if (!NILP (XWINDOW (window)->next))
2277 return XWINDOW (window)->next;
2279 window = XWINDOW (window)->parent;
2282 window = XWINDOW (window)->parent;
2284 while (!EQ (window, root));
2287 if (!NILP (XWINDOW (window)->hchild))
2288 window = XWINDOW (window)->hchild;
2289 else if (!NILP (XWINDOW (window)->vchild))
2290 window = XWINDOW (window)->vchild;
2295 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2296 Select the N'th different window on this frame.
2297 All windows on current frame are arranged in a cyclic order.
2298 This command selects the window N steps away in that order.
2299 A negative N moves in the opposite order.
2301 If optional argument FRAME is `visible', search all visible frames.
2302 If FRAME is 0, search all visible and iconified frames.
2303 If FRAME is t, search all frames.
2304 If FRAME is nil, search only the selected frame.
2305 If FRAME is a frame, search only that frame.
2307 Optional third argument CONSOLE controls which consoles or devices the
2308 returned window may be on. If CONSOLE is a console, return windows only
2309 on that console. If CONSOLE is a device, return windows only on that
2310 device. If CONSOLE is a console type, return windows only on consoles
2311 of that type. If CONSOLE is 'window-system, return any windows on any
2312 window-system consoles. If CONSOLE is nil or omitted, return windows only
2313 on FRAME'S console, or on the selected console if FRAME is not a frame.
2314 Otherwise, all windows are considered.
2316 (n, frame, console))
2322 w = Fselected_window (Qnil);
2327 w = Fnext_window (w, Qnil, frame, console);
2332 w = Fprevious_window (w, Qnil, frame, console);
2335 Fselect_window (w, Qnil);
2340 /* Look at all windows, performing an operation specified by TYPE
2343 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2344 frame. If FRAMES is a frame, just look at windows on that frame.
2345 If MINI is non-zero, perform the operation on minibuffer windows too.
2351 GET_BUFFER_WINDOW, /* Arg is buffer */
2352 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2353 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2354 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2356 UNSHOW_BUFFER, /* Arg is buffer */
2357 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2358 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2362 window_loop (enum window_loop type,
2367 Lisp_Object console)
2369 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2371 Lisp_Object best_window = Qnil;
2372 Lisp_Object next_window;
2373 Lisp_Object last_window;
2374 struct frame *frame;
2375 Lisp_Object frame_arg = Qt;
2376 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2377 /* #### I think the change of "precomputing" last_window and next_window
2378 * #### catch the lossage this is meant(?) to punt on...
2381 Lisp_Object devcons, concons;
2383 /* FRAME_ARG is Qlambda to stick to one frame,
2384 Qvisible to consider all visible frames,
2387 /* If we're only looping through windows on a particular frame,
2388 FRAME points to that frame. If we're looping through windows
2389 on all frames, FRAME is 0. */
2391 if (FRAMEP (frames))
2392 frame = XFRAME (frames);
2393 else if (NILP (frames))
2394 frame = selected_frame ();
2398 frame_arg = Qlambda;
2399 else if (ZEROP (frames))
2401 else if (EQ (frames, Qvisible))
2404 DEVICE_LOOP_NO_BREAK (devcons, concons)
2406 Lisp_Object device = XCAR (devcons);
2407 Lisp_Object the_frame;
2410 XSETFRAME (the_frame, frame);
2412 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2414 if (NILP (the_frame))
2417 if (!device_matches_console_spec (the_frame, device, console))
2420 /* Pick a window to start with. */
2424 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2426 /* Figure out the last window we're going to mess with. Since
2427 Fnext_window, given the same options, is guaranteed to go in a
2428 ring, we can just use Fprevious_window to find the last one.
2430 We can't just wait until we hit the first window again,
2431 because it might be deleted. */
2433 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2438 struct window *p = XWINDOW (w);
2439 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2441 /* Pick the next window now, since some operations will delete
2442 the current window. */
2443 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2445 /* #### Still needed ?? */
2446 /* Given the outstanding quality of the rest of this code,
2447 I feel no shame about putting this piece of shit in. */
2448 if (++lose_lose >= 500)
2451 /* Note that we do not pay attention here to whether
2452 the frame is visible, since Fnext_window skips non-visible frames
2453 if that is desired, under the control of frame_arg. */
2454 if (! MINI_WINDOW_P (p)
2455 || (mini && minibuf_level > 0))
2458 case GET_BUFFER_WINDOW:
2460 if (XBUFFER (p->buffer) == XBUFFER (obj))
2465 case GET_BUFFER_WINDOW_COUNT:
2467 if (XBUFFER (p->buffer) == XBUFFER (obj))
2472 case GET_LRU_WINDOW:
2474 /* t as arg means consider only full-width windows */
2476 && !window_full_width_p (p))
2478 /* Ignore dedicated windows and minibuffers. */
2479 if (MINI_WINDOW_P (p)
2480 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2482 if (NILP (best_window)
2483 || (XINT (XWINDOW (best_window)->use_time)
2484 > XINT (p->use_time)))
2489 case GET_BUFFER_MRU_WINDOW:
2491 /* #### what about the first check in GET_LRU_WINDOW? */
2492 /* Ignore dedicated windows and minibuffers. */
2493 if (MINI_WINDOW_P (p)
2494 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2497 if (XBUFFER (p->buffer) == XBUFFER (obj))
2499 if (NILP (best_window)
2500 || (XINT (XWINDOW (best_window)->use_time)
2501 < XINT (p->use_time)))
2507 case DELETE_OTHER_WINDOWS:
2509 /* Don't delete the last window on a frame; this can
2510 happen when the minibuffer is selected, and would
2511 cause the frame to be deleted. */
2512 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2513 Fdelete_window (w, Qnil);
2517 case DELETE_BUFFER_WINDOWS:
2519 if (EQ (p->buffer, obj))
2521 struct frame *f = XFRAME (WINDOW_FRAME (p));
2523 /* If this window is dedicated, and in a frame
2524 of its own, kill the frame. */
2525 if (EQ (w, FRAME_ROOT_WINDOW (f))
2526 && !NILP (p->dedicated)
2527 && other_visible_frames (f))
2529 /* Skip the other windows on this frame.
2530 There might be one, the minibuffer! */
2531 if (! EQ (w, last_window))
2532 while (f == XFRAME (WINDOW_FRAME
2533 (XWINDOW (next_window))))
2535 /* As we go, check for the end of the
2536 loop. We mustn't start going
2537 around a second time. */
2538 if (EQ (next_window, last_window))
2543 next_window = Fnext_window (next_window,
2547 /* Now we can safely delete the frame. */
2548 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2551 /* If we're deleting the buffer displayed in
2552 the only window on the frame, find a new
2553 buffer to display there. */
2554 if (NILP (p->parent))
2556 Lisp_Object new_buffer;
2557 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2558 if (NILP (new_buffer))
2559 new_buffer = Fget_buffer_create (QSscratch);
2560 Fset_window_buffer (w, new_buffer);
2561 if (EQ (w, Fselected_window (Qnil)))
2562 Fset_buffer (p->buffer);
2565 Fdelete_window (w, Qnil);
2570 case GET_LARGEST_WINDOW:
2572 /* Ignore dedicated windows and minibuffers. */
2573 if (MINI_WINDOW_P (p)
2574 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2577 /* write the check as follows to avoid tripping
2578 error_check_window() --ben */
2579 struct window *b = NILP (best_window) ? 0 :
2580 XWINDOW (best_window);
2581 if (NILP (best_window)
2582 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2583 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2591 if (EQ (p->buffer, obj))
2593 /* Find another buffer to show in this window. */
2594 Lisp_Object another_buffer =
2595 Fother_buffer (obj, Qnil, Qnil);
2596 if (NILP (another_buffer))
2598 = Fget_buffer_create (QSscratch);
2599 /* If this window is dedicated, and in a frame
2600 of its own, kill the frame. */
2601 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2602 && !NILP (p->dedicated)
2603 && other_visible_frames (w_frame))
2605 /* Skip the other windows on this frame.
2606 There might be one, the minibuffer! */
2607 if (! EQ (w, last_window))
2608 while (w_frame == XFRAME (WINDOW_FRAME
2609 (XWINDOW (next_window))))
2611 /* As we go, check for the end of the
2612 loop. We mustn't start going
2613 around a second time. */
2614 if (EQ (next_window, last_window))
2619 next_window = Fnext_window (next_window,
2623 /* Now we can safely delete the frame. */
2624 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2629 /* Otherwise show a different buffer in the
2631 p->dedicated = Qnil;
2632 Fset_window_buffer (w, another_buffer);
2633 if (EQ (w, Fselected_window (Qnil)))
2634 Fset_buffer (p->buffer);
2644 if (EQ (w, last_window))
2651 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2654 #if 0 /* not currently used */
2657 buffer_window_count (struct buffer *b, struct frame *f)
2659 Lisp_Object buffer, frame;
2661 XSETFRAME (frame, f);
2662 XSETBUFFER (buffer, b);
2664 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2669 buffer_window_mru (struct window *w)
2671 Lisp_Object window =
2672 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2676 else if (XWINDOW (window) == w)
2685 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2686 Return the window least recently selected or used for display.
2687 If optional argument FRAME is `visible', search all visible frames.
2688 If FRAME is 0, search all visible and iconified frames.
2689 If FRAME is t, search all frames.
2690 If FRAME is nil, search only the selected frame.
2691 If FRAME is a frame, search only that frame.
2693 Optional second argument CONSOLE controls which consoles or devices the
2694 returned window may be on. If CONSOLE is a console, return windows only
2695 on that console. If CONSOLE is a device, return windows only on that
2696 device. If CONSOLE is a console type, return windows only on consoles
2697 of that type. If CONSOLE is 'window-system, return any windows on any
2698 window-system consoles. If CONSOLE is nil or omitted, return windows only
2699 on FRAME'S console, or on the selected console if FRAME is not a frame.
2700 Otherwise, all windows are considered.
2705 /* First try for a non-dedicated window that is full-width */
2706 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2707 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2710 /* Then try for any non-dedicated window */
2711 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2712 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2716 /* FSFmacs never returns a dedicated window here. If we do,
2717 it makes `display-buffer' not work right. #### All of this
2718 shit is so disgusting and awful that it needs to be rethought
2720 /* then try for a dedicated window that is full-width */
2721 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2722 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2725 /* If none of them, then all windows, dedicated or not. */
2726 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2728 /* At this point we damn well better have found something. */
2729 if (NILP (w)) abort ();
2735 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2736 Return the window largest in area.
2737 If optional argument FRAME is `visible', search all visible frames.
2738 If FRAME is 0, search all visible and iconified frames.
2739 If FRAME is t, search all frames.
2740 If FRAME is nil, search only the selected frame.
2741 If FRAME is a frame, search only that frame.
2743 Optional second argument CONSOLE controls which consoles or devices the
2744 returned window may be on. If CONSOLE is a console, return windows only
2745 on that console. If CONSOLE is a device, return windows only on that
2746 device. If CONSOLE is a console type, return windows only on consoles
2747 of that type. If CONSOLE is 'window-system, return any windows on any
2748 window-system consoles. If CONSOLE is nil or omitted, return windows only
2749 on FRAME'S console, or on the selected console if FRAME is not a frame.
2750 Otherwise, all windows are considered.
2754 /* Don't search dedicated windows because FSFmacs doesn't.
2755 This stuff is all black magic so don't try to apply common
2757 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2760 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2761 Return a window currently displaying BUFFER, or nil if none.
2762 If optional argument FRAME is `visible', search all visible frames.
2763 If optional argument FRAME is 0, search all visible and iconified frames.
2764 If FRAME is t, search all frames.
2765 If FRAME is nil, search only the selected frame.
2766 If FRAME is a frame, search only that frame.
2768 Optional third argument CONSOLE controls which consoles or devices the
2769 returned window may be on. If CONSOLE is a console, return windows only
2770 on that console. If CONSOLE is a device, return windows only on that
2771 device. If CONSOLE is a console type, return windows only on consoles
2772 of that type. If CONSOLE is 'window-system, return any windows on any
2773 window-system consoles. If CONSOLE is nil or omitted, return windows only
2774 on FRAME'S console, or on the selected console if FRAME is not a frame.
2775 Otherwise, all windows are considered.
2777 (buffer, frame, console))
2779 buffer = Fget_buffer (buffer);
2780 if (BUFFERP (buffer))
2781 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2782 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2787 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2788 but there is no sensible way to implement those functions, since
2789 you can't in general derive a window from a buffer. */
2791 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2793 Return the width in pixels of the left outside margin of window WINDOW.
2794 If WINDOW is nil, the selected window is assumed.
2798 return make_int (window_left_margin_width (decode_window (window)));
2801 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2803 Return the width in pixels of the right outside margin of window WINDOW.
2804 If WINDOW is nil, the selected window is assumed.
2808 return make_int (window_right_margin_width (decode_window (window)));
2811 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2812 Make WINDOW (or the selected window) fill its frame.
2813 Only the frame WINDOW is on is affected.
2814 This function tries to reduce display jumps
2815 by keeping the text previously visible in WINDOW
2816 in the same place on the frame. Doing this depends on
2817 the value of (window-start WINDOW), so if calling this function
2818 in a program gives strange scrolling, make sure the window-start
2819 value is reasonable when this function is called.
2823 struct window *w = decode_window (window);
2824 struct buffer *b = XBUFFER (w->buffer);
2826 int old_top = WINDOW_TOP (w);
2828 XSETWINDOW (window, w);
2830 if (MINI_WINDOW_P (w) && old_top > 0)
2831 error ("Can't expand minibuffer to full frame");
2833 /* Ignore dedicated windows. */
2834 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2836 start_pos = marker_position (w->start[CURRENT_DISP]);
2838 /* Try to minimize scrolling, by setting the window start to the
2839 point which will cause the text at the old window start to be at
2840 the same place on the frame. But don't try to do this if the
2841 window start is outside the visible portion (as might happen when
2842 the display is not current, due to typeahead). */
2843 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2844 && !MINI_WINDOW_P (w))
2846 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2848 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2850 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2852 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2854 /* We need to do this, so that the window-scroll-functions
2862 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2863 "bDelete windows on (buffer): ", /*
2864 Delete all windows showing BUFFER.
2865 Optional second argument FRAME controls which frames are affected.
2866 If nil or omitted, delete all windows showing BUFFER in any frame.
2867 If t, delete only windows showing BUFFER in the selected frame.
2868 If `visible', delete all windows showing BUFFER in any visible frame.
2869 If a frame, delete only windows showing BUFFER in that frame.
2871 Optional third argument CONSOLE controls which consoles or devices the
2872 returned window may be on. If CONSOLE is a console, return windows only
2873 on that console. If CONSOLE is a device, return windows only on that
2874 device. If CONSOLE is a console type, return windows only on consoles
2875 of that type. If CONSOLE is 'window-system, return any windows on any
2876 window-system consoles. If CONSOLE is nil or omitted, return windows only
2877 on FRAME'S console, or on the selected console if FRAME is not a frame.
2878 Otherwise, all windows are considered.
2880 (buffer, frame, console))
2882 /* This function can GC */
2883 /* FRAME uses t and nil to mean the opposite of what window_loop
2885 if (!FRAMEP (frame))
2886 frame = NILP (frame) ? Qt : Qnil;
2890 buffer = Fget_buffer (buffer);
2891 CHECK_BUFFER (buffer);
2892 /* Ignore dedicated windows. */
2893 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2898 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2899 "bReplace buffer in windows: ", /*
2900 Replace BUFFER with some other buffer in all windows showing it.
2904 /* This function can GC */
2907 buffer = Fget_buffer (buffer);
2908 CHECK_BUFFER (buffer);
2909 /* Ignore dedicated windows. */
2910 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2915 /* The smallest acceptable dimensions for a window. Anything smaller
2916 might crash Emacs. */
2917 #define MIN_SAFE_WINDOW_WIDTH (2)
2918 #define MIN_SAFE_WINDOW_HEIGHT (2)
2920 /* Make sure that window_min_height and window_min_width are
2921 not too small; if they are, set them to safe minima. */
2924 check_min_window_sizes (void)
2926 /* Smaller values might permit a crash. */
2927 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2928 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2929 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2930 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2933 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2934 minimum allowable size. */
2936 check_frame_size (struct frame *frame, int *rows, int *cols)
2938 /* For height, we have to see whether the frame has a minibuffer, and
2939 whether it wants a modeline. */
2941 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2942 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2943 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2945 if (*rows < min_height)
2947 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2948 *cols = MIN_SAFE_WINDOW_WIDTH;
2951 /* Normally the window is deleted if it gets too small.
2952 nodelete nonzero means do not do this.
2953 (The caller should check later and do so if appropriate) */
2955 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
2958 struct window *w = XWINDOW (window);
2959 struct frame *f = XFRAME (w->frame);
2961 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
2962 Lisp_Object child, minor_kid, major_kid;
2965 int defheight, defwidth;
2967 /* #### This is very likely incorrect and instead the char_to_pixel_
2968 functions should be called. */
2969 default_face_height_and_width (window, &defheight, &defwidth);
2970 line_size = (set_height ? defheight : defwidth);
2972 check_min_window_sizes ();
2974 minsize = (set_height ? window_min_height : window_min_width);
2975 minsize *= line_size;
2978 && !TOP_LEVEL_WINDOW_P (w)
2979 && new_pixsize < minsize)
2981 Fdelete_window (window, Qnil);
2985 SET_LAST_MODIFIED (w, 0);
2986 SET_LAST_FACECHANGE (w);
2987 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
2990 WINDOW_HEIGHT (w) = new_pixsize;
2991 major_kid = w->vchild;
2992 minor_kid = w->hchild;
2996 WINDOW_WIDTH (w) = new_pixsize;
2997 major_kid = w->hchild;
2998 minor_kid = w->vchild;
3001 if (!NILP (minor_kid))
3003 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3006 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3008 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3010 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3013 else if (!NILP (major_kid))
3015 int last_pos, last_old_pos, pos, old_pos, first;
3016 int pixel_adj_left = new_pixsize - old_pixsize;
3017 int div_val = old_pixsize << 1;
3020 * Previously we bailed out here if there was no size change.
3021 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3022 * toolbar appears or disappears, windows may not change size,
3023 * but their top and left coordinates need to be updated.
3025 * So we don't bail until after the loop below.
3028 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3031 for (child = major_kid; !NILP (child); child = c->next)
3033 c = XWINDOW (child);
3037 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3038 WINDOW_TOP (c) = last_pos;
3042 old_pos = last_old_pos + WINDOW_WIDTH (c);
3043 WINDOW_LEFT (c) = last_pos;
3046 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3047 /* All but the last window should have a height which is
3048 a multiple of the default line height. */
3049 if (!NILP (c->next))
3050 pos = (pos / line_size) * line_size;
3052 /* Avoid confusion: don't delete child if it becomes too small */
3053 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3055 last_pos = pos + first;
3056 last_old_pos = old_pos;
3059 /* Sometimes we may get called with our old size. In that case
3060 we don't need to do anything else. */
3061 if (!pixel_adj_left)
3064 /* Now delete any children that became too small. */
3066 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3069 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3071 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3076 /* Set the height of WINDOW and all its inferiors. */
3078 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3080 set_window_pixsize (window, new_pixheight, nodelete, 1);
3083 /* Recursively set width of WINDOW and its inferiors. */
3085 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3087 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3091 static int window_select_count;
3093 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3094 Make WINDOW display BUFFER as its contents.
3095 BUFFER can be a buffer or buffer name.
3100 struct window *w = decode_window (window);
3102 buffer = Fget_buffer (buffer);
3103 CHECK_BUFFER (buffer);
3105 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3106 error ("Attempt to display deleted buffer");
3110 error ("Window is deleted");
3112 /* While this seems like a logical thing to do, it causes problems
3113 because of saved window configurations. It is possible for a
3114 buffer to get restored into a window in which it is already being
3115 displayed, but start and point are actually at completely
3116 different locations. So we let this function complete fully and
3117 it will then make sure redisplay correctly updates things.
3119 #### This is a kludge. The correct approach is not to do this
3120 but to fix set-window-configuration. */
3122 else if (EQ (tem, buffer))
3125 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3126 is first being set up. */
3128 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3129 error ("Window is dedicated to buffer %s",
3130 XSTRING_DATA (XBUFFER (tem)->name));
3136 w->window_end_pos[CURRENT_DISP] = 0;
3138 w->modeline_hscroll = 0;
3139 Fset_marker (w->pointm[CURRENT_DISP],
3140 make_int (BUF_PT (XBUFFER (buffer))),
3142 set_marker_restricted (w->start[CURRENT_DISP],
3143 make_int (XBUFFER (buffer)->last_window_start),
3145 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3146 /* set start_at_line_beg correctly. GE */
3147 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3148 marker_position (w->start[CURRENT_DISP]));
3149 w->force_start = 0; /* Lucid fix */
3150 SET_LAST_MODIFIED (w, 1);
3151 SET_LAST_FACECHANGE (w);
3152 MARK_WINDOWS_CHANGED (w);
3153 recompute_all_cached_specifiers_in_window (w);
3154 if (EQ (window, Fselected_window (Qnil)))
3156 Fset_buffer (buffer);
3161 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3162 Select WINDOW. Most editing will apply to WINDOW's buffer.
3163 The main editor command loop selects the buffer of the selected window
3164 before each command.
3166 With non-nil optional argument `norecord', do not modify the
3167 global or per-frame buffer ordering.
3172 Lisp_Object old_selected_window = Fselected_window (Qnil);
3174 CHECK_LIVE_WINDOW (window);
3175 w = XWINDOW (window);
3177 /* we have already caught dead-window errors */
3178 if (!NILP (w->hchild) || !NILP (w->vchild))
3179 error ("Trying to select non-leaf window");
3181 w->use_time = make_int (++window_select_count);
3182 if (EQ (window, old_selected_window))
3185 /* deselect the old window, if it exists (it might not exist if
3186 the selected device has no frames, which occurs at startup) */
3187 if (!NILP (old_selected_window))
3189 struct window *ow = XWINDOW (old_selected_window);
3191 Fset_marker (ow->pointm[CURRENT_DISP],
3192 make_int (BUF_PT (XBUFFER (ow->buffer))),
3195 MARK_WINDOWS_CHANGED (ow);
3198 /* now select the window's frame */
3199 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3201 select_frame_1 (WINDOW_FRAME (w));
3203 /* also select the window's buffer */
3204 if (NILP (norecord))
3205 Frecord_buffer (w->buffer);
3206 Fset_buffer (w->buffer);
3208 /* Go to the point recorded in the window.
3209 This is important when the buffer is in more
3210 than one window. It also matters when
3211 redisplay_window has altered point after scrolling,
3212 because it makes the change only in the window. */
3214 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3215 if (new_point < BUF_BEGV (current_buffer))
3216 new_point = BUF_BEGV (current_buffer);
3217 else if (new_point > BUF_ZV (current_buffer))
3218 new_point = BUF_ZV (current_buffer);
3220 BUF_SET_PT (current_buffer, new_point);
3223 MARK_WINDOWS_CHANGED (w);
3229 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3230 Lisp_Object override_frame)
3232 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3236 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3238 /* This function can GC */
3241 struct buffer *b = XBUFFER (buf);
3243 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3244 widen_buffer (b, 0);
3245 BUF_SET_PT (b, BUF_BEG (b));
3247 if (!NILP (Vtemp_buffer_show_function))
3248 call1 (Vtemp_buffer_show_function, buf);
3251 window = display_buffer (buf, Qnil, same_frame);
3253 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3254 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3256 Vminibuffer_scroll_window = window;
3257 w = XWINDOW (window);
3259 w->modeline_hscroll = 0;
3260 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3261 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3262 set_marker_restricted (w->sb_point, make_int (1), buf);
3264 /* Run temp-buffer-show-hook, with the chosen window selected. */
3265 if (!preparing_for_armageddon)
3268 tem = Fboundp (Qtemp_buffer_show_hook);
3271 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3274 int count = specpdl_depth ();
3276 /* Select the window that was chosen, for running
3278 record_unwind_protect (save_window_excursion_unwind,
3279 Fcurrent_window_configuration (Qnil));
3281 Fselect_window (window, Qnil);
3282 run_hook (Qtemp_buffer_show_hook);
3283 unbind_to (count, Qnil);
3291 make_dummy_parent (Lisp_Object window)
3294 struct window *o = XWINDOW (window);
3295 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3297 XSETWINDOW (new, p);
3298 copy_lcrecord (p, o);
3300 /* Don't copy the pointers to the line start cache or the face
3302 p->line_start_cache = Dynarr_new (line_start_cache);
3303 p->face_cachels = Dynarr_new (face_cachel);
3304 p->glyph_cachels = Dynarr_new (glyph_cachel);
3306 /* Put new into window structure in place of window */
3307 replace_window (window, new);
3315 p->start[CURRENT_DISP] = Qnil;
3316 p->start[DESIRED_DISP] = Qnil;
3317 p->start[CMOTION_DISP] = Qnil;
3318 p->pointm[CURRENT_DISP] = Qnil;
3319 p->pointm[DESIRED_DISP] = Qnil;
3320 p->pointm[CMOTION_DISP] = Qnil;
3325 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3326 Split WINDOW, putting SIZE lines in the first of the pair.
3327 WINDOW defaults to selected one and SIZE to half its size.
3328 If optional third arg HOR-FLAG is non-nil, split side by side
3329 and put SIZE columns in the first of the pair.
3331 (window, chsize, horflag))
3334 struct window *o, *p;
3340 window = Fselected_window (Qnil);
3342 CHECK_LIVE_WINDOW (window);
3344 o = XWINDOW (window);
3345 f = XFRAME (WINDOW_FRAME (o));
3349 if (!NILP (horflag))
3350 /* In the new scheme, we are symmetric with respect to separators
3351 so there is no need to do weird things here. */
3353 psize = WINDOW_WIDTH (o) >> 1;
3354 size = window_pixel_width_to_char_width (o, psize, 0);
3358 psize = WINDOW_HEIGHT (o) >> 1;
3359 size = window_pixel_height_to_char_height (o, psize, 1);
3365 size = XINT (chsize);
3366 if (!NILP (horflag))
3367 psize = window_char_width_to_pixel_width (o, size, 0);
3369 psize = window_char_height_to_pixel_height (o, size, 1);
3372 if (MINI_WINDOW_P (o))
3373 error ("Attempt to split minibuffer window");
3374 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3375 error ("Attempt to split unsplittable frame");
3377 check_min_window_sizes ();
3381 if (size < window_min_height)
3382 error ("Window height %d too small (after splitting)", size);
3383 if (size + window_min_height > window_char_height (o, 1))
3384 error ("Window height %d too small (after splitting)",
3385 window_char_height (o, 1) - size);
3386 if (NILP (o->parent)
3387 || NILP (XWINDOW (o->parent)->vchild))
3389 make_dummy_parent (window);
3390 reset_face_cachels (XWINDOW (window));
3392 XWINDOW (new)->vchild = window;
3393 XFRAME (o->frame)->mirror_dirty = 1;
3398 if (size < window_min_width)
3399 error ("Window width %d too small (after splitting)", size);
3400 if (size + window_min_width > window_char_width (o, 0))
3401 error ("Window width %d too small (after splitting)",
3402 window_char_width (o, 0) - size);
3403 if (NILP (o->parent)
3404 || NILP (XWINDOW (o->parent)->hchild))
3406 make_dummy_parent (window);
3407 reset_face_cachels (XWINDOW (window));
3409 XWINDOW (new)->hchild = window;
3410 XFRAME (o->frame)->mirror_dirty = 1;
3414 /* Now we know that window's parent is a vertical combination
3415 if we are dividing vertically, or a horizontal combination
3416 if we are making side-by-side windows */
3418 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3419 new = allocate_window ();
3422 p->frame = o->frame;
3424 if (!NILP (p->next))
3425 XWINDOW (p->next)->prev = new;
3428 p->parent = o->parent;
3431 reset_face_cachels (p);
3432 reset_glyph_cachels (p);
3435 /* Apportion the available frame space among the two new windows */
3437 if (!NILP (horflag))
3439 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3440 WINDOW_TOP (p) = WINDOW_TOP (o);
3441 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3442 WINDOW_WIDTH (o) = psize;
3443 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3447 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3448 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3449 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3450 WINDOW_HEIGHT (o) = psize;
3451 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3454 XFRAME (p->frame)->mirror_dirty = 1;
3455 /* do this last (after the window is completely initialized and
3456 the mirror-dirty flag is set) so that specifier recomputation
3457 caused as a result of this will work properly and not abort. */
3458 Fset_window_buffer (new, o->buffer);
3463 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3464 Make the selected window N lines bigger.
3465 From program, optional second arg SIDE non-nil means grow sideways N columns,
3466 and optional third arg WINDOW specifies the window to change instead of the
3471 struct window *w = decode_window (window);
3473 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3477 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3478 Make the selected window N pixels bigger.
3479 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3480 and optional third arg WINDOW specifies the window to change instead of the
3485 struct window *w = decode_window (window);
3487 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3491 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3492 Make the selected window N lines smaller.
3493 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3494 and optional third arg WINDOW specifies the window to change instead of the
3500 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3505 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3506 Make the selected window N pixels smaller.
3507 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3508 and optional third arg WINDOW specifies the window to change instead of the
3514 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3520 window_pixel_height (Lisp_Object window)
3522 return WINDOW_HEIGHT (XWINDOW (window));
3526 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3527 int include_gutters_p)
3530 int defheight, defwidth;
3534 XSETWINDOW (window, w);
3536 avail_height = (pixel_height -
3537 (include_gutters_p ? 0 :
3538 window_top_gutter_height (w) +
3539 window_bottom_gutter_height (w)));
3541 default_face_height_and_width (window, &defheight, &defwidth);
3543 char_height = avail_height / defheight;
3545 /* It's the calling function's responsibility to check these values
3546 and make sure they're not out of range.
3548 #### We need to go through the calling functions and actually
3550 return max (0, char_height);
3554 window_char_height_to_pixel_height (struct window *w, int char_height,
3555 int include_gutters_p)
3558 int defheight, defwidth;
3563 XSETWINDOW (window, w);
3565 default_face_height_and_width (window, &defheight, &defwidth);
3567 avail_height = char_height * defheight;
3568 pixel_height = (avail_height +
3569 (include_gutters_p ? 0 :
3570 window_top_gutter_height (w) +
3571 window_bottom_gutter_height (w)));
3573 /* It's the calling function's responsibility to check these values
3574 and make sure they're not out of range.
3576 #### We need to go through the calling functions and actually
3578 return max (0, pixel_height);
3581 /* Return number of default lines of text can fit in the window W.
3582 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3583 horizontal scrollbar) in the space that is used for the calculation.
3586 window_char_height (struct window *w, int include_gutters_p)
3588 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3593 * Return number of lines currently displayed in window w. If
3594 * end-of-buffer is displayed then the area below end-of-buffer is assume
3595 * to be blank lines of default height.
3596 * Does not include the modeline.
3599 window_displayed_height (struct window *w)
3601 struct buffer *b = XBUFFER (w->buffer);
3602 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3604 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3606 : w->window_end_pos[CURRENT_DISP]);
3608 if (!Dynarr_length (dla))
3609 return window_char_height (w, 0);
3611 num_lines = Dynarr_length (dla);
3613 /* #### Document and assert somewhere that w->window_end_pos == -1
3614 indicates that end-of-buffer is being displayed. */
3617 struct display_line *dl = Dynarr_atp (dla, 0);
3618 int ypos1 = dl->ypos + dl->descent;
3619 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3621 int defheight, defwidth;
3623 XSETWINDOW (window, w);
3629 if (Dynarr_length (dla) == 1)
3630 ypos1 = WINDOW_TEXT_TOP (w);
3633 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3634 /* If this line is clipped then we know that there is no
3635 blank room between eob and the modeline. If we are
3636 scrolling on clipped lines just know off the clipped
3638 if (scroll_on_clipped_lines && dl->clip)
3639 return num_lines - 1;
3640 ypos1 = dl->ypos + dl->descent - dl->clip;
3644 default_face_height_and_width (window, &defheight, &defwidth);
3645 /* #### This probably needs to know about the clipping area once a
3646 final definition is decided on. */
3647 num_lines += ((ypos2 - ypos1) / defheight);
3651 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3654 if (scroll_on_clipped_lines
3655 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3663 window_pixel_width (Lisp_Object window)
3665 return WINDOW_WIDTH (XWINDOW (window));
3669 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3670 int include_margins_p)
3674 int defheight, defwidth;
3677 XSETWINDOW (window, w);
3679 avail_width = (pixel_width -
3680 window_left_gutter_width (w, 0) -
3681 window_right_gutter_width (w, 0) -
3682 (include_margins_p ? 0 : window_left_margin_width (w)) -
3683 (include_margins_p ? 0 : window_right_margin_width (w)));
3685 default_face_height_and_width (window, &defheight, &defwidth);
3687 char_width = (avail_width / defwidth);
3689 /* It's the calling function's responsibility to check these values
3690 and make sure they're not out of range.
3692 #### We need to go through the calling functions and actually
3694 return max (0, char_width);
3698 window_char_width_to_pixel_width (struct window *w, int char_width,
3699 int include_margins_p)
3703 int defheight, defwidth;
3706 XSETWINDOW (window, w);
3708 default_face_height_and_width (window, &defheight, &defwidth);
3710 avail_width = char_width * defwidth;
3711 pixel_width = (avail_width +
3712 window_left_gutter_width (w, 0) +
3713 window_right_gutter_width (w, 0) +
3714 (include_margins_p ? 0 : window_left_margin_width (w)) +
3715 (include_margins_p ? 0 : window_right_margin_width (w)));
3717 /* It's the calling function's responsibility to check these values
3718 and make sure they're not out of range.
3720 #### We need to go through the calling functions and actually
3722 return max (0, pixel_width);
3725 /* This returns the usable space which doesn't include space needed by
3726 scrollbars or divider lines. */
3728 window_char_width (struct window *w, int include_margins_p)
3730 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3734 #define MINSIZE(w) \
3736 ? window_min_width * defwidth \
3737 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3740 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3742 #define CURSIZE(w) \
3743 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3745 #define CURCHARSIZE(w) \
3746 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3748 #define MINCHARSIZE(window) \
3749 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3750 ? 1 : window_min_height)
3752 /* Unlike set_window_pixheight, this function
3753 also changes the heights of the siblings so as to
3754 keep everything consistent. */
3757 change_window_height (struct window *win, int delta, int widthflag,
3765 int (*sizefun) (Lisp_Object) = (widthflag
3766 ? window_pixel_width
3767 : window_pixel_height);
3768 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3769 ? set_window_pixwidth
3770 : set_window_pixheight);
3772 int defheight, defwidth;
3777 check_min_window_sizes ();
3779 XSETWINDOW (window, win);
3780 f = XFRAME (win->frame);
3781 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3782 error ("Won't change only window");
3784 /* #### This is very likely incorrect and instead the char_to_pixel_
3785 functions should be called. */
3786 default_face_height_and_width (window, &defheight, &defwidth);
3790 w = XWINDOW (window);
3795 error ("No other window to side of this one");
3799 ? !NILP (XWINDOW (parent)->hchild)
3800 : !NILP (XWINDOW (parent)->vchild))
3805 sizep = &CURSIZE (w);
3806 dim = CURCHARSIZE (w);
3808 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3809 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3811 if (MINI_WINDOW_P (XWINDOW (window)))
3813 else if (!NILP (parent))
3815 Fdelete_window (window, Qnil);
3821 delta *= (widthflag ? defwidth : defheight);
3826 maxdelta = ((!NILP (parent))
3827 ? (*sizefun) (parent) - *sizep
3828 : ((!NILP (w->next))
3829 ? (*sizefun) (w->next) - MINSIZE (w->next)
3830 : ((!NILP (w->prev))
3831 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3832 /* This is a frame with only one window,
3833 a minibuffer-only or a minibufferless frame. */
3836 if (delta > maxdelta)
3837 /* This case traps trying to make the minibuffer
3838 the full frame, or make the only window aside from the
3839 minibuffer the full frame. */
3846 /* #### Chuck: is this correct? */
3847 if (*sizep + delta < MINSIZE (window))
3849 Fdelete_window (window);
3855 if (!NILP (w->next) &&
3856 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3858 CURBEG (XWINDOW (w->next)) += delta;
3859 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3860 (*setsizefun) (window, *sizep + delta, 0);
3862 else if (!NILP (w->prev) &&
3863 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3865 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3866 CURBEG (w) -= delta;
3867 (*setsizefun) (window, *sizep + delta, 0);
3872 int opht = (*sizefun) (parent);
3874 /* If trying to grow this window to or beyond size of the parent,
3875 make delta1 so big that, on shrinking back down,
3876 all the siblings end up with less than one line and are deleted. */
3877 if (opht <= *sizep + delta)
3878 delta1 = opht * opht * 2;
3879 /* Otherwise, make delta1 just right so that if we add delta1
3880 lines to this window and to the parent, and then shrink
3881 the parent back to its original size, the new proportional
3882 size of this window will increase by delta. */
3884 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3886 /* Add delta1 lines or columns to this window, and to the parent,
3887 keeping things consistent while not affecting siblings. */
3888 CURSIZE (XWINDOW (parent)) = opht + delta1;
3889 (*setsizefun) (window, *sizep + delta1, 0);
3891 /* Squeeze out delta1 lines or columns from our parent,
3892 shrinking this window and siblings proportionately.
3893 This brings parent back to correct size.
3894 Delta1 was calculated so this makes this window the desired size,
3895 taking it all out of the siblings. */
3896 (*setsizefun) (parent, opht, 0);
3899 SET_LAST_MODIFIED (w, 0);
3900 SET_LAST_FACECHANGE (w);
3901 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3902 /* overkill maybe, but better to be correct */
3903 MARK_FRAME_GUTTERS_CHANGED (f);
3913 /* Scroll contents of window WINDOW up N lines. */
3915 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3916 Error_behavior errb)
3918 struct window *w = XWINDOW (window);
3919 struct buffer *b = XBUFFER (w->buffer);
3920 int selected = EQ (window, Fselected_window (Qnil));
3922 Lisp_Object point, tem;
3925 point = make_int (BUF_PT (b));
3928 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3930 if (pos < BUF_BEGV (b))
3932 else if (pos > BUF_ZV (b))
3935 point = make_int (pos);
3938 /* Always set force_start so that redisplay_window will run
3939 the window-scroll-functions. */
3942 /* #### When the fuck does this happen? I'm so glad that history has
3943 completely documented the behavior of the scrolling functions under
3944 all circumstances. */
3945 tem = Fpos_visible_in_window_p (point, window);
3948 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
3950 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
3951 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
3952 MARK_WINDOWS_CHANGED (w);
3961 n = Fprefix_numeric_value (n);
3962 value = XINT (n) * direction;
3965 return; /* someone just made a pointless call */
3969 /* If the user didn't specify how far to scroll then we have to figure it
3970 out by ourselves. */
3971 if (NILP (n) || EQ (n, Qminus))
3973 /* Going forwards is easy. If that is what we are doing then just
3974 set value and the section which handles the user specifying a
3975 positive value will work. */
3978 value = window_displayed_height (w) - next_screen_context_lines;
3979 value = (value < 1 ? 1 : value);
3982 /* Going backwards is hard. We can't use the same loop used if the
3983 user specified a negative value because we care about
3984 next_screen_context_lines. In a variable height world you don't
3985 know how many lines above you can actually be displayed and still
3986 have the context lines appear. So we leave value set to 0 and add
3987 a separate section to deal with this. */
3991 if (direction == 1 && !value)
3998 Bufpos startp, old_start;
4000 old_start = marker_position (w->start[CURRENT_DISP]);
4001 startp = vmotion (w, old_start, value, &vtarget);
4003 if (vtarget < value &&
4004 (w->window_end_pos[CURRENT_DISP] == -1
4005 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4007 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4012 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4015 w->start_at_line_beg = beginning_of_line_p (b, startp);
4016 MARK_WINDOWS_CHANGED (w);
4018 if (!point_would_be_visible (w, startp, XINT (point)))
4021 BUF_SET_PT (b, startp);
4023 set_marker_restricted (w->pointm[CURRENT_DISP],
4032 Bufpos startp, old_start;
4034 old_start = marker_position (w->start[CURRENT_DISP]);
4035 startp = vmotion (w, old_start, value, &vtarget);
4038 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4040 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4045 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4048 w->start_at_line_beg = beginning_of_line_p (b, startp);
4049 MARK_WINDOWS_CHANGED (w);
4051 if (!point_would_be_visible (w, startp, XINT (point)))
4055 if (MINI_WINDOW_P (w))
4058 new_point = start_of_last_line (w, startp);
4061 BUF_SET_PT (b, new_point);
4063 set_marker_restricted (w->pointm[CURRENT_DISP],
4064 make_int (new_point),
4069 else /* value == 0 && direction == -1 */
4071 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4073 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4079 int movement = next_screen_context_lines - 1;
4080 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4081 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4083 start_with_point_on_display_line (w, bottom,
4084 -1 - (movement - vtarget));
4086 if (startp >= old_startp)
4087 startp = vmotion (w, old_startp, -1, NULL);
4089 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4092 w->start_at_line_beg = beginning_of_line_p (b, startp);
4093 MARK_WINDOWS_CHANGED (w);
4095 if (!point_would_be_visible (w, startp, XINT (point)))
4097 Bufpos new_point = start_of_last_line (w, startp);
4100 BUF_SET_PT (b, new_point);
4102 set_marker_restricted (w->pointm[CURRENT_DISP],
4103 make_int (new_point),
4111 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4112 Scroll text of current window upward N lines; or near full screen if no arg.
4113 A near full screen is `next-screen-context-lines' less than a full screen.
4114 Negative N means scroll downward.
4115 When calling from a program, supply an integer as argument or nil.
4116 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4117 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4122 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4126 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4127 Scroll text of current window downward N lines; or near full screen if no arg.
4128 A near full screen is `next-screen-context-lines' less than a full screen.
4129 Negative N means scroll upward.
4130 When calling from a program, supply a number as argument or nil.
4131 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4132 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4137 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4141 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4142 Return the other window for "other window scroll" commands.
4143 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4144 specifies the window.
4145 If `other-window-scroll-buffer' is non-nil, a window
4146 showing that buffer is used.
4151 Lisp_Object selected_window = Fselected_window (Qnil);
4153 if (MINI_WINDOW_P (XWINDOW (selected_window))
4154 && !NILP (Vminibuffer_scroll_window))
4155 window = Vminibuffer_scroll_window;
4156 /* If buffer is specified, scroll that buffer. */
4157 else if (!NILP (Vother_window_scroll_buffer))
4159 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4161 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4165 /* Nothing specified; look for a neighboring window on the same
4167 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4169 if (EQ (window, selected_window))
4170 /* That didn't get us anywhere; look for a window on another
4173 window = Fnext_window (window, Qnil, Qt, Qnil);
4174 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4175 && ! EQ (window, selected_window));
4178 CHECK_LIVE_WINDOW (window);
4180 if (EQ (window, selected_window))
4181 error ("There is no other window");
4186 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4187 Scroll next window upward N lines; or near full frame if no arg.
4188 The next window is the one below the current one; or the one at the top
4189 if the current one is at the bottom. Negative N means scroll downward.
4190 When calling from a program, supply a number as argument or nil.
4192 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4193 specifies the window to scroll.
4194 If `other-window-scroll-buffer' is non-nil, scroll the window
4195 showing that buffer, popping the buffer up if necessary.
4199 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4203 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4204 Scroll selected window display N columns left.
4205 Default for N is window width minus 2.
4209 Lisp_Object window = Fselected_window (Qnil);
4210 struct window *w = XWINDOW (window);
4211 int count = (NILP (n) ?
4212 window_char_width (w, 0) - 2 :
4213 XINT (Fprefix_numeric_value (n)));
4215 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4218 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4219 Scroll selected window display N columns right.
4220 Default for N is window width minus 2.
4224 Lisp_Object window = Fselected_window (Qnil);
4225 struct window *w = XWINDOW (window);
4226 int count = (NILP (n) ?
4227 window_char_width (w, 0) - 2 :
4228 XINT (Fprefix_numeric_value (n)));
4230 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4233 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4234 Center point in WINDOW. With N, put point on line N.
4235 The desired position of point is always relative to the window.
4236 If WINDOW is nil, the selected window is used.
4240 struct window *w = decode_window (window);
4241 struct buffer *b = XBUFFER (w->buffer);
4242 Bufpos opoint = BUF_PT (b);
4246 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4249 n = Fprefix_numeric_value (n);
4251 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4254 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4256 w->start_at_line_beg = beginning_of_line_p (b, startp);
4258 MARK_WINDOWS_CHANGED (w);
4262 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4263 Position point relative to WINDOW.
4264 With no argument, position text at center of window.
4265 An argument specifies window line; zero means top of window,
4266 negative means relative to bottom of window.
4267 If WINDOW is nil, the selected window is used.
4274 Bufpos start, new_point;
4277 /* Don't use decode_window() because we need the new value of
4280 window = Fselected_window (Qnil);
4282 CHECK_LIVE_WINDOW (window);
4283 w = XWINDOW (window);
4284 b = XBUFFER (w->buffer);
4286 height = window_displayed_height (w);
4287 selected = EQ (window, Fselected_window (w->frame));
4293 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4294 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4296 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4299 BUF_SET_PT (b, new_point);
4301 Fset_window_point (window, make_int (new_point));
4303 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4307 start = marker_position (w->start[CURRENT_DISP]);
4308 if (start < BUF_BEGV (b))
4309 start = BUF_BEGV (b);
4310 else if (start > BUF_ZV (b))
4314 new_point = BUF_PT (b);
4316 new_point = marker_position (w->pointm[CURRENT_DISP]);
4318 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4321 BUF_SET_PT (b, new_point);
4323 Fset_window_point (window, make_int (new_point));
4325 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4328 return make_int (retval);
4332 /* #### Is this going to work right when at eob? */
4333 arg = Fprefix_numeric_value (arg);
4335 XSETINT (arg, XINT (arg) + height);
4338 start = marker_position (w->start[CURRENT_DISP]);
4339 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4342 new_point = BUF_PT (b);
4344 new_point = marker_position (w->pointm[CURRENT_DISP]);
4346 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4349 BUF_SET_PT (b, new_point);
4351 Fset_window_point (window, make_int (new_point));
4353 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4355 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4361 BUF_SET_PT (b, start);
4363 Fset_window_point (window, make_int (start));
4367 return Fvertical_motion (arg, window, Qnil);
4371 new_point = vmotion (XWINDOW (window),
4372 marker_position (w->pointm[CURRENT_DISP]),
4374 Fset_window_point (window, make_int (new_point));
4375 return make_int (vpos);
4381 map_windows_1 (Lisp_Object window,
4382 int (*mapfun) (struct window *w, void *closure),
4385 for (; !NILP (window); window = XWINDOW (window)->next)
4388 struct window *w = XWINDOW (window);
4390 if (!NILP (w->vchild))
4391 retval = map_windows_1 (w->vchild, mapfun, closure);
4392 else if (!NILP (w->hchild))
4393 retval = map_windows_1 (w->hchild, mapfun, closure);
4395 retval = (mapfun) (w, closure);
4404 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4405 invocation of MAPFUN. If any invocation of MAPFUN returns
4406 non-zero, the mapping is halted. Otherwise, map_windows() maps
4407 over all windows in F.
4409 If MAPFUN creates or deletes windows, the behavior is undefined. */
4412 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4416 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4419 Lisp_Object frmcons, devcons, concons;
4421 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4423 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4435 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4438 w->shadow_thickness_changed = 1;
4439 MARK_WINDOWS_CHANGED (w);
4443 vertical_divider_changed_in_window (Lisp_Object specifier,
4447 MARK_WINDOWS_CHANGED (w);
4448 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4451 /* also used in scrollbar.c */
4453 some_window_value_changed (Lisp_Object specifier, struct window *w,
4456 MARK_WINDOWS_CHANGED (w);
4459 #ifdef MEMORY_USAGE_STATS
4465 #ifdef HAVE_SCROLLBARS
4469 int other_redisplay;
4474 compute_window_mirror_usage (struct window_mirror *mir,
4475 struct window_stats *stats,
4476 struct overhead_stats *ovstats)
4480 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4482 #ifdef HAVE_SCROLLBARS
4484 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4487 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4490 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4493 #endif /* HAVE_SCROLLBARS */
4494 stats->other_redisplay +=
4495 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4496 stats->other_redisplay +=
4497 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4501 compute_window_usage (struct window *w, struct window_stats *stats,
4502 struct overhead_stats *ovstats)
4505 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4506 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4507 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4508 stats->line_start +=
4509 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4510 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4513 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4514 Return stats about the memory usage of window WINDOW.
4515 The values returned are in the form of an alist of usage types and byte
4516 counts. The byte counts attempt to encompass all the memory used
4517 by the window (separate from the memory logically associated with a
4518 buffer or frame), including internal structures and any malloc()
4519 overhead associated with them. In practice, the byte counts are
4520 underestimated because certain memory usage is very hard to determine
4521 \(e.g. the amount of memory used inside the Xt library or inside the
4522 X server) and because there is other stuff that might logically
4523 be associated with a window, buffer, or frame (e.g. window configurations,
4524 glyphs) but should not obviously be included in the usage counts.
4526 Multiple slices of the total memory usage may be returned, separated
4527 by a nil. Each slice represents a particular view of the memory, a
4528 particular way of partitioning it into groups. Within a slice, there
4529 is no overlap between the groups of memory, and each slice collectively
4530 represents all the memory concerned.
4534 struct window_stats stats;
4535 struct overhead_stats ovstats;
4536 Lisp_Object val = Qnil;
4538 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4540 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4542 val = acons (Qface_cache, make_int (stats.face), val);
4543 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4544 #ifdef HAVE_SCROLLBARS
4545 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4547 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4548 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4549 val = acons (Qother, make_int (stats.other), val);
4550 val = Fcons (Qnil, val);
4551 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4552 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4553 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4555 return Fnreverse (val);
4558 #endif /* MEMORY_USAGE_STATS */
4561 /************************************************************************/
4562 /* Window configurations */
4563 /************************************************************************/
4565 /* #### This window configuration stuff has had serious bugs lurking in it
4566 for years; it would be a -huge- win if this was reimplemented in lisp.
4569 /* If you add anything to this structure make sure saved_window_equal
4573 Lisp_Object window; /* window */
4574 Lisp_Object buffer; /* buffer */
4575 Lisp_Object start; /* copied marker */
4576 Lisp_Object pointm; /* copied marker */
4577 Lisp_Object sb_point; /* copied marker */
4578 Lisp_Object mark; /* copied marker */
4584 int modeline_hscroll;
4585 int parent_index; /* index into saved_windows */
4586 int prev_index; /* index into saved_windows */
4587 char start_at_line_beg; /* boolean */
4589 #define WINDOW_SLOT_DECLARATION
4590 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4591 #include "winslots.h"
4594 /* If you add anything to this structure make sure window_config_equal
4596 struct window_config
4598 struct lcrecord_header header;
4599 /* int frame_width; No longer needed, JV
4600 int frame_height; */
4602 Lisp_Object selected_frame;
4604 Lisp_Object current_window;
4605 Lisp_Object current_buffer;
4606 Lisp_Object minibuffer_scroll_window;
4607 Lisp_Object root_window;
4608 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4609 /* Record the values of window-min-width and window-min-height
4610 so that window sizes remain consistent with them. */
4611 int min_width, min_height;
4612 int saved_windows_count;
4613 /* Zero-sized arrays aren't ANSI C */
4614 struct saved_window saved_windows[1];
4617 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4618 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4619 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4620 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4621 #define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
4622 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4625 mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
4627 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4629 markobj (config->current_window);
4630 markobj (config->current_buffer);
4631 markobj (config->minibuffer_scroll_window);
4632 markobj (config->root_window);
4634 for (i = 0; i < config->saved_windows_count; i++)
4636 struct saved_window *s = SAVED_WINDOW_N (config, i);
4637 markobj (s->window);
4638 markobj (s->buffer);
4640 markobj (s->pointm);
4641 markobj (s->sb_point);
4644 /* #### This looked like this. I do not see why specifier cached
4645 values should not be marked, as such specifiers as toolbars
4646 might have GC-able instances. Freed configs are not marked,
4647 aren't they? -- kkm */
4648 markobj (s->dedicated);
4650 #define WINDOW_SLOT(slot, compare) ((void) (markobj (s->slot)))
4651 #include "winslots.h"
4658 sizeof_window_config_for_n_windows (int n)
4660 return (sizeof (struct window_config) +
4661 /* n - 1 because zero-sized arrays aren't ANSI C */
4662 (n - 1) *sizeof (struct saved_window));
4666 sizeof_window_config (CONST void *h)
4668 CONST struct window_config *c = (CONST struct window_config *) h;
4669 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4673 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4675 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4678 error ("printing unreadable object #<window-configuration 0x%x>",
4679 config->header.uid);
4680 write_c_string ("#<window-configuration ", printcharfun);
4681 sprintf (buf, "0x%x>", config->header.uid);
4682 write_c_string (buf, printcharfun);
4685 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4686 window_configuration,
4688 print_window_config,
4689 0, 0, 0, 0, sizeof_window_config,
4690 struct window_config);
4693 /* Returns a boolean indicating whether the two saved windows are
4696 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4698 #define WINDOW_SLOT(slot, compare) \
4699 if (!compare (win1->slot, win2->slot)) \
4701 #include "winslots.h"
4704 EQ (win1->window, win2->window) &&
4705 EQ (win1->buffer, win2->buffer) &&
4706 internal_equal (win1->start, win2->start, 0) &&
4707 internal_equal (win1->pointm, win2->pointm, 0) &&
4708 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4709 internal_equal (win1->mark, win2->mark, 0) &&
4710 win1->pixel_left == win2->pixel_left &&
4711 win1->pixel_top == win2->pixel_top &&
4712 win1->pixel_width == win2->pixel_width &&
4713 win1->pixel_height == win2->pixel_height &&
4714 win1->hscroll == win2->hscroll &&
4715 win1->modeline_hscroll == win2->modeline_hscroll &&
4716 win1->parent_index == win2->parent_index &&
4717 win1->prev_index == win2->prev_index &&
4718 win1->start_at_line_beg == win2->start_at_line_beg;
4721 /* Returns a boolean indicating whether the two given configurations
4724 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4726 struct window_config *fig1, *fig2;
4729 /* First check if they are truly the same. */
4730 if (EQ (conf1, conf2))
4733 fig1 = XWINDOW_CONFIGURATION (conf1);
4734 fig2 = XWINDOW_CONFIGURATION (conf2);
4736 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4737 EQ (fig1->current_window, fig2->current_window) &&
4738 EQ (fig1->current_buffer, fig2->current_buffer) &&
4739 EQ (fig1->root_window, fig2->root_window) &&
4740 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
4742 fig1->frame_width == fig2->frame_width &&
4743 fig1->frame_height == fig2->frame_height)) */
4746 for (i = 0; i < fig1->saved_windows_count; i++)
4748 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4749 SAVED_WINDOW_N (fig2, i)))
4756 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4757 Return t if OBJECT is a window-configuration object.
4761 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4765 mark_windows_in_use_closure (struct window *w, void *closure)
4767 int mark = *(int *)closure;
4768 w->config_mark = mark;
4773 mark_windows_in_use (struct frame *f, int mark)
4775 map_windows (f, mark_windows_in_use_closure, &mark);
4778 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4780 free_window_configuration (Lisp_Object window_config)
4783 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4785 /* Free all the markers. It's not completely necessary that
4786 we do this (window configs sitting in a free list aren't
4787 marked normally so the markers wouldn't be marked anyway)
4788 but it's more efficient. */
4789 for (i = 0; i < config->saved_windows_count; i++)
4791 struct saved_window *p = SAVED_WINDOW_N (config, i);
4793 if (!NILP (p->pointm))
4795 free_marker (XMARKER (p->pointm));
4798 if (!NILP (p->start))
4800 free_marker (XMARKER (p->start));
4803 if (!NILP (p->sb_point))
4805 free_marker (XMARKER (p->sb_point));
4808 if (!NILP (p->mark))
4810 free_marker (XMARKER (p->mark));
4815 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4816 free_managed_lcrecord (Vwindow_configuration_free_list
4817 [config->saved_windows_count - 1],
4823 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4824 Set the configuration of windows and buffers as specified by CONFIGURATION.
4825 CONFIGURATION must be a value previously returned
4826 by `current-window-configuration' (which see).
4831 struct window_config *config;
4832 struct saved_window *p;
4833 Lisp_Object new_current_buffer;
4837 struct gcpro gcpro1;
4838 Lisp_Object old_window_config;
4839 /* int previous_frame_height;
4840 int previous_frame_width;*/
4841 int previous_pixel_top;
4842 int previous_pixel_height;
4843 int previous_pixel_left;
4844 int previous_pixel_width;
4845 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
4846 int real_font_height;
4847 int converted_minibuf_height,target_minibuf_height;
4848 int specpdl_count = specpdl_depth ();
4850 GCPRO1 (configuration);
4852 CHECK_WINDOW_CONFIGURATION (configuration);
4853 config = XWINDOW_CONFIGURATION (configuration);
4855 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4858 /* Do not signal an error here if the frame was deleted. There are
4859 reasonable cases where we could get here with a deleted frame and
4860 just want to do close to nothing instead. */
4862 if (FRAME_LIVE_P (f))
4864 /* restore the frame characteristics */
4866 new_current_buffer = config->current_buffer;
4867 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4868 new_current_buffer = Qnil;
4871 * Assumed precondition: w->config_mark = 0 for all w
4872 * This procedure should ensure this is true by the time it exits
4873 * to ensure the precondition for future calls.
4875 * We use w->config_mark to know whether we're modifying a
4876 * window that is currently visible on the frame (#### we
4877 * should just be able to check whether the window is dead
4878 * or not, but this way is safer?). As we process each
4879 * window, we set its config_mark to 0. At the end, we
4880 * go through all the windows that used to be on the frame,
4881 * set each one's config_mark to 0 (to maintain the
4882 * assumed precondition) and delete each one that's no
4885 * #### Using a window-configuration to keep track of
4886 * the current windows is wasteful. All we need is the
4887 * list of windows, so we could just use a dynarr.
4889 old_window_config = Fcurrent_window_configuration (frame);
4891 /* If the new configuration is already equal to the old, then stop
4892 right here. This saves the work below and it also saves
4893 triggering a full redisplay of this window. This is a huge win
4894 when using the mouse since the mode motion code uses
4895 save-window-excursion extensively but will rarely cause the
4896 configuration to actually change. */
4897 if (window_config_equal (configuration, old_window_config))
4899 free_window_configuration (old_window_config);
4904 /* We can't quit or even check for quit because that may cause
4905 investigation of the frame state, which may crash if the frame is
4906 in an inconsistent state. */
4907 begin_dont_check_for_quit ();
4908 record_unwind_protect (free_window_configuration, old_window_config);
4910 mark_windows_in_use (f, 1);
4913 /* JV: This is bogus,
4914 First of all, the units are inconsistent. The frame sizes are measured
4915 in characters but the window sizes are stored in pixels. So if a
4916 font size change happened between saving and restoring, the
4917 frame "sizes" maybe equal but the windows still should be
4918 resized. This is tickled alot by the new "character size
4919 stays constant" policy in 21.0. It leads to very wierd
4920 glitches (and possibly craches when asserts are tickled).
4922 Just changing the units doens't help because changing the
4923 toolbar configuration can also change the pixel positions.
4924 Luckily there is a much simpler way of doing this, see below.
4926 previous_frame_width = FRAME_WIDTH (f);
4927 previous_frame_height = FRAME_HEIGHT (f);
4928 /* If the frame has been resized since this window configuration was
4929 made, we change the frame to the size specified in the
4930 configuration, restore the configuration, and then resize it
4931 back. We keep track of the prevailing height in these variables. */
4932 if (config->frame_height != FRAME_HEIGHT (f)
4933 || config->frame_width != FRAME_WIDTH (f))
4934 change_frame_size (f, config->frame_height, config->frame_width, 0);
4937 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
4938 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
4939 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
4940 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
4942 /* remember some properties of the minibuffer */
4944 default_face_height_and_width (frame, &real_font_height, 0);
4945 assert(real_font_height > 0);
4947 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
4949 previous_minibuf_height
4950 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
4951 previous_minibuf_top
4952 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
4953 previous_minibuf_width
4954 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
4958 previous_minibuf_height = 0;
4959 previous_minibuf_width = 0;
4961 converted_minibuf_height =
4962 (previous_minibuf_height % real_font_height) == 0 ?
4963 - (previous_minibuf_height / real_font_height ) : /* lines */
4964 previous_minibuf_height; /* pixels */
4966 /* Temporarily avoid any problems with windows that are smaller
4967 than they are supposed to be. */
4968 window_min_height = 1;
4969 window_min_width = 1;
4971 /* OK, now restore all the windows in the window config.
4972 This may involve "undeleting" windows, since the
4973 windows in the window config may be deleted.
4975 for (k = 0; k < config->saved_windows_count; k++)
4977 p = SAVED_WINDOW_N (config, k);
4978 w = XWINDOW (p->window);
4981 /* The window might be dead. In this case, its redisplay
4982 structures were freed, so we need to reallocate them. */
4983 if (!w->face_cachels)
4985 w->face_cachels = Dynarr_new (face_cachel);
4986 reset_face_cachels (w);
4988 if (!w->glyph_cachels)
4989 w->glyph_cachels = Dynarr_new (glyph_cachel);
4990 if (!w->line_start_cache)
4991 w->line_start_cache = Dynarr_new (line_start_cache);
4994 if (p->parent_index >= 0)
4995 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
4999 if (p->prev_index >= 0)
5001 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5003 /* This is true for a minibuffer-only frame. */
5004 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5007 XWINDOW (w->prev)->next = p->window;
5012 if (!NILP (w->parent))
5014 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5016 XWINDOW (w->parent)->vchild = p->window;
5017 XWINDOW (w->parent)->hchild = Qnil;
5021 XWINDOW (w->parent)->hchild = p->window;
5022 XWINDOW (w->parent)->vchild = Qnil;
5026 if (!w->config_mark)
5028 /* #### This should be equivalent to the window previously
5029 having been dead. If we're brave, we'll put in an
5030 assertion to this effect. */
5031 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5033 else /* if (!EQ (w->buffer, p->buffer)) */
5035 /* With the new redisplay we let it know that a change has
5036 been made and it will take care of the rest. If we don't
5037 tell it something has possibly changed it could lead to
5038 incorrect display. */
5039 MARK_WINDOWS_CHANGED (w);
5042 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5043 WINDOW_TOP (w) = WINDOW_TOP (p);
5044 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5045 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5046 w->hscroll = p->hscroll;
5047 w->modeline_hscroll = p->modeline_hscroll;
5048 w->line_cache_last_updated = Qzero;
5049 SET_LAST_MODIFIED (w, 1);
5050 SET_LAST_FACECHANGE (w);
5053 #define WINDOW_SLOT(slot, compare) w->slot = p->slot;
5054 #include "winslots.h"
5056 /* Reinstall the saved buffer and pointers into it. */
5057 if (NILP (p->buffer))
5058 w->buffer = p->buffer;
5061 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5062 /* If saved buffer is alive, install it. */
5064 w->buffer = p->buffer;
5065 w->start_at_line_beg = p->start_at_line_beg;
5066 set_marker_restricted (w->start[CURRENT_DISP],
5067 Fmarker_position (p->start),
5069 set_marker_restricted (w->pointm[CURRENT_DISP],
5070 Fmarker_position (p->pointm),
5072 set_marker_restricted (w->sb_point,
5073 Fmarker_position (p->sb_point),
5075 Fset_marker (XBUFFER (w->buffer)->mark,
5076 Fmarker_position (p->mark), w->buffer);
5078 /* As documented in Fcurrent_window_configuration, don't
5079 save the location of point in the buffer which was current
5080 when the window configuration was recorded. */
5081 if (!EQ (p->buffer, new_current_buffer) &&
5082 XBUFFER (p->buffer) == current_buffer)
5083 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5085 else if (NILP (w->buffer) ||
5086 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5087 /* Else if window's old buffer is dead too, get a live one. */
5089 /* #### The following line makes me nervous... */
5090 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5091 w->buffer = Fget_buffer_create (QSscratch);
5092 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5093 /* This will set the markers to beginning of visible
5095 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5096 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5098 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5099 w->start_at_line_beg = 1;
5102 /* Keeping window's old buffer; make sure the markers
5105 /* Set window markers at start of visible range. */
5106 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5107 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5109 if (XMARKER (w->sb_point)->buffer == 0)
5110 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5111 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5112 set_marker_restricted (w->pointm[CURRENT_DISP],
5114 (BUF_PT (XBUFFER (w->buffer))),
5116 w->start_at_line_beg = 1;
5121 FRAME_ROOT_WINDOW (f) = config->root_window;
5122 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5123 then calls do_switch_frame() below to select the frame that was
5124 recorded in the window config as being selected.
5126 Instead, we don't ever change the selected frame, and either
5127 call Fselect_window() below if the window config's frame is
5128 currently selected, or just set the selected window of the
5129 window config's frame. */
5132 /* Set the frame height to the value it had before this function. */
5133 if (previous_frame_height != FRAME_HEIGHT (f)
5134 || previous_frame_width != FRAME_WIDTH (f))
5135 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5137 /* We just reset the size and position of the minibuffer, to its old
5138 value, which needn't be valid. So we do some magic to see which value
5139 to actually take. Then we set it.
5142 We take the old value if is in the same units but differs from the
5145 #### Now we get more cases correct then ever before, but
5146 are we treating all? For instance what if the frames minibuf window
5147 is no longer the same one?
5149 target_minibuf_height = previous_minibuf_height;
5150 if (converted_minibuf_height &&
5151 (converted_minibuf_height * config->minibuf_height) > 0 &&
5152 (converted_minibuf_height != config->minibuf_height))
5154 target_minibuf_height = config->minibuf_height < 0 ?
5155 - (config->minibuf_height * real_font_height) :
5156 config->minibuf_height;
5157 target_minibuf_height =
5158 max(target_minibuf_height,real_font_height);
5160 if (previous_minibuf_height)
5162 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5163 = previous_minibuf_top -
5164 (target_minibuf_height - previous_minibuf_height);
5165 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5166 target_minibuf_height, 0);
5167 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5168 previous_minibuf_width, 0);
5171 /* This is a better way to deal with frame resizing, etc.
5172 What we _actually_ want is for the old (just restored)
5174 into the place of the new one. So we just do that. Simple! */
5175 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5176 /* Note that this function also updates the subwindow
5178 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5179 previous_pixel_height -
5180 (target_minibuf_height - previous_minibuf_height), 0);
5181 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5182 /* Note that this function also updates the subwindow
5184 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5186 /* If restoring in the current frame make the window current,
5187 otherwise just update the frame selected_window slot to be
5188 the restored current_window. */
5189 if (f == selected_frame ())
5191 /* When using `pop-window-configuration', often the minibuffer
5192 ends up as the selected window even though it's not active ...
5193 I really don't know the cause of this, but it should never
5194 happen. This kludge should fix it.
5196 #### Find out why this is really going wrong. */
5197 if (!minibuf_level &&
5198 MINI_WINDOW_P (XWINDOW (config->current_window)))
5199 Fselect_window (Fnext_window (config->current_window,
5203 Fselect_window (config->current_window, Qnil);
5204 if (!NILP (new_current_buffer))
5205 Fset_buffer (new_current_buffer);
5207 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5210 set_frame_selected_window (f, config->current_window);
5213 old_window_config = Qnil; /* Warning suppression */
5215 /* Restore the minimum heights recorded in the configuration. */
5216 window_min_height = config->min_height;
5217 window_min_width = config->min_width;
5220 /* see above comment */
5221 /* Fselect_window will have made f the selected frame, so we
5222 reselect the proper frame here. Fhandle_switch_frame will change the
5223 selected window too, but that doesn't make the call to
5224 Fselect_window above totally superfluous; it still sets f's
5226 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5227 do_switch_frame (config->selected_frame, Qnil, 0);
5230 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5232 if (FRAME_LIVE_P (f))
5234 /* Do this before calling recompute_all_cached_specifiers_in_window()
5235 so that things like redisplay_redraw_cursor() won't abort due
5236 to no window mirror present. */
5237 f->mirror_dirty = 1;
5239 config = XWINDOW_CONFIGURATION (old_window_config);
5240 for (k = 0; k < config->saved_windows_count; k++)
5242 p = SAVED_WINDOW_N (config, k);
5243 w = XWINDOW (p->window);
5244 /* Remember, we set w->config_mark on all currently visible
5245 windows, and reset it on all newly visible windows.
5246 Any windows still marked need to be deleted. */
5249 mark_window_as_deleted (w);
5254 /* We just potentially changed the window's buffer and
5255 potentially turned a dead window into a live one,
5256 so we need to recompute the cached specifier values. */
5257 recompute_all_cached_specifiers_in_window (w);
5262 /* Now restore things, when everything else if OK. */
5264 unbind_to (specpdl_count, Qnil);
5271 /* Mark all subwindows of a window as deleted. The argument
5272 W is actually the subwindow tree of the window in question. */
5275 delete_all_subwindows (struct window *w)
5277 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5278 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5279 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5281 mark_window_as_deleted (w);
5286 count_windows (struct window *window)
5289 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5290 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5291 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5295 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5298 for (j = 0; j < lim; j++)
5300 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5304 return 0; /* suppress compiler warning */
5308 save_window_save (Lisp_Object window, struct window_config *config, int i)
5312 for (; !NILP (window); window = w->next)
5314 struct saved_window *p = SAVED_WINDOW_N (config, i);
5316 w = XWINDOW (window);
5319 p->buffer = w->buffer;
5320 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5321 WINDOW_TOP (p) = WINDOW_TOP (w);
5322 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5323 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5324 p->hscroll = w->hscroll;
5325 p->modeline_hscroll = w->modeline_hscroll;
5327 #define WINDOW_SLOT(slot, compare) p->slot = w->slot;
5328 #include "winslots.h"
5330 if (!NILP (w->buffer))
5332 /* Save w's value of point in the window configuration.
5333 If w is the selected window, then get the value of point
5334 from the buffer; pointm is garbage in the selected window. */
5335 if (EQ (window, Fselected_window (Qnil)))
5337 p->pointm = noseeum_make_marker ();
5338 Fset_marker (p->pointm,
5339 make_int (BUF_PT (XBUFFER (w->buffer))),
5343 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5345 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5346 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5347 p->start_at_line_beg = w->start_at_line_beg;
5349 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5357 p->start_at_line_beg = 0;
5360 if (NILP (w->parent))
5361 p->parent_index = -1;
5363 p->parent_index = saved_window_index (w->parent, config, i);
5367 p->prev_index = saved_window_index (w->prev, config, i);
5368 if (!NILP (w->vchild))
5369 i = save_window_save (w->vchild, config, i);
5370 if (!NILP (w->hchild))
5371 i = save_window_save (w->hchild, config, i);
5378 /* Added to doc string:
5380 This also records the currently selected frame, and FRAME's focus
5381 redirection (see `redirect-frame-focus').
5386 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5387 Return an object representing the current window configuration of FRAME.
5388 If FRAME is nil or omitted, use the selected frame.
5389 This describes the number of windows, their sizes and current buffers,
5390 and for each displayed buffer, where display starts, and the positions of
5391 point and mark. An exception is made for point in the current buffer:
5392 its value is -not- saved.
5397 struct frame *f = decode_frame (frame);
5398 struct window_config *config;
5399 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5401 int real_font_height;
5403 if (n_windows <= countof (Vwindow_configuration_free_list))
5404 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5405 (Vwindow_configuration_free_list
5408 /* More than ten windows; just allocate directly */
5409 config = (struct window_config *)
5410 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5411 &lrecord_window_configuration);
5412 XSETWINDOW_CONFIGURATION (result, config);
5414 config->frame_width = FRAME_WIDTH (f);
5415 config->frame_height = FRAME_HEIGHT (f); */
5416 config->current_window = FRAME_SELECTED_WINDOW (f);
5417 XSETBUFFER (config->current_buffer, current_buffer);
5418 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5419 config->root_window = FRAME_ROOT_WINDOW (f);
5420 config->min_height = window_min_height;
5421 config->min_width = window_min_width;
5422 config->saved_windows_count = n_windows;
5423 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5425 /* save the minibuffer height using the heuristics from
5426 change_frame_size_1 */
5428 XSETFRAME (frame, f); /* frame could have been nil ! */
5429 default_face_height_and_width (frame, &real_font_height, 0);
5430 assert(real_font_height > 0);
5432 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5433 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5436 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5437 - (minibuf_height / real_font_height ) : /* lines */
5438 minibuf_height; /* pixels */
5444 save_window_excursion_unwind (Lisp_Object window_config)
5446 Lisp_Object val = Fset_window_configuration (window_config);
5447 free_window_configuration (window_config);
5451 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5452 Execute body, preserving window sizes and contents.
5453 Restores which buffer appears in which window, where display starts,
5454 as well as the current buffer.
5455 Does not restore the value of point in current buffer.
5459 /* This function can GC */
5461 int speccount = specpdl_depth ();
5463 record_unwind_protect (save_window_excursion_unwind,
5464 Fcurrent_window_configuration (Qnil));
5465 val = Fprogn (args);
5466 return unbind_to (speccount, val);
5471 /* This is short and simple in elisp, but... it was written to debug
5472 problems purely on the C side. That is where we need to call it so
5475 debug_print_window (Lisp_Object window, int level)
5478 Lisp_Object child = Fwindow_first_vchild (window);
5481 child = Fwindow_first_hchild (window);
5483 for (i = level; i > 0; i--)
5484 putc ('\t', stderr);
5486 fputs ("#<window", stderr);
5488 Lisp_Object buffer = XWINDOW (window)->buffer;
5489 if (!NILP (buffer) && BUFFERP (buffer))
5490 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5492 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5494 while (!NILP (child))
5496 debug_print_window (child, level + 1);
5497 child = Fwindow_next_child (child);
5501 void debug_print_windows (struct frame *f);
5503 debug_print_windows (struct frame *f)
5505 debug_print_window (f->root_window, 0);
5506 putc ('\n', stderr);
5508 #endif /* DEBUG_XEMACS */
5511 /************************************************************************/
5512 /* initialization */
5513 /************************************************************************/
5516 syms_of_window (void)
5518 defsymbol (&Qwindowp, "windowp");
5519 defsymbol (&Qwindow_live_p, "window-live-p");
5520 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5521 defsymbol (&Qscroll_up, "scroll-up");
5522 defsymbol (&Qscroll_down, "scroll-down");
5523 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5524 defsymbol (&Qdisplay_buffer, "display-buffer");
5526 #ifdef MEMORY_USAGE_STATS
5527 defsymbol (&Qface_cache, "face-cache");
5528 defsymbol (&Qglyph_cache, "glyph-cache");
5529 defsymbol (&Qline_start_cache, "line-start-cache");
5530 #ifdef HAVE_SCROLLBARS
5531 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5533 defsymbol (&Qother_redisplay, "other-redisplay");
5534 /* Qother in general.c */
5537 DEFSUBR (Fselected_window);
5538 DEFSUBR (Fminibuffer_window);
5539 DEFSUBR (Fwindow_minibuffer_p);
5541 DEFSUBR (Fwindow_live_p);
5542 DEFSUBR (Fwindow_first_hchild);
5543 DEFSUBR (Fwindow_first_vchild);
5544 DEFSUBR (Fwindow_next_child);
5545 DEFSUBR (Fwindow_previous_child);
5546 DEFSUBR (Fwindow_parent);
5547 DEFSUBR (Fwindow_lowest_p);
5548 DEFSUBR (Fwindow_highest_p);
5549 DEFSUBR (Fwindow_leftmost_p);
5550 DEFSUBR (Fwindow_rightmost_p);
5551 DEFSUBR (Fpos_visible_in_window_p);
5552 DEFSUBR (Fwindow_buffer);
5553 DEFSUBR (Fwindow_frame);
5554 DEFSUBR (Fwindow_height);
5555 DEFSUBR (Fwindow_displayed_height);
5556 DEFSUBR (Fwindow_width);
5557 DEFSUBR (Fwindow_pixel_height);
5558 DEFSUBR (Fwindow_pixel_width);
5559 DEFSUBR (Fwindow_text_area_pixel_height);
5560 DEFSUBR (Fwindow_displayed_text_pixel_height);
5561 DEFSUBR (Fwindow_text_area_pixel_width);
5562 DEFSUBR (Fwindow_hscroll);
5563 #ifdef MODELINE_IS_SCROLLABLE
5564 DEFSUBR (Fmodeline_hscroll);
5565 DEFSUBR (Fset_modeline_hscroll);
5566 #endif /* MODELINE_IS_SCROLLABLE */
5567 #if 0 /* bogus FSF crock */
5568 DEFSUBR (Fwindow_redisplay_end_trigger);
5569 DEFSUBR (Fset_window_redisplay_end_trigger);
5571 DEFSUBR (Fset_window_hscroll);
5572 DEFSUBR (Fwindow_pixel_edges);
5573 DEFSUBR (Fwindow_text_area_pixel_edges);
5574 DEFSUBR (Fwindow_point);
5575 DEFSUBR (Fwindow_start);
5576 DEFSUBR (Fwindow_end);
5577 DEFSUBR (Fset_window_point);
5578 DEFSUBR (Fset_window_start);
5579 DEFSUBR (Fwindow_dedicated_p);
5580 DEFSUBR (Fset_window_dedicated_p);
5581 DEFSUBR (Fnext_window);
5582 DEFSUBR (Fprevious_window);
5583 DEFSUBR (Fnext_vertical_window);
5584 DEFSUBR (Fother_window);
5585 DEFSUBR (Fget_lru_window);
5586 DEFSUBR (Fget_largest_window);
5587 DEFSUBR (Fget_buffer_window);
5588 DEFSUBR (Fwindow_left_margin_pixel_width);
5589 DEFSUBR (Fwindow_right_margin_pixel_width);
5590 DEFSUBR (Fdelete_other_windows);
5591 DEFSUBR (Fdelete_windows_on);
5592 DEFSUBR (Freplace_buffer_in_windows);
5593 DEFSUBR (Fdelete_window);
5594 DEFSUBR (Fset_window_buffer);
5595 DEFSUBR (Fselect_window);
5596 DEFSUBR (Fsplit_window);
5597 DEFSUBR (Fenlarge_window);
5598 DEFSUBR (Fenlarge_window_pixels);
5599 DEFSUBR (Fshrink_window);
5600 DEFSUBR (Fshrink_window_pixels);
5601 DEFSUBR (Fscroll_up);
5602 DEFSUBR (Fscroll_down);
5603 DEFSUBR (Fscroll_left);
5604 DEFSUBR (Fscroll_right);
5605 DEFSUBR (Fother_window_for_scrolling);
5606 DEFSUBR (Fscroll_other_window);
5607 DEFSUBR (Fcenter_to_window_line);
5608 DEFSUBR (Fmove_to_window_line);
5609 #ifdef MEMORY_USAGE_STATS
5610 DEFSUBR (Fwindow_memory_usage);
5612 DEFSUBR (Fwindow_configuration_p);
5613 DEFSUBR (Fset_window_configuration);
5614 DEFSUBR (Fcurrent_window_configuration);
5615 DEFSUBR (Fsave_window_excursion);
5619 vars_of_window (void)
5621 /* Make sure all windows get marked */
5622 minibuf_window = Qnil;
5623 staticpro (&minibuf_window);
5625 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5626 *Non-nil means to scroll if point lands on a line which is clipped.
5628 scroll_on_clipped_lines = 1;
5630 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5631 See `temp-buffer-show-function'.
5633 Vtemp_buffer_show_hook = Qnil;
5635 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5636 Non-nil means call as function to display a help buffer.
5637 The function is called with one argument, the buffer to be displayed.
5638 Used by `with-output-to-temp-buffer'.
5639 If this function is used, then it must do the entire job of showing
5640 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5642 Vtemp_buffer_show_function = Qnil;
5644 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5645 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5647 Vminibuffer_scroll_window = Qnil;
5649 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5650 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5652 Vother_window_scroll_buffer = Qnil;
5654 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5655 *Number of lines of continuity when scrolling by screenfuls.
5657 next_screen_context_lines = 2;
5659 DEFVAR_INT ("window-min-height", &window_min_height /*
5660 *Delete any window less than this tall (including its modeline).
5662 window_min_height = 4;
5664 DEFVAR_INT ("window-min-width", &window_min_width /*
5665 *Delete any window less than this wide.
5667 window_min_width = 10;
5672 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5674 Vwindow_configuration_free_list[i] =
5675 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5676 &lrecord_window_configuration);
5677 staticpro (&Vwindow_configuration_free_list[i]);
5683 specifier_vars_of_window (void)
5685 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5686 *How thick to draw 3D shadows around modelines.
5687 If this is set to 0, modelines will be the traditional 2D. Sizes above
5688 10 will be accepted but the maximum thickness that will be drawn is 10.
5689 This is a specifier; use `set-specifier' to change it.
5691 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5692 /* The initial value for modeline-shadow-thickness is 2, but if the
5693 user removes all specifications we provide a fallback value of 0,
5694 which is probably what was expected. */
5695 set_specifier_fallback (Vmodeline_shadow_thickness,
5696 list1 (Fcons (Qnil, Qzero)));
5697 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5699 set_specifier_caching (Vmodeline_shadow_thickness,
5700 slot_offset (struct window,
5701 modeline_shadow_thickness),
5702 modeline_shadow_thickness_changed,
5705 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5706 *Whether the modeline should be displayed.
5707 This is a specifier; use `set-specifier' to change it.
5709 Vhas_modeline_p = Fmake_specifier (Qboolean);
5710 set_specifier_fallback (Vhas_modeline_p,
5711 list1 (Fcons (Qnil, Qt)));
5712 set_specifier_caching (Vhas_modeline_p,
5713 slot_offset (struct window,
5715 /* #### It's strange that we need a special
5716 flag to indicate that the shadow-thickness
5717 has changed, but not one to indicate that
5718 the modeline has been turned off or on. */
5719 some_window_value_changed,
5722 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5723 &Vvertical_divider_always_visible_p /*
5724 *Should XEmacs always display vertical dividers between windows.
5726 When this is non-nil, vertical dividers are always shown, and are
5727 draggable. When it is nil, vertical dividers are shown only when
5728 there are no scrollbars in between windows, and are not draggable.
5730 This is a specifier; use `set-specifier' to change it.
5732 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5733 set_specifier_fallback (Vvertical_divider_always_visible_p,
5734 list1 (Fcons (Qnil, Qt)));
5735 set_specifier_caching (Vvertical_divider_always_visible_p,
5736 slot_offset (struct window,
5737 vertical_divider_always_visible_p),
5738 vertical_divider_changed_in_window,
5741 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5742 *How thick to draw 3D shadows around vertical dividers.
5743 This is a specifier; use `set-specifier' to change it.
5745 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5746 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5747 list1 (Fcons (Qnil, Qzero)));
5748 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5750 set_specifier_caching (Vvertical_divider_shadow_thickness,
5751 slot_offset (struct window,
5752 vertical_divider_shadow_thickness),
5753 vertical_divider_changed_in_window,
5755 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5756 *The width of the vertical dividers, not including shadows.
5758 For TTY windows, divider line is always one character wide. When
5759 instance of this specifier is zero in a TTY window, no divider is
5760 drawn at all between windows. When non-zero, a one character wide
5761 divider is displayed.
5763 This is a specifier; use `set-specifier' to change it.
5766 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5768 Lisp_Object fb = Qnil;
5770 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
5772 #ifdef HAVE_X_WINDOWS
5773 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5775 #ifdef HAVE_MS_WINDOWS
5776 /* #### This should be made magic and made to obey system settings */
5777 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5779 set_specifier_fallback (Vvertical_divider_line_width, fb);
5781 set_specifier_caching (Vvertical_divider_line_width,
5782 slot_offset (struct window,
5783 vertical_divider_line_width),
5784 vertical_divider_changed_in_window,
5787 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5788 *How much space to leave around the vertical dividers.
5790 In TTY windows, spacing is always zero, and the value of this
5791 specifier is ignored.
5793 This is a specifier; use `set-specifier' to change it.
5795 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5797 Lisp_Object fb = Qnil;
5799 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5801 #ifdef HAVE_X_WINDOWS
5802 /* #### 3D dividers look great on MS Windows with spacing = 0.
5803 Should not the same value be the fallback under X? - kkm */
5804 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
5806 #ifdef HAVE_MS_WINDOWS
5807 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
5809 set_specifier_fallback (Vvertical_divider_spacing, fb);
5811 set_specifier_caching (Vvertical_divider_spacing,
5812 slot_offset (struct window,
5813 vertical_divider_spacing),
5814 vertical_divider_changed_in_window,