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 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 (Lisp_Object window, int delta,
68 Lisp_Object horizontalp, int inpixels);
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 edge of divider border and window edge */
86 Lisp_Object Vvertical_divider_spacing;
88 /* How much to scroll by per-line. */
89 Lisp_Object Vwindow_pixel_scroll_increment;
91 /* Scroll if point lands on the bottom line and that line is partially
93 int scroll_on_clipped_lines;
95 /* The minibuffer window of the selected frame.
96 Note that you cannot test for minibufferness of an arbitrary window
97 by comparing against this; but you can test for minibufferness of
98 the selected window. */
99 Lisp_Object minibuf_window;
101 /* Non-nil means it is the window for C-M-v to scroll
102 when the minibuffer is selected. */
103 Lisp_Object Vminibuffer_scroll_window;
105 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
106 Lisp_Object Vother_window_scroll_buffer;
108 /* Non-nil means it's the function to call to display temp buffers. */
109 Lisp_Object Vtemp_buffer_show_function;
111 Lisp_Object Vtemp_buffer_show_hook;
113 /* If a window gets smaller than either of these, it is removed. */
114 int window_min_height;
115 int window_min_width;
117 /* Hook run at end of temp_output_buffer_show. */
118 Lisp_Object Qtemp_buffer_show_hook;
120 /* Number of lines of continuity in scrolling by screenfuls. */
121 int next_screen_context_lines;
123 /* List of freed window configurations with 1 - 10 windows. */
124 static Lisp_Object Vwindow_configuration_free_list[10];
126 #define SET_LAST_MODIFIED(w, cache_too) \
128 (w)->last_modified[CURRENT_DISP] = Qzero; \
129 (w)->last_modified[DESIRED_DISP] = Qzero; \
130 (w)->last_modified[CMOTION_DISP] = Qzero; \
132 (w)->line_cache_last_updated = Qzero; \
135 #define SET_LAST_FACECHANGE(w) \
137 (w)->last_facechange[CURRENT_DISP] = Qzero; \
138 (w)->last_facechange[DESIRED_DISP] = Qzero; \
139 (w)->last_facechange[CMOTION_DISP] = Qzero; \
143 #define MARK_DISP_VARIABLE(field) \
144 mark_object (window->field[CURRENT_DISP]); \
145 mark_object (window->field[DESIRED_DISP]); \
146 mark_object (window->field[CMOTION_DISP]);
149 mark_window (Lisp_Object obj)
151 struct window *window = XWINDOW (obj);
152 mark_object (window->frame);
153 mark_object (window->mini_p);
154 mark_object (window->next);
155 mark_object (window->prev);
156 mark_object (window->hchild);
157 mark_object (window->vchild);
158 mark_object (window->parent);
159 mark_object (window->buffer);
160 MARK_DISP_VARIABLE (start);
161 MARK_DISP_VARIABLE (pointm);
162 mark_object (window->sb_point); /* #### move to scrollbar.c? */
163 mark_object (window->use_time);
164 MARK_DISP_VARIABLE (last_modified);
165 MARK_DISP_VARIABLE (last_point);
166 MARK_DISP_VARIABLE (last_start);
167 MARK_DISP_VARIABLE (last_facechange);
168 mark_object (window->line_cache_last_updated);
169 mark_object (window->redisplay_end_trigger);
170 mark_object (window->subwindow_instance_cache);
172 mark_face_cachels (window->face_cachels);
173 mark_glyph_cachels (window->glyph_cachels);
175 #define WINDOW_SLOT(slot, compare) mark_object (window->slot)
176 #include "winslots.h"
182 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
187 error ("printing unreadable object #<window 0x%x>",
188 XWINDOW (obj)->header.uid);
190 write_c_string ("#<window", printcharfun);
191 if (!NILP (XWINDOW (obj)->buffer))
193 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
194 write_c_string (" on ", printcharfun);
195 print_internal (name, printcharfun, 1);
197 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
198 write_c_string (buf, printcharfun);
202 finalize_window (void *header, int for_disksave)
204 struct window *w = (struct window *) header;
206 if (w->line_start_cache)
208 Dynarr_free (w->line_start_cache);
209 w->line_start_cache = 0;
216 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
218 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
219 if (cachel->merged_faces)
221 Dynarr_free (cachel->merged_faces);
222 cachel->merged_faces = 0;
225 Dynarr_free (w->face_cachels);
229 if (w->glyph_cachels)
231 Dynarr_free (w->glyph_cachels);
232 w->glyph_cachels = 0;
236 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
237 mark_window, print_window, finalize_window,
238 0, 0, 0, struct window);
241 #define INIT_DISP_VARIABLE(field, initialization) \
242 p->field[CURRENT_DISP] = initialization; \
243 p->field[DESIRED_DISP] = initialization; \
244 p->field[CMOTION_DISP] = initialization;
246 /* We have an implicit assertion that the first two elements (default
247 and modeline faces) are always present in the face_element_cache.
248 Normally redisplay ensures this. However, it is possible for a
249 window to get created and functions which reference these values
250 called before redisplay works with the window for the first time.
251 All callers of allocate_window should therefore call
252 reset_face_cachels on the created window. We can't do it
253 here because the window must have its frame pointer set or
254 reset_face_cachels will fail. */
256 allocate_window (void)
259 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
273 INIT_DISP_VARIABLE (start, Fmake_marker ());
274 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
275 p->sb_point = Fmake_marker ();
277 INIT_DISP_VARIABLE (last_modified, Qzero);
278 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
279 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
280 INIT_DISP_VARIABLE (last_facechange, Qzero);
281 p->face_cachels = Dynarr_new (face_cachel);
282 p->glyph_cachels = Dynarr_new (glyph_cachel);
283 p->line_start_cache = Dynarr_new (line_start_cache);
284 p->subwindow_instance_cache = make_lisp_hash_table (30,
285 HASH_TABLE_KEY_VALUE_WEAK,
287 p->line_cache_last_updated = Qzero;
288 INIT_DISP_VARIABLE (last_point_x, 0);
289 INIT_DISP_VARIABLE (last_point_y, 0);
290 INIT_DISP_VARIABLE (window_end_pos, 0);
291 p->redisplay_end_trigger = Qnil;
293 p->gutter_extent_modiff[0] = 0;
294 p->gutter_extent_modiff[1] = 0;
295 p->gutter_extent_modiff[2] = 0;
296 p->gutter_extent_modiff[3] = 0;
298 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
299 #include "winslots.h"
301 p->windows_changed = 1;
302 p->shadow_thickness_changed = 1;
306 #undef INIT_DISP_VARIABLE
309 * The redisplay structures used to be stored with each window. While
310 * they are logically something associated with frames they can't be
311 * stored there with a redisplay which handles variable height lines.
312 * Lines in horizontally split windows might not line up. So they get
313 * stored with the windows.
315 * The problem with this is window configurations. When restoring a
316 * window configuration it now becomes problematic to do an
317 * incremental redisplay. The solution is to store the redisplay
318 * structures with the frame as they should be but laid out in the
319 * same manner as the window structure. Thus is born the window
322 * It also becomes a convenient place to stick scrollbar instances
323 * since they extrapolate out to having the same problem described for
324 * the display structures.
327 /* Create a new window mirror structure and associated redisplay
329 static struct window_mirror *
330 new_window_mirror (struct frame *f)
332 struct window_mirror *t = xnew_and_zero (struct window_mirror);
336 t->current_display_lines = Dynarr_new (display_line);
337 t->desired_display_lines = Dynarr_new (display_line);
340 #ifdef HAVE_SCROLLBARS
341 t->scrollbar_vertical_instance = NULL;
342 t->scrollbar_horizontal_instance = NULL;
348 /* Synchronize the mirror structure with a given window structure.
349 This is normally called from update_frame_window_mirror with a
350 starting window of f->root_window. */
351 static struct window_mirror *
352 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
358 free_window_mirror (mir);
365 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
367 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
368 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
369 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
372 * If the redisplay structs are not empty and the mirror has
373 * children, then this mirror structure was formerly being used for
374 * display but is no longer. Reset its current display structs so
375 * that redisplay doesn't accidentally think they are accurate if it
376 * is later used for display purposes once again. Also, mark the
377 * scrollbar instance as not active.
379 if (mir->vchild || mir->hchild)
381 /* The redisplay structures are big. Leaving them around in
382 non-leaf windows can add up to a lot of wasted space. So
384 free_display_structs (mir);
385 mir->current_display_lines = Dynarr_new (display_line);
386 mir->desired_display_lines = Dynarr_new (display_line);
388 #ifdef HAVE_SCROLLBARS
389 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
397 /* Given a window mirror, determine which real window it contains the
398 redisplay structures for. */
400 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
401 struct window_mirror *mir)
403 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
407 if (!NILP (XWINDOW (win)->vchild))
410 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
414 if (!NILP (XWINDOW (win)->hchild))
417 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
426 /* Given a real window, find the mirror structure which contains its
427 redisplay structures. */
428 static struct window_mirror *
429 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
432 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
434 if (w == XWINDOW (win))
437 if (!NILP (XWINDOW (win)->vchild))
439 struct window_mirror *retval =
440 find_window_mirror_internal (XWINDOW (win)->vchild,
442 if (retval) return retval;
445 if (!NILP (XWINDOW (win)->hchild))
447 struct window_mirror *retval =
448 find_window_mirror_internal (XWINDOW (win)->hchild,
450 if (retval) return retval;
457 /* Update the mirror structure for the given frame. */
459 update_frame_window_mirror (struct frame *f)
461 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
465 /* Free a given mirror structure along with all of its children as
466 well as their associated display structures. */
468 free_window_mirror (struct window_mirror *mir)
472 struct window_mirror *prev = mir;
473 if (mir->hchild) free_window_mirror (mir->hchild);
474 if (mir->vchild) free_window_mirror (mir->vchild);
475 #ifdef HAVE_SCROLLBARS
476 release_window_mirror_scrollbars (mir);
478 free_display_structs (mir);
484 /* Given a mirror structure, return the window it mirrors. Calls
485 real_window_internal to do most of the work. */
487 real_window (struct window_mirror *mir, int no_abort)
489 Lisp_Object retval = real_window_internal (mir->frame->root_window,
490 mir->frame->root_mirror, mir);
491 if (NILP (retval) && !no_abort)
497 /* Given a real window, return its mirror structure. Calls
498 find_window_mirror_internal to do all of the work. */
499 struct window_mirror *
500 find_window_mirror (struct window *w)
502 struct frame *f = XFRAME (w->frame);
504 update_frame_window_mirror (f);
505 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
508 /*****************************************************************************
509 find_window_by_pixel_pos
511 Given a pixel position relative to a frame, find the window at that
513 ****************************************************************************/
515 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
520 for (; !NILP (win); win = XWINDOW (win)->next)
524 if (!NILP (XWINDOW (win)->vchild))
526 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
529 if (!NILP (XWINDOW (win)->hchild))
531 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
535 if (pix_x >= WINDOW_LEFT (w)
536 && pix_x <= WINDOW_RIGHT (w)
537 && pix_y >= WINDOW_TOP (w)
538 && pix_y <= WINDOW_BOTTOM (w))
544 /* Return a pointer to the display structures for the given window. */
545 display_line_dynarr *
546 window_display_lines (struct window *w, int which)
548 struct window_mirror *t;
550 if (XFRAME (w->frame)->mirror_dirty)
551 update_frame_window_mirror (XFRAME (w->frame));
552 t = find_window_mirror (w);
556 if (which == CURRENT_DISP)
557 return t->current_display_lines;
558 else if (which == DESIRED_DISP)
559 return t->desired_display_lines;
560 else if (which == CMOTION_DISP)
561 /* The CMOTION_DISP display lines are global. */
562 return cmotion_display_lines;
566 return 0; /* shut up compiler */
570 window_display_buffer (struct window *w)
572 struct window_mirror *t;
574 if (XFRAME (w->frame)->mirror_dirty)
575 update_frame_window_mirror (XFRAME (w->frame));
576 t = find_window_mirror (w);
584 set_window_display_buffer (struct window *w, struct buffer *b)
586 struct window_mirror *t;
588 if (XFRAME (w->frame)->mirror_dirty)
589 update_frame_window_mirror (XFRAME (w->frame));
590 t = find_window_mirror (w);
598 /* Determining a window's position based solely on its pixel
599 positioning doesn't work. Instead, we do it the intelligent way,
600 by checking its positioning in the window hierarchy. */
602 window_is_leftmost (struct window *w)
604 Lisp_Object parent, current_ancestor, window;
606 XSETWINDOW (window, w);
608 parent = XWINDOW (window)->parent;
609 current_ancestor = window;
611 while (!NILP (parent))
613 if (!NILP (XWINDOW (parent)->hchild) &&
614 !EQ (XWINDOW (parent)->hchild, current_ancestor))
617 current_ancestor = parent;
618 parent = XWINDOW (parent)->parent;
625 window_is_rightmost (struct window *w)
627 Lisp_Object parent, current_ancestor, window;
629 XSETWINDOW (window, w);
631 parent = XWINDOW (window)->parent;
632 current_ancestor = window;
634 while (!NILP (parent))
636 if (!NILP (XWINDOW (parent)->hchild)
637 && !NILP (XWINDOW (current_ancestor)->next))
640 current_ancestor = parent;
641 parent = XWINDOW (parent)->parent;
648 window_full_width_p (struct window *w)
650 return window_is_leftmost (w) && window_is_rightmost (w);
654 window_is_highest (struct window *w)
656 Lisp_Object parent, current_ancestor, window;
658 XSETWINDOW (window, w);
660 parent = XWINDOW (window)->parent;
661 current_ancestor = window;
663 while (!NILP (parent))
665 if (!NILP (XWINDOW (parent)->vchild) &&
666 !EQ (XWINDOW (parent)->vchild, current_ancestor))
669 current_ancestor = parent;
670 parent = XWINDOW (parent)->parent;
673 /* This is really to catch the minibuffer but we make it generic in
674 case we ever change things around to let the minibuffer be on top. */
675 if (NILP (XWINDOW (current_ancestor)->prev))
682 window_is_lowest (struct window *w)
684 Lisp_Object parent, current_ancestor, window;
686 XSETWINDOW (window, w);
688 parent = XWINDOW (window)->parent;
689 current_ancestor = window;
691 while (!NILP (parent))
693 if (!NILP (XWINDOW (parent)->vchild)
694 && !NILP (XWINDOW (current_ancestor)->next))
697 current_ancestor = parent;
698 parent = XWINDOW (parent)->parent;
704 #if 0 /* not currently used */
707 window_full_height_p (struct window *w)
709 return window_is_highest (w) && window_is_lowest (w);
715 window_truncation_on (struct window *w)
717 /* Minibuffer windows are never truncated.
718 #### is this the right way ? */
719 if (MINI_WINDOW_P (w))
722 /* Horizontally scrolled windows are truncated. */
726 /* If truncate_partial_width_windows is true and the window is not
727 the full width of the frame it is truncated. */
728 if (truncate_partial_width_windows
729 && !(window_is_leftmost (w) && window_is_rightmost (w)))
732 /* If the window's buffer's value of truncate_lines is non-nil, then
733 the window is truncated. */
734 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
740 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
741 Returns non-nil if text in the window is truncated.
745 struct window *w = decode_window (window);
747 return window_truncation_on (w) ? Qt : Qnil;
752 have_undivided_common_edge (struct window *w_right, void *closure)
754 struct window *w_left = (struct window *) closure;
755 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
756 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
757 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
758 #ifdef HAVE_SCROLLBARS
759 && (NILP (w_right->scrollbar_on_left_p)
760 || NILP (w_right->vertical_scrollbar_visible_p)
761 || ZEROP (w_right->scrollbar_width))
767 window_needs_vertical_divider_1 (struct window *w)
769 /* Never if we're on the right */
770 if (window_is_rightmost (w))
773 /* Always if draggable */
774 if (!NILP (w->vertical_divider_always_visible_p))
777 #ifdef HAVE_SCROLLBARS
778 /* Our right scrollbar is enough to separate us at the right */
779 if (NILP (w->scrollbar_on_left_p)
780 && !NILP (w->vertical_scrollbar_visible_p)
781 && !ZEROP (w->scrollbar_width))
785 /* Ok. to determine whether we need a divider on the left, we must
786 check that our right neighbor windows have scrollbars on their
787 left sides. We must check all such windows which have common
788 left edge with our window's right edge. */
789 return map_windows (XFRAME (WINDOW_FRAME (w)),
790 have_undivided_common_edge, (void*)w);
794 window_needs_vertical_divider (struct window *w)
796 if (!w->need_vertical_divider_valid_p)
798 w->need_vertical_divider_p =
799 window_needs_vertical_divider_1 (w);
800 w->need_vertical_divider_valid_p = 1;
802 return w->need_vertical_divider_p;
805 /* Called from invalidate_vertical_divider_cache_in_frame */
807 invalidate_vertical_divider_cache_in_window (struct window *w,
810 w->need_vertical_divider_valid_p = 0;
814 /* Calculate width of vertical divider, including its shadows
815 and spacing. The returned value is effectively the distance
816 between adjacent window edges. This function does not check
817 whether a window needs a vertical divider, so the returned
818 value is a "theoretical" one */
820 window_divider_width (struct window *w)
822 /* the shadow thickness can be negative. This means that the divider
823 will have a depressed look */
825 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
827 XINT (w->vertical_divider_line_width)
828 + 2 * XINT (w->vertical_divider_spacing)
829 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
831 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
835 window_scrollbar_width (struct window *w)
837 #ifdef HAVE_SCROLLBARS
838 if (!WINDOW_WIN_P (w)
841 || NILP (w->vertical_scrollbar_visible_p))
842 /* #### when does NILP (w->buffer) happen? */
845 return XINT (w->scrollbar_width);
848 #endif /* HAVE_SCROLLBARS */
851 /* Horizontal scrollbars are only active on windows with truncation
854 window_scrollbar_height (struct window *w)
856 #ifdef HAVE_SCROLLBARS
857 if (!WINDOW_WIN_P (w)
860 || NILP (w->horizontal_scrollbar_visible_p)
861 || !window_truncation_on (w))
864 return XINT (w->scrollbar_height);
867 #endif /* HAVE_SCROLLBARS */
871 window_modeline_height (struct window *w)
873 struct frame *f = XFRAME (w->frame);
876 if (MINI_WINDOW_P (w) || NILP (w->buffer))
880 else if (!WINDOW_HAS_MODELINE_P (w))
882 if (window_scrollbar_height (w))
886 modeline_height = FRAMEMETH (f, divider_height, ());
888 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
889 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
898 display_line_dynarr *dla;
900 /* We don't force a regeneration of the modeline here.
901 Instead it is now a precondition that any function calling
902 this should make sure that one of these structures is
903 up-to-date. In practice this only affects two internal
904 redisplay functions, regenerate_window and
905 regenerate_window_point_center. */
906 /* We check DESIRED_DISP because if it is valid it is more
907 up-to-date than CURRENT_DISP. For calls to this outside
908 of redisplay it doesn't matter which structure we check
909 since there is a redisplay condition that these
910 structures be identical outside of redisplay. */
911 dla = window_display_lines (w, DESIRED_DISP);
912 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
913 modeline_height = (Dynarr_atp (dla, 0)->ascent +
914 Dynarr_atp (dla, 0)->descent);
917 dla = window_display_lines (w, CURRENT_DISP);
918 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
919 modeline_height = (Dynarr_atp (dla, 0)->ascent +
920 Dynarr_atp (dla, 0)->descent);
922 /* This should be an abort except I'm not yet 100%
923 confident that it won't ever get hit (though I
924 haven't been able to trigger it). It is extremely
925 unlikely to cause any noticeable problem and even if
926 it does it will be a minor display glitch. */
927 /* #### Bullshit alert. It does get hit and it causes
928 noticeable glitches. real_current_modeline_height
929 is a kludge to fix this for 19.14. */
930 modeline_height = real_current_modeline_height (w);
933 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
934 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
938 return modeline_height;
941 /*****************************************************************************
942 margin_width_internal
944 For a given window, return the width in pixels of the specified margin.
945 ****************************************************************************/
947 margin_width_internal (struct window *w, int left_margin)
950 int window_cwidth = window_char_width (w, 1);
955 /* We might be getting called on a non-leaf. */
956 if (NILP (w->buffer))
959 /* The minibuffer never has margins. */
960 if (MINI_WINDOW_P (w))
963 XSETWINDOW (window, w);
964 b = XBUFFER (w->buffer);
965 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
966 XINT (w->right_margin_width));
968 default_face_height_and_width (window, 0, &font_width);
970 /* The left margin takes precedence over the right margin so we
971 subtract its width from the space available for the right
974 window_cwidth -= XINT (w->left_margin_width);
976 /* The margin cannot be wider than the window is. We allow the
977 value to be bigger since it is possible for the user to enlarge
978 the window such that the left margin value would no longer be too
979 big, but we won't return a value that is larger. */
980 if (margin_cwidth > window_cwidth)
981 margin_cwidth = window_cwidth;
983 /* At the user level the margin is always specified in characters.
984 Internally however it is manipulated in terms of pixels. */
985 return margin_cwidth * font_width;
989 window_left_margin_width (struct window *w)
991 return margin_width_internal (w, 1);
995 window_right_margin_width (struct window *w)
997 return margin_width_internal (w, 0);
1000 /*****************************************************************************
1003 The gutters of a window are those areas in the boundary defined by
1004 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1005 do not contain text. Items which may be in the gutters include
1006 scrollbars, toolbars and modelines. The margin areas are not
1007 included. This is an exception made because redisplay special cases
1008 the handling of those areas in many places in such a way that
1009 including them in the gutter area would make life difficult.
1011 The size functions refer to height for the bottom and top gutters and
1012 width for the left and right gutters. The starting position
1013 functions refer to the Y coord for bottom and top gutters and the X
1014 coord for left and right gutters. All starting positions are
1015 relative to the frame, not the window.
1016 ****************************************************************************/
1019 window_top_window_gutter_height (struct window *w)
1021 if (!NILP (w->hchild) || !NILP (w->vchild))
1024 #ifdef HAVE_SCROLLBARS
1025 if (!NILP (w->scrollbar_on_top_p))
1026 return window_scrollbar_height (w);
1033 window_top_gutter_height (struct window *w)
1035 return window_top_window_gutter_height (w);
1039 window_bottom_window_gutter_height (struct window *w)
1043 if (!NILP (w->hchild) || !NILP (w->vchild))
1046 gutter = window_modeline_height (w);
1048 #ifdef HAVE_SCROLLBARS
1049 if (NILP (w->scrollbar_on_top_p))
1050 return window_scrollbar_height (w) + gutter;
1057 window_bottom_gutter_height (struct window *w)
1059 return window_bottom_window_gutter_height (w);
1063 window_left_window_gutter_width (struct window *w, int modeline)
1065 if (!NILP (w->hchild) || !NILP (w->vchild))
1068 #ifdef HAVE_SCROLLBARS
1069 if (!modeline && !NILP (w->scrollbar_on_left_p))
1070 return window_scrollbar_width (w);
1077 window_left_gutter_width (struct window *w, int modeline)
1079 return window_left_window_gutter_width (w, modeline);
1083 window_right_window_gutter_width (struct window *w, int modeline)
1087 if (!NILP (w->hchild) || !NILP (w->vchild))
1090 #ifdef HAVE_SCROLLBARS
1091 if (!modeline && NILP (w->scrollbar_on_left_p))
1092 gutter += window_scrollbar_width (w);
1095 if (window_needs_vertical_divider (w))
1096 gutter += window_divider_width (w);
1102 window_right_gutter_width (struct window *w, int modeline)
1104 return window_right_window_gutter_width (w, modeline);
1108 window_pixel_height (struct window* w)
1110 return WINDOW_HEIGHT (w);
1114 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1115 Return t if OBJECT is a window.
1119 return WINDOWP (object) ? Qt : Qnil;
1122 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1123 Return t if OBJECT is a window which is currently visible.
1127 return WINDOWP (object) && WINDOW_LIVE_P (XWINDOW (object))
1131 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1132 Return the window that the cursor now appears in and commands apply to.
1133 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1134 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1135 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1136 is a console, the selected frame on that console's selected device will
1137 be used. Otherwise, the selected frame is used.
1141 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1142 return Qnil; /* happens at startup */
1145 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1146 return FRAME_SELECTED_WINDOW (f);
1150 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1151 Return the last selected window that is not a minibuffer window.
1152 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1153 return the last non-minibuffer window used by that frame. If
1154 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1155 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1156 that console's selected device will be used. Otherwise, the selected
1161 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1162 return Qnil; /* happens at startup */
1165 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1166 return FRAME_LAST_NONMINIBUF_WINDOW (f);
1170 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1171 Return the window used now for minibuffers.
1172 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1173 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1174 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1175 is a console, the selected frame on that console's selected device will
1176 be used. Otherwise, the selected frame is used.
1180 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1183 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1184 Return non-nil if WINDOW is a minibuffer window.
1188 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1191 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1192 Return the first horizontal child of WINDOW, or nil.
1196 return decode_window (window)->hchild;
1199 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1200 Return the first vertical child of WINDOW, or nil.
1204 return decode_window (window)->vchild;
1207 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1208 Return the next window on the same level as WINDOW, or nil.
1212 return decode_window (window)->next;
1215 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1216 Return the previous window on the same level as WINDOW, or nil.
1220 return decode_window (window)->prev;
1223 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1224 Return the parent of WINDOW, or nil.
1228 return decode_window (window)->parent;
1231 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1232 Return non-nil if WINDOW is along the bottom of its frame.
1236 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1239 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1240 Return non-nil if WINDOW is along the top of its frame.
1244 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1247 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1248 Return non-nil if WINDOW is along the left edge of its frame.
1252 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1255 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1256 Return non-nil if WINDOW is along the right edge of its frame.
1260 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1263 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1264 Return t if position POS is currently on the frame in WINDOW.
1265 Returns nil if that position is scrolled vertically out of view.
1266 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1270 struct window *w = decode_window (window);
1271 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1273 struct buffer *buf = XBUFFER (w->buffer);
1276 posint = BUF_PT (buf);
1279 CHECK_INT_COERCE_MARKER (pos);
1280 posint = XINT (pos);
1283 if (posint < top || posint > BUF_ZV (buf))
1286 /* w->start can be out of range. If it is, do something reasonable. */
1287 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1290 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1295 decode_window (Lisp_Object window)
1298 return XWINDOW (Fselected_window (Qnil));
1300 CHECK_LIVE_WINDOW (window);
1301 return XWINDOW (window);
1304 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1305 Return the buffer that WINDOW is displaying.
1309 return decode_window (window)->buffer;
1312 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1313 Return the frame that window WINDOW is on.
1317 return decode_window (window)->frame;
1320 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1321 Return the number of default lines in WINDOW.
1322 This actually works by dividing the window's pixel height (including
1323 the modeline and horizontal scrollbar, if any) by the height of the
1324 default font; therefore, the number of displayed lines will probably
1326 Use `window-height' to get consistent results in geometry calculations.
1327 Use `window-displayed-height' to get the actual number of lines
1328 currently displayed in a window.
1330 The names are somewhat confusing; here's a table to help out:
1333 -------------------------------------------------------------------------
1335 (rows/columns) window-width window-text-area-height
1336 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1339 (rows/columns) window-full-width window-height
1340 (pixels) window-pixel-width window-pixel-height
1343 (rows/columns) ---- window-displayed-height
1344 (pixels) ---- window-displayed-text-pixel-height
1348 return make_int (window_char_height (decode_window (window), 1));
1351 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1352 Return the number of lines currently displayed in WINDOW.
1353 This counts the actual number of lines displayed in WINDOW
1354 \(as opposed to `window-height'). The modeline and horizontal
1355 scrollbar do not count as lines. If there is some blank space
1356 between the end of the buffer and the end of the window, this
1357 function pretends that there are lines of text in the default
1362 return make_int (window_displayed_height (decode_window (window)));
1365 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1366 Return the height of WINDOW in pixels. Defaults to current window.
1367 This includes the window's modeline and horizontal scrollbar (if any).
1371 return make_int (window_pixel_height (decode_window (window)));
1374 DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1375 Return the number of default lines in the text area of WINDOW.
1376 This actually works by dividing the window's text area pixel height (i.e.
1377 excluding the modeline and horizontal scrollbar, if any) by the height of the
1378 default font; therefore, the number of displayed lines will probably
1380 See also `window-height' and `window-displayed-height'.
1384 return make_int (window_char_height (decode_window (window), 0));
1387 DEFUN ("window-text-area-pixel-height",
1388 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1389 Return the height in pixels of the text-displaying portion of WINDOW.
1390 Unlike `window-pixel-height', the space occupied by the modeline and
1391 horizontal scrollbar, if any, is not counted.
1395 struct window *w = decode_window (window);
1397 return make_int (WINDOW_TEXT_HEIGHT (w));
1400 DEFUN ("window-displayed-text-pixel-height",
1401 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1402 Return the height in pixels of the text displayed in WINDOW.
1403 Unlike `window-text-area-pixel-height', any blank space below the
1404 end of the buffer is not included. If optional argument NOCLIPPED
1405 is non-nil, do not include space occupied by clipped lines.
1407 (window, noclipped))
1410 Bufpos start, eobuf;
1412 int hlimit, height, prev_height = -1;
1416 line_start_cache_dynarr *cache;
1419 window = Fselected_window (Qnil);
1421 CHECK_LIVE_WINDOW (window);
1422 w = XWINDOW (window);
1424 start = marker_position (w->start[CURRENT_DISP]);
1425 hlimit = WINDOW_TEXT_HEIGHT (w);
1426 eobuf = BUF_ZV (XBUFFER (w->buffer));
1428 default_face_height_and_width (window, &defheight, NULL);
1430 /* guess lines needed in line start cache + a few extra */
1431 needed = (hlimit + defheight-1) / defheight + 3;
1434 elt = point_in_line_start_cache (w, start, needed);
1435 assert (elt >= 0); /* in the cache */
1437 cache = w->line_start_cache;
1438 nelt = Dynarr_length (cache);
1441 for (i = elt; i < nelt; i++) {
1442 line = Dynarr_atp (cache, i)->height;
1444 if (height + line > hlimit)
1445 return make_int (!NILP (noclipped) ? height : hlimit);
1449 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1450 return make_int (height);
1453 /* get here => need more cache lines. try again. */
1454 assert(height > prev_height); /* progress? */
1455 prev_height = height;
1457 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1460 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1463 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1464 Return the number of display columns in WINDOW.
1465 This is the width that is usable columns available for text in WINDOW,
1466 and does not include vertical scrollbars, dividers, or the like. See also
1467 `window-full-width' and `window-height'.
1471 return make_int (window_char_width (decode_window (window), 0));
1474 DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1475 Return the total number of columns in WINDOW.
1476 This is like `window-width' but includes vertical scrollbars, dividers,
1481 return make_int (window_char_width (decode_window (window), 1));
1484 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1485 Return the width of WINDOW in pixels. Defaults to current window.
1489 return make_int (decode_window (window)->pixel_width);
1492 DEFUN ("window-text-area-pixel-width",
1493 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1494 Return the width in pixels of the text-displaying portion of WINDOW.
1495 Unlike `window-pixel-width', the space occupied by the vertical
1496 scrollbar or divider, if any, is not counted.
1500 struct window *w = decode_window (window);
1502 return make_int (WINDOW_TEXT_WIDTH (w));
1505 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1506 Return the number of columns by which WINDOW is scrolled from left margin.
1510 return make_int (decode_window (window)->hscroll);
1513 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1514 Return the horizontal scrolling amount of WINDOW's modeline.
1515 If the window has no modeline, return nil.
1519 struct window *w = decode_window (window);
1521 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
1525 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1526 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1527 If NCOL is negative, it will silently be forced to 0.
1528 If the window has no modeline, return nil. Otherwise, return the actual
1533 struct window *w = decode_window (window);
1535 if (WINDOW_HAS_MODELINE_P (w))
1540 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
1541 if (ncols != w->modeline_hscroll)
1543 MARK_MODELINE_CHANGED;
1544 w->modeline_hscroll = ncols;
1546 return make_int ((int) ncols);
1552 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1553 Set number of columns WINDOW is scrolled from left margin to NCOL.
1554 NCOL should be zero or positive.
1562 ncols = XINT (ncol);
1563 if (ncols < 0) ncols = 0;
1564 w = decode_window (window);
1565 if (w->hscroll != ncols)
1566 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1571 #if 0 /* bogus FSF crock */
1573 xxDEFUN ("window-redisplay-end-trigger",
1574 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1575 Return WINDOW's redisplay end trigger value.
1576 See `set-window-redisplay-end-trigger' for more information.
1580 return decode_window (window)->redisplay_end_trigger;
1583 xxDEFUN ("set-window-redisplay-end-trigger",
1584 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1585 Set WINDOW's redisplay end trigger value to VALUE.
1586 VALUE should be a buffer position (typically a marker) or nil.
1587 If it is a buffer position, then if redisplay in WINDOW reaches a position
1588 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1589 with two arguments: WINDOW, and the end trigger value.
1590 Afterwards the end-trigger value is reset to nil.
1594 return (decode_window (window)->redisplay_end_trigger = value);
1599 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1600 Return a list of the pixel edge coordinates of WINDOW.
1601 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1602 all relative to 0, 0 at the top left corner of WINDOW's frame.
1603 The frame toolbars, menubars and gutters are considered to be outside
1604 of this area, while the scrollbars are considered to be inside.
1608 struct window *w = decode_window (window);
1609 struct frame *f = XFRAME (w->frame);
1612 w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
1614 w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
1616 return list4 (make_int (left),
1618 make_int (left + w->pixel_width),
1619 make_int (top + w->pixel_height));
1622 DEFUN ("window-text-area-pixel-edges",
1623 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1624 Return a list of the pixel edge coordinates of the text area of WINDOW.
1625 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1626 all relative to 0, 0 at the top left corner of the total area allocated
1627 to the window, which includes the scrollbars.
1631 struct window *w = decode_window (window);
1633 int left = window_left_gutter_width (w, /* modeline = */ 0);
1634 int top = window_top_gutter_height (w);
1635 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1636 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1638 return list4 (make_int (left),
1644 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1645 Return current value of point in WINDOW.
1646 For a non-selected window, this is the value point would have
1647 if that window were selected.
1649 Note that, when WINDOW is the selected window and its buffer
1650 is also currently selected, the value returned is the same as (point).
1651 It would be more strictly correct to return the `top-level' value
1652 of point, outside of any save-excursion forms.
1653 But that value is hard to find.
1657 struct window *w = decode_window (window);
1659 /* The special check for current buffer is necessary for this
1660 function to work as defined when called within an excursion. */
1661 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1662 && current_buffer == XBUFFER (w->buffer))
1663 return Fpoint (Qnil);
1664 return Fmarker_position (w->pointm[CURRENT_DISP]);
1667 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1668 Return position at which display currently starts in WINDOW.
1669 This is updated by redisplay or by calling `set-window-start'.
1673 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1676 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1677 Return position at which display currently ends in WINDOW.
1678 This is updated by redisplay, when it runs to completion.
1679 Simply changing the buffer text or setting `window-start' does not
1680 update this value. WINDOW defaults to the selected window.
1682 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1683 to be the same value as this function would return at the end of the
1684 next full redisplay assuming nothing else changes in the meantime.
1685 This function is potentially much slower with this flag set.
1687 (window, guarantee))
1689 struct window *w = decode_window (window);
1691 if (NILP (guarantee))
1696 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1700 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1701 return make_int (end_of_last_line (w, startp));
1705 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1706 Return pixel height of visible part of last window line if it is clipped.
1707 If the last line is not clipped, return nil.
1711 struct window *w = decode_window (window);
1712 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1713 int num_lines = Dynarr_length (dla);
1714 struct display_line *dl;
1716 /* No lines - no clipped lines */
1717 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
1720 dl = Dynarr_atp (dla, num_lines - 1);
1724 return make_int (dl->ascent + dl->descent - dl->clip);
1727 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1728 Make point value in WINDOW be at position POS in WINDOW's buffer.
1732 struct window *w = decode_window (window);
1734 CHECK_INT_COERCE_MARKER (pos);
1735 if (w == XWINDOW (Fselected_window (Qnil)))
1736 Fgoto_char (pos, Qnil);
1738 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1744 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1745 Make display in WINDOW start at position POS in WINDOW's buffer.
1746 Optional third arg NOFORCE non-nil inhibits next redisplay
1747 from overriding motion of point in order to display at this exact start.
1749 (window, pos, noforce))
1751 struct window *w = decode_window (window);
1753 CHECK_INT_COERCE_MARKER (pos);
1754 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1755 /* this is not right, but much easier than doing what is right. */
1756 /* w->start_at_line_beg = 0; */
1757 /* WTF is the above supposed to mean? GE */
1758 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1759 marker_position (w->start[CURRENT_DISP]));
1762 w->redo_modeline = 1;
1763 SET_LAST_MODIFIED (w, 0);
1764 SET_LAST_FACECHANGE (w);
1766 MARK_WINDOWS_CHANGED (w);
1771 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1772 Return WINDOW's dedicated object, usually t or nil.
1773 See also `set-window-dedicated-p'.
1777 return decode_window (window)->dedicated;
1780 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1781 Control whether WINDOW is dedicated to the buffer it displays.
1782 If it is dedicated, Emacs will not automatically change
1783 which buffer appears in it.
1784 The second argument is the new value for the dedication flag;
1789 struct window *w = decode_window (window);
1791 w->dedicated = NILP (arg) ? Qnil : Qt;
1793 return w->dedicated;
1796 /* FSFmacs has window-display-table here. We have display table as a
1800 /* Record info on buffer window w is displaying
1801 when it is about to cease to display that buffer. */
1803 unshow_buffer (struct window *w)
1805 Lisp_Object buf = w->buffer;
1807 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1810 /* FSF disables this check, so I'll do it too. I hope it won't
1811 break things. --ben */
1813 if (w == XWINDOW (Fselected_window (Qnil))
1814 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1815 /* Do this except when the selected window's buffer
1816 is being removed from some other window. */
1818 /* last_window_start records the start position that this buffer
1819 had in the last window to be disconnected from it.
1820 Now that this statement is unconditional,
1821 it is possible for the buffer to be displayed in the
1822 selected window, while last_window_start reflects another
1823 window which was recently showing the same buffer.
1824 Some people might say that might be a good thing. Let's see. */
1825 XBUFFER (buf)->last_window_start =
1826 marker_position (w->start[CURRENT_DISP]);
1828 /* Point in the selected window's buffer
1829 is actually stored in that buffer, and the window's pointm isn't used.
1830 So don't clobber point in that buffer. */
1831 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1833 struct buffer *b= XBUFFER (buf);
1834 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1835 marker_position (w->pointm[CURRENT_DISP]),
1840 /* Put REPLACEMENT into the window structure in place of OLD. */
1842 replace_window (Lisp_Object old, Lisp_Object replacement)
1845 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1847 /* If OLD is its frame's root_window, then replacement is the new
1848 root_window for that frame. */
1850 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1851 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1853 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1854 WINDOW_TOP (p) = WINDOW_TOP (o);
1855 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1856 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1858 p->next = tem = o->next;
1860 XWINDOW (tem)->prev = replacement;
1862 p->prev = tem = o->prev;
1864 XWINDOW (tem)->next = replacement;
1866 p->parent = tem = o->parent;
1869 if (EQ (XWINDOW (tem)->vchild, old))
1870 XWINDOW (tem)->vchild = replacement;
1871 if (EQ (XWINDOW (tem)->hchild, old))
1872 XWINDOW (tem)->hchild = replacement;
1875 /* #### Here, if replacement is a vertical combination
1876 and so is its new parent, we should make replacement's
1877 children be children of that parent instead. */
1879 ERROR_CHECK_SUBWINDOW_CACHE (p);
1883 window_unmap_subwindows (struct window* w)
1885 assert (!NILP (w->subwindow_instance_cache));
1886 elisp_maphash (unmap_subwindow_instance_cache_mapper,
1887 w->subwindow_instance_cache, (void*)1);
1890 /* we're deleting W; set the structure of W to indicate this. */
1893 mark_window_as_deleted (struct window *w)
1895 /* The window instance cache is going away now, so need to get the
1896 cachels reset by redisplay. */
1897 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
1899 /* The cache is going away. If we leave unmapping to
1900 reset_subwindow_cachels then we get in a situation where the
1901 domain (the window) has been deleted but we still need access to
1902 its attributes in order to unmap windows properly. Since the
1903 subwindows are going to get GC'd anyway as a result of the domain
1904 going away, it is safer to just unmap them all while we know the
1905 domain is still valid. */
1906 ERROR_CHECK_SUBWINDOW_CACHE (w);
1907 window_unmap_subwindows (w);
1910 (while t (split-window) (delete-window))
1911 we end up with a tree of deleted windows which are all connected
1912 through the `next' slot. This might not seem so bad, as they're
1913 deleted, and will presumably be GCed - but if even *one* of those
1914 windows is still being pointed to, by the user, or by a window
1915 configuration, then *all* of those windows stick around.
1917 Since the window-configuration code doesn't need any of the
1918 pointers to other windows (they are all recreated from the
1919 window-config data), we set them all to nil so that we
1920 are able to collect more actual garbage. */
1926 w->subwindow_instance_cache = Qnil;
1930 /* Free the extra data structures attached to windows immediately so
1931 they don't sit around consuming excess space. They will be
1932 reinitialized by the window-configuration code as necessary. */
1933 finalize_window ((void *) w, 0);
1936 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1937 Remove WINDOW from the display. Default is selected window.
1938 If window is the only one on its frame, the frame is deleted as well.
1939 Normally, you cannot delete the last non-minibuffer-only frame (you must
1940 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1941 second argument FORCE is non-nil, you can delete the last frame. (This
1942 will automatically call `save-buffers-kill-emacs'.)
1946 /* This function can GC if this is the only window in the frame */
1954 /* Note: this function is called by other C code on non-leaf
1957 /* Do the equivalent of decode_window() but don't error out on
1958 deleted window; it's OK to delete an already-deleted window. */
1960 window = Fselected_window (Qnil);
1962 CHECK_WINDOW (window);
1964 w = XWINDOW (window);
1966 /* It's okay to delete an already-deleted window. */
1967 if (! WINDOW_LIVE_P (w))
1970 frame = WINDOW_FRAME (w);
1972 d = XDEVICE (FRAME_DEVICE (f));
1974 if (TOP_LEVEL_WINDOW_P (w))
1976 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1977 /* this frame isn't fully initialized yet; don't blow up. */
1980 if (MINI_WINDOW_P (XWINDOW (window)))
1981 error ("Attempt to delete the minibuffer window");
1983 /* It has been suggested that it's a good thing for C-x 0 to have this
1984 behavior, but not such a good idea for #'delete-window to have it.
1985 Maybe C-x 0 should be bound to something else, or maybe frame
1986 deletion should only happen when this is called interactively.
1988 delete_frame_internal (f, !NILP (force), 0, 0);
1992 /* At this point, we know the window has a parent. */
1994 par = XWINDOW (parent);
1996 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1997 /* It's quite likely that deleting a window will result in
1998 subwindows needing to be deleted also (since they are cached
1999 per-window). So we mark them as changed, so that the cachels will
2000 get reset by redisplay and thus deleted subwindows can get
2002 MARK_FRAME_SUBWINDOWS_CHANGED (f);
2004 /* Are we trying to delete any frame's selected window?
2005 Note that we could be dealing with a non-leaf window
2006 where the selected window is one of our children.
2007 So, we check by scanning all the ancestors of the
2008 frame's selected window and comparing each one with
2011 Lisp_Object pwindow;
2013 pwindow = FRAME_SELECTED_WINDOW (f);
2015 while (!NILP (pwindow))
2017 if (EQ (window, pwindow))
2019 pwindow = XWINDOW (pwindow)->parent;
2022 if (EQ (window, pwindow))
2024 /* OK, we found it. */
2025 Lisp_Object alternative;
2026 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
2028 /* If we're about to delete the selected window on the
2029 selected frame, then we should use Fselect_window to select
2030 the new window. On the other hand, if we're about to
2031 delete the selected window on any other frame, we shouldn't do
2032 anything but set the frame's selected_window slot. */
2033 if (EQ (frame, Fselected_frame (Qnil)))
2034 Fselect_window (alternative, Qnil);
2036 set_frame_selected_window (f, alternative);
2040 /* w->buffer is nil in a non-leaf window; in this case,
2041 get rid of the markers we maintain that point into that buffer. */
2042 if (!NILP (w->buffer))
2045 unchain_marker (w->pointm[CURRENT_DISP]);
2046 unchain_marker (w->pointm[DESIRED_DISP]);
2047 unchain_marker (w->pointm[CMOTION_DISP]);
2048 unchain_marker (w->start[CURRENT_DISP]);
2049 unchain_marker (w->start[DESIRED_DISP]);
2050 unchain_marker (w->start[CMOTION_DISP]);
2051 unchain_marker (w->sb_point);
2052 /* This breaks set-window-configuration if windows in the saved
2053 configuration get deleted and multiple frames are in use. */
2054 /* w->buffer = Qnil; */
2057 /* close up the hole in the sibling list */
2058 if (!NILP (w->next))
2059 XWINDOW (w->next)->prev = w->prev;
2060 if (!NILP (w->prev))
2061 XWINDOW (w->prev)->next = w->next;
2062 if (EQ (window, par->hchild))
2063 par->hchild = w->next;
2064 if (EQ (window, par->vchild))
2065 par->vchild = w->next;
2067 /* Find one of our siblings to give our space to. */
2069 Lisp_Object sib = w->prev;
2072 /* If w gives its space to its next sibling, that sibling needs
2073 to have its top/left side pulled back to where w's is.
2074 set_window_{height,width} will re-position the sibling's
2077 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
2078 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
2081 /* Stretch that sibling. */
2082 if (!NILP (par->vchild))
2083 set_window_pixheight
2084 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
2085 if (!NILP (par->hchild))
2087 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
2090 /* If parent now has only one child,
2091 put the child into the parent's place. */
2093 Lisp_Object parchild = par->hchild;
2094 if (NILP (parchild))
2095 parchild = par->vchild;
2096 if (NILP (XWINDOW (parchild)->next))
2098 replace_window (parent, parchild);
2099 mark_window_as_deleted (XWINDOW (parent));
2103 /* Since we may be deleting combination windows, we must make sure that
2104 not only W but all its children have been marked as deleted. */
2105 if (!NILP (w->hchild))
2106 delete_all_subwindows (XWINDOW (w->hchild));
2107 else if (!NILP (w->vchild))
2108 delete_all_subwindows (XWINDOW (w->vchild));
2110 mark_window_as_deleted (w);
2112 f->mirror_dirty = 1;
2117 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2118 Return the next window after WINDOW in the canonical ordering of windows.
2119 If omitted, WINDOW defaults to the selected window.
2121 Optional second arg MINIBUF t means count the minibuffer window even
2122 if not active. MINIBUF nil or omitted means count the minibuffer iff
2123 it is active. MINIBUF neither t nor nil means not to count the
2124 minibuffer even if it is active.
2126 Several frames may share a single minibuffer; if the minibuffer
2127 counts, all windows on all frames that share that minibuffer count
2128 too. Therefore, `next-window' can be used to iterate through the
2129 set of windows even when the minibuffer is on another frame. If the
2130 minibuffer does not count, only windows from WINDOW's frame count.
2132 By default, only the windows in the selected frame are considered.
2133 The optional argument WHICH-FRAMES changes this behavior:
2134 WHICH-FRAMES = `visible' means search windows on all visible frames.
2135 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2136 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2137 WHICH-FRAMES = a frame means search only windows on that frame.
2138 Anything else means restrict to the selected frame.
2140 The optional fourth argument WHICH-DEVICES further clarifies on which
2141 devices to search for frames as specified by WHICH-FRAMES. This value
2142 is only meaningful if WHICH-FRAMES is non-nil.
2143 If nil or omitted, search all devices on the selected console.
2144 If a device, only search that device.
2145 If a console, search all devices on that console.
2146 If a device type, search all devices of that type.
2147 If `window-system', search all window-system devices.
2148 Any other non-nil value means search all devices.
2150 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2151 you can use `next-window' to iterate through the entire cycle of
2152 acceptable windows, eventually ending up back at the window you started with.
2153 `previous-window' traverses the same cycle, in the reverse order.
2155 (window, minibuf, which_frames, which_devices))
2158 Lisp_Object start_window;
2161 window = Fselected_window (Qnil);
2163 CHECK_LIVE_WINDOW (window);
2165 start_window = window;
2167 /* minibuf == nil may or may not include minibuffers.
2168 Decide if it does. */
2170 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2171 else if (! EQ (minibuf, Qt))
2173 /* Now `minibuf' is one of:
2174 t => count all minibuffer windows
2175 lambda => count none of them
2176 or a specific minibuffer window (the active one) to count. */
2178 /* which_frames == nil doesn't specify which frames to include. */
2179 if (NILP (which_frames))
2180 which_frames = (! EQ (minibuf, Qlambda)
2181 ? (FRAME_MINIBUF_WINDOW
2184 (XWINDOW (window)))))
2186 else if (EQ (which_frames, Qvisible))
2188 else if (ZEROP (which_frames))
2190 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2191 /* If which_frames is a frame and window arg isn't on that frame, just
2192 return the first window on the frame. */
2193 return frame_first_window (XFRAME (which_frames));
2194 else if (! EQ (which_frames, Qt))
2195 which_frames = Qnil;
2196 /* Now `which_frames' is one of:
2197 t => search all frames
2198 nil => search just the current frame
2199 visible => search just visible frames
2200 0 => search visible and iconified frames
2201 a window => search the frame that window belongs to. */
2203 /* Do this loop at least once, to get the next window, and perhaps
2204 again, if we hit the minibuffer and that is not acceptable. */
2207 /* Find a window that actually has a next one. This loop
2208 climbs up the tree. */
2209 while (tem = XWINDOW (window)->next, NILP (tem))
2210 if (tem = XWINDOW (window)->parent, !NILP (tem))
2212 else /* window must be minibuffer window now */
2214 /* We've reached the end of this frame.
2215 Which other frames are acceptable? */
2216 tem = WINDOW_FRAME (XWINDOW (window));
2218 if (! NILP (which_frames))
2220 Lisp_Object tem1 = tem;
2221 tem = next_frame (tem, which_frames, which_devices);
2223 /* In the case where the minibuffer is active,
2224 and we include its frame as well as the selected one,
2225 next_frame may get stuck in that frame.
2226 If that happens, go back to the selected frame
2227 so we can complete the cycle. */
2229 XSETFRAME (tem, selected_frame ());
2232 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2238 /* If we're in a combination window, find its first child and
2239 recurse on that. Otherwise, we've found the window we want. */
2242 if (!NILP (XWINDOW (window)->hchild))
2243 window = XWINDOW (window)->hchild;
2244 else if (!NILP (XWINDOW (window)->vchild))
2245 window = XWINDOW (window)->vchild;
2249 /* Which windows are acceptable?
2250 Exit the loop and accept this window if
2251 this isn't a minibuffer window,
2252 or we're accepting all minibuffer windows,
2253 or this is the active minibuffer and we are accepting that one, or
2254 we've come all the way around and we're back at the original window. */
2255 while (MINI_WINDOW_P (XWINDOW (window))
2256 && ! EQ (minibuf, Qt)
2257 && ! EQ (minibuf, window)
2258 && ! EQ (window, start_window));
2263 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2264 Return the window preceding WINDOW in the canonical ordering of windows.
2265 If omitted, WINDOW defaults to the selected window.
2267 Optional second arg MINIBUF t means count the minibuffer window even
2268 if not active. MINIBUF nil or omitted means count the minibuffer iff
2269 it is active. MINIBUF neither t nor nil means not to count the
2270 minibuffer even if it is active.
2272 Several frames may share a single minibuffer; if the minibuffer
2273 counts, all windows on all frames that share that minibuffer count
2274 too. Therefore, `previous-window' can be used to iterate through
2275 the set of windows even when the minibuffer is on another frame. If
2276 the minibuffer does not count, only windows from WINDOW's frame count.
2278 By default, only the windows in the selected frame are considered.
2279 The optional argument WHICH-FRAMES changes this behavior:
2280 WHICH-FRAMES = `visible' means search windows on all visible frames.
2281 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2282 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2283 WHICH-FRAMES = a frame means search only windows on that frame.
2284 Anything else means restrict to the selected frame.
2286 The optional fourth argument WHICH-DEVICES further clarifies on which
2287 devices to search for frames as specified by WHICH-FRAMES. This value
2288 is only meaningful if WHICH-FRAMES is non-nil.
2289 If nil or omitted, search all devices on the selected console.
2290 If a device, only search that device.
2291 If a console, search all devices on that console.
2292 If a device type, search all devices of that type.
2293 If `window-system', search all window-system devices.
2294 Any other non-nil value means search all devices.
2296 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2297 you can use `previous-window' to iterate through the entire cycle of
2298 acceptable windows, eventually ending up back at the window you started with.
2299 `next-window' traverses the same cycle, in the reverse order.
2301 (window, minibuf, which_frames, devices))
2304 Lisp_Object start_window;
2307 window = Fselected_window (Qnil);
2309 CHECK_LIVE_WINDOW (window);
2311 start_window = window;
2313 /* minibuf == nil may or may not include minibuffers.
2314 Decide if it does. */
2316 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2317 else if (! EQ (minibuf, Qt))
2319 /* Now `minibuf' is one of:
2320 t => count all minibuffer windows
2321 lambda => count none of them
2322 or a specific minibuffer window (the active one) to count. */
2324 /* which_frames == nil doesn't specify which frames to include.
2325 Decide which frames it includes. */
2326 if (NILP (which_frames))
2327 which_frames = (! EQ (minibuf, Qlambda)
2328 ? (FRAME_MINIBUF_WINDOW
2331 (XWINDOW (window)))))
2333 else if (EQ (which_frames, Qvisible))
2335 else if (ZEROP (which_frames))
2337 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2338 /* If which_frames is a frame and window arg isn't on that frame, just
2339 return the first window on the frame. */
2340 return frame_first_window (XFRAME (which_frames));
2341 else if (! EQ (which_frames, Qt))
2342 which_frames = Qnil;
2343 /* Now `which_frames' is one of:
2344 t => search all frames
2345 nil => search just the current frame
2346 visible => search just visible frames
2347 0 => search visible and iconified frames
2348 a window => search the frame that window belongs to. */
2350 /* Do this loop at least once, to get the next window, and perhaps
2351 again, if we hit the minibuffer and that is not acceptable. */
2354 /* Find a window that actually has a next one. This loop
2355 climbs up the tree. */
2356 while (tem = XWINDOW (window)->prev, NILP (tem))
2357 if (tem = XWINDOW (window)->parent, !NILP (tem))
2359 else /* window must be minibuffer window now */
2361 /* We have found the top window on the frame.
2362 Which frames are acceptable? */
2363 tem = WINDOW_FRAME (XWINDOW (window));
2365 if (! NILP (which_frames))
2366 /* It's actually important that we use previous_frame here,
2367 rather than next_frame. All the windows acceptable
2368 according to the given parameters should form a ring;
2369 Fnext_window and Fprevious_window should go back and
2370 forth around the ring. If we use next_frame here,
2371 then Fnext_window and Fprevious_window take different
2372 paths through the set of acceptable windows.
2373 window_loop assumes that these `ring' requirement are
2376 Lisp_Object tem1 = tem;
2377 tem = previous_frame (tem, which_frames, devices);
2378 /* In the case where the minibuffer is active,
2379 and we include its frame as well as the selected one,
2380 next_frame may get stuck in that frame.
2381 If that happens, go back to the selected frame
2382 so we can complete the cycle. */
2384 XSETFRAME (tem, selected_frame ());
2387 /* If this frame has a minibuffer, find that window first,
2388 because it is conceptually the last window in that frame. */
2389 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2390 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2392 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2399 /* If we're in a combination window, find its first child and
2400 recurse on that. Otherwise, we've found the window we want. */
2403 if (!NILP (XWINDOW (window)->hchild))
2404 window = XWINDOW (window)->hchild;
2405 else if (!NILP (XWINDOW (window)->vchild))
2406 window = XWINDOW (window)->vchild;
2408 while (tem = XWINDOW (window)->next, !NILP (tem))
2412 /* Which windows are acceptable?
2413 Exit the loop and accept this window if
2414 this isn't a minibuffer window,
2415 or we're accepting all minibuffer windows,
2416 or this is the active minibuffer and we are accepting that one, or
2417 we've come all the way around and we're back at the original window. */
2418 while (MINI_WINDOW_P (XWINDOW (window))
2419 && ! EQ (minibuf, Qt)
2420 && ! EQ (minibuf, window)
2421 && ! EQ (window, start_window));
2426 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2427 Return the next window which is vertically after WINDOW.
2432 struct window *w = decode_window (window);
2433 XSETWINDOW (window, w);
2435 if (MINI_WINDOW_P (XWINDOW (window)))
2438 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2440 if (EQ (window, root))
2443 if (!NILP (XWINDOW (window)->hchild))
2444 window = XWINDOW (window)->hchild;
2445 else if (!NILP (XWINDOW (window)->vchild))
2446 window = XWINDOW (window)->vchild;
2453 if (!NILP (XWINDOW (window)->parent) &&
2454 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2456 if (!NILP (XWINDOW (window)->next))
2457 return XWINDOW (window)->next;
2459 window = XWINDOW (window)->parent;
2462 window = XWINDOW (window)->parent;
2464 while (!EQ (window, root));
2467 if (!NILP (XWINDOW (window)->hchild))
2468 window = XWINDOW (window)->hchild;
2469 else if (!NILP (XWINDOW (window)->vchild))
2470 window = XWINDOW (window)->vchild;
2475 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2476 Select the COUNT'th different window on this frame.
2477 All windows on current frame are arranged in a cyclic order.
2478 This command selects the window COUNT steps away in that order.
2479 A negative COUNT moves in the opposite order.
2481 By default, only the windows in the selected frame are considered.
2482 The optional argument WHICH-FRAMES changes this behavior:
2483 WHICH-FRAMES = `visible' means search windows on all visible frames.
2484 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2485 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2486 WHICH-FRAMES = a frame means search only windows on that frame.
2487 Anything else means restrict to the selected frame.
2489 The optional argument WHICH-DEVICES further clarifies on which devices
2490 to search for frames as specified by WHICH-FRAMES. This value is only
2491 meaningful if WHICH-FRAMES is non-nil.
2492 If nil or omitted, search all devices on the selected console.
2493 If a device, only search that device.
2494 If a console, search all devices on that console.
2495 If a device type, search all devices of that type.
2496 If `window-system', search all window-system devices.
2497 Any other non-nil value means search all devices.
2499 (count, which_frames, which_devices))
2505 w = Fselected_window (Qnil);
2510 w = Fnext_window (w, Qnil, which_frames, which_devices);
2515 w = Fprevious_window (w, Qnil, which_frames, which_devices);
2518 Fselect_window (w, Qnil);
2523 /* Look at all windows, performing an operation specified by TYPE
2526 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2527 frame. If FRAMES is a frame, just look at windows on that frame.
2528 If MINI is non-zero, perform the operation on minibuffer windows too.
2534 GET_BUFFER_WINDOW, /* Arg is buffer */
2535 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2536 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2537 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2539 UNSHOW_BUFFER, /* Arg is buffer */
2540 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2541 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2545 window_loop (enum window_loop type,
2548 Lisp_Object which_frames,
2550 Lisp_Object which_devices)
2552 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2554 Lisp_Object best_window = Qnil;
2555 Lisp_Object next_window;
2556 Lisp_Object last_window;
2557 struct frame *frame;
2558 Lisp_Object frame_arg = Qt;
2559 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2560 /* #### I think the change of "precomputing" last_window and next_window
2561 * #### catch the lossage this is meant(?) to punt on...
2564 Lisp_Object devcons, concons;
2566 /* If we're only looping through windows on a particular frame,
2567 FRAME points to that frame. If we're looping through windows
2568 on all frames, FRAME is 0. */
2569 if (FRAMEP (which_frames))
2570 frame = XFRAME (which_frames);
2571 else if (NILP (which_frames))
2572 frame = selected_frame ();
2576 /* FRAME_ARG is Qlambda to stick to one frame,
2577 Qvisible to consider all visible frames,
2580 frame_arg = Qlambda;
2581 else if (ZEROP (which_frames))
2582 frame_arg = which_frames;
2583 else if (EQ (which_frames, Qvisible))
2584 frame_arg = which_frames;
2586 DEVICE_LOOP_NO_BREAK (devcons, concons)
2588 Lisp_Object device = XCAR (devcons);
2589 Lisp_Object the_frame;
2592 XSETFRAME (the_frame, frame);
2594 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2596 if (NILP (the_frame))
2599 if (!device_matches_device_spec (device,
2600 NILP (which_devices) ?
2601 FRAME_CONSOLE (XFRAME (the_frame)) :
2605 /* Pick a window to start with. */
2609 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2611 /* Figure out the last window we're going to mess with. Since
2612 Fnext_window, given the same options, is guaranteed to go in a
2613 ring, we can just use Fprevious_window to find the last one.
2615 We can't just wait until we hit the first window again,
2616 because it might be deleted. */
2618 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2623 struct window *p = XWINDOW (w);
2624 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2626 /* Pick the next window now, since some operations will delete
2627 the current window. */
2628 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
2630 /* #### Still needed ?? */
2631 /* Given the outstanding quality of the rest of this code,
2632 I feel no shame about putting this piece of shit in. */
2633 if (++lose_lose >= 500)
2636 /* Note that we do not pay attention here to whether
2637 the frame is visible, since Fnext_window skips non-visible frames
2638 if that is desired, under the control of frame_arg. */
2639 if (! MINI_WINDOW_P (p)
2640 || (mini && minibuf_level > 0))
2643 case GET_BUFFER_WINDOW:
2645 if (XBUFFER (p->buffer) == XBUFFER (obj))
2650 case GET_BUFFER_WINDOW_COUNT:
2652 if (XBUFFER (p->buffer) == XBUFFER (obj))
2657 case GET_LRU_WINDOW:
2659 /* t as arg means consider only full-width windows */
2661 && !window_full_width_p (p))
2663 /* Ignore dedicated windows and minibuffers. */
2664 if (MINI_WINDOW_P (p)
2665 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2667 if (NILP (best_window)
2668 || (XINT (XWINDOW (best_window)->use_time)
2669 > XINT (p->use_time)))
2674 case GET_BUFFER_MRU_WINDOW:
2676 /* #### what about the first check in GET_LRU_WINDOW? */
2677 /* Ignore dedicated windows and minibuffers. */
2678 if (MINI_WINDOW_P (p)
2679 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2682 if (XBUFFER (p->buffer) == XBUFFER (obj))
2684 if (NILP (best_window)
2685 || (XINT (XWINDOW (best_window)->use_time)
2686 < XINT (p->use_time)))
2692 case DELETE_OTHER_WINDOWS:
2694 /* Don't delete the last window on a frame; this can
2695 happen when the minibuffer is selected, and would
2696 cause the frame to be deleted. */
2697 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2698 Fdelete_window (w, Qnil);
2702 case DELETE_BUFFER_WINDOWS:
2704 if (EQ (p->buffer, obj))
2706 struct frame *f = XFRAME (WINDOW_FRAME (p));
2708 /* If this window is dedicated, and in a frame
2709 of its own, kill the frame. */
2710 if (EQ (w, FRAME_ROOT_WINDOW (f))
2711 && !NILP (p->dedicated)
2712 && other_visible_frames (f))
2714 /* Skip the other windows on this frame.
2715 There might be one, the minibuffer! */
2716 if (! EQ (w, last_window))
2717 while (f == XFRAME (WINDOW_FRAME
2718 (XWINDOW (next_window))))
2720 /* As we go, check for the end of the
2721 loop. We mustn't start going
2722 around a second time. */
2723 if (EQ (next_window, last_window))
2728 next_window = Fnext_window (next_window,
2732 /* Now we can safely delete the frame. */
2733 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2736 /* If we're deleting the buffer displayed in
2737 the only window on the frame, find a new
2738 buffer to display there. */
2739 if (NILP (p->parent))
2741 Lisp_Object new_buffer;
2742 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2743 if (NILP (new_buffer))
2744 new_buffer = Fget_buffer_create (QSscratch);
2745 Fset_window_buffer (w, new_buffer, Qnil);
2746 if (EQ (w, Fselected_window (Qnil)))
2747 Fset_buffer (p->buffer);
2750 Fdelete_window (w, Qnil);
2755 case GET_LARGEST_WINDOW:
2757 /* Ignore dedicated windows and minibuffers. */
2758 if (MINI_WINDOW_P (p)
2759 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2762 /* write the check as follows to avoid tripping
2763 error_check_window() --ben */
2764 struct window *b = NILP (best_window) ? 0 :
2765 XWINDOW (best_window);
2766 if (NILP (best_window)
2767 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2768 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2776 if (EQ (p->buffer, obj))
2778 /* Find another buffer to show in this window. */
2779 Lisp_Object another_buffer =
2780 Fother_buffer (obj, Qnil, Qnil);
2781 if (NILP (another_buffer))
2783 = Fget_buffer_create (QSscratch);
2784 /* If this window is dedicated, and in a frame
2785 of its own, kill the frame. */
2786 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2787 && !NILP (p->dedicated)
2788 && other_visible_frames (w_frame))
2790 /* Skip the other windows on this frame.
2791 There might be one, the minibuffer! */
2792 if (! EQ (w, last_window))
2793 while (w_frame == XFRAME (WINDOW_FRAME
2794 (XWINDOW (next_window))))
2796 /* As we go, check for the end of the
2797 loop. We mustn't start going
2798 around a second time. */
2799 if (EQ (next_window, last_window))
2804 next_window = Fnext_window (next_window,
2808 /* Now we can safely delete the frame. */
2809 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2814 /* Otherwise show a different buffer in the
2816 p->dedicated = Qnil;
2817 Fset_window_buffer (w, another_buffer, Qnil);
2818 if (EQ (w, Fselected_window (Qnil)))
2819 Fset_buffer (p->buffer);
2829 if (EQ (w, last_window))
2836 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2839 #if 0 /* not currently used */
2842 buffer_window_count (struct buffer *b, struct frame *f)
2844 Lisp_Object buffer, frame;
2846 XSETFRAME (frame, f);
2847 XSETBUFFER (buffer, b);
2849 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2854 buffer_window_mru (struct window *w)
2856 Lisp_Object window =
2857 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2861 else if (XWINDOW (window) == w)
2870 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2871 Return the window least recently selected or used for display.
2873 By default, only the windows in the selected frame are considered.
2874 The optional argument WHICH-FRAMES changes this behavior:
2875 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2876 If WHICH-FRAMES is 0, search all visible and iconified frames.
2877 If WHICH-FRAMES is t, search all frames.
2878 If WHICH-FRAMES is nil, search only the selected frame.
2879 If WHICH-FRAMES is a frame, search only that frame.
2881 The optional argument WHICH-DEVICES further clarifies on which devices
2882 to search for frames as specified by WHICH-FRAMES. This value is only
2883 meaningful if WHICH-FRAMES is non-nil.
2884 If nil or omitted, search all devices on the selected console.
2885 If a device, only search that device.
2886 If a console, search all devices on that console.
2887 If a device type, search all devices of that type.
2888 If `window-system', search all devices on window-system consoles.
2889 Any other non-nil value means search all devices.
2891 (which_frames, which_devices))
2894 /* First try for a non-dedicated window that is full-width */
2895 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2896 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2899 /* Then try for any non-dedicated window */
2900 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices);
2901 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2905 /* FSFmacs never returns a dedicated window here. If we do,
2906 it makes `display-buffer' not work right. #### All of this
2907 shit is so disgusting and awful that it needs to be rethought
2909 /* then try for a dedicated window that is full-width */
2910 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2911 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2914 /* If none of them, then all windows, dedicated or not. */
2915 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
2917 /* At this point we damn well better have found something. */
2918 if (NILP (w)) abort ();
2924 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2925 Return the window largest in area.
2927 By default, only the windows in the selected frame are considered.
2928 The optional argument WHICH-FRAMES changes this behavior:
2929 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2930 If WHICH-FRAMES is 0, search all visible and iconified frames.
2931 If WHICH-FRAMES is t, search all frames.
2932 If WHICH-FRAMES is nil, search only the selected frame.
2933 If WHICH-FRAMES is a frame, search only that frame.
2935 The optional argument WHICH-DEVICES further clarifies on which devices
2936 to search for frames as specified by WHICH-FRAMES. This value is only
2937 meaningful if WHICH-FRAMES is non-nil.
2938 If nil or omitted, search all devices on the selected console.
2939 If a device, only search that device.
2940 If a console, search all devices on that console.
2941 If a device type, search all devices of that type.
2942 If `window-system', search all devices on window-system consoles.
2943 Any other non-nil value means search all devices.
2945 (which_frames, which_devices))
2947 /* Don't search dedicated windows because FSFmacs doesn't.
2948 This stuff is all black magic so don't try to apply common
2950 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2951 which_frames, 0, which_devices);
2954 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2955 Return a window currently displaying BUFFER, or nil if none.
2957 By default, only the windows in the selected frame are considered.
2958 The optional argument WHICH-FRAMES changes this behavior:
2959 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2960 If WHICH-FRAMES is 0, search all visible and iconified frames.
2961 If WHICH-FRAMES is t, search all frames.
2962 If WHICH-FRAMES is nil, search only the selected frame.
2963 If WHICH-FRAMES is a frame, search only that frame.
2965 The optional argument WHICH-DEVICES further clarifies on which devices
2966 to search for frames as specified by WHICH-FRAMES. This value is only
2967 meaningful if WHICH-FRAMES is non-nil.
2968 If nil or omitted, search all devices on the selected console.
2969 If a device, only search that device.
2970 If a console, search all devices on that console.
2971 If a device type, search all devices of that type.
2972 If `window-system', search all devices on window-system consoles.
2973 Any other non-nil value means search all devices.
2975 (buffer, which_frames, which_devices))
2977 buffer = Fget_buffer (buffer);
2978 if (BUFFERP (buffer))
2979 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2980 return window_loop (GET_BUFFER_WINDOW, buffer, 1,
2981 which_frames, 1, which_devices);
2986 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2987 but there is no sensible way to implement those functions, since
2988 you can't in general derive a window from a buffer. */
2990 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2992 Return the width in pixels of the left outside margin of window WINDOW.
2993 If WINDOW is nil, the selected window is assumed.
2997 return make_int (window_left_margin_width (decode_window (window)));
3000 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
3002 Return the width in pixels of the right outside margin of window WINDOW.
3003 If WINDOW is nil, the selected window is assumed.
3007 return make_int (window_right_margin_width (decode_window (window)));
3010 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
3011 Make WINDOW (or the selected window) fill its frame.
3012 Only the frame WINDOW is on is affected.
3013 This function tries to reduce display jumps
3014 by keeping the text previously visible in WINDOW
3015 in the same place on the frame. Doing this depends on
3016 the value of (window-start WINDOW), so if calling this function
3017 in a program gives strange scrolling, make sure the window-start
3018 value is reasonable when this function is called.
3022 struct window *w = decode_window (window);
3023 struct buffer *b = XBUFFER (w->buffer);
3025 int old_top = WINDOW_TOP (w);
3027 XSETWINDOW (window, w);
3029 if (MINI_WINDOW_P (w) && old_top > 0)
3030 error ("Can't expand minibuffer to full frame");
3032 /* Ignore dedicated windows. */
3033 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3035 start_pos = marker_position (w->start[CURRENT_DISP]);
3037 /* Try to minimize scrolling, by setting the window start to the
3038 point which will cause the text at the old window start to be at
3039 the same place on the frame. But don't try to do this if the
3040 window start is outside the visible portion (as might happen when
3041 the display is not current, due to typeahead). */
3042 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
3043 && !MINI_WINDOW_P (w))
3045 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
3047 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
3049 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
3051 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3053 /* We need to do this, so that the window-scroll-functions
3061 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3062 "bDelete windows on (buffer): ", /*
3063 Delete all windows showing BUFFER.
3065 Optional second argument WHICH-FRAMES controls which frames are affected.
3066 If nil or omitted, delete all windows showing BUFFER in any frame.
3067 If t, delete only windows showing BUFFER in the selected frame.
3068 If `visible', delete all windows showing BUFFER in any visible frame.
3069 If a frame, delete only windows showing BUFFER in that frame.
3070 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3071 except that the meanings of nil and t are reversed.
3073 The optional third argument WHICH-DEVICES further clarifies on which
3074 devices to search for frames as specified by WHICH-FRAMES. This value
3075 is only meaningful if WHICH-FRAMES is not t.
3076 If nil or omitted, search only the selected console.
3077 If a device, only search that device.
3078 If a console, search all devices on that console.
3079 If a device type, search all devices of that type.
3080 If `window-system', search all devices on a window system.
3081 Any other non-nil value means search all devices.
3083 (buffer, which_frames, which_devices))
3085 /* This function can GC */
3086 buffer = Fget_buffer (buffer);
3087 CHECK_BUFFER (buffer);
3089 /* WHICH-FRAMES values t and nil mean the opposite of what
3090 window_loop expects. */
3091 if (EQ (which_frames, Qnil))
3093 else if (EQ (which_frames, Qt))
3094 which_frames = Qnil;
3096 /* Ignore dedicated windows. */
3097 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0,
3098 which_frames, 0, which_devices);
3102 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3,
3103 "bReplace buffer in windows: ", /*
3104 Replace BUFFER with some other buffer in all windows showing it.
3106 Optional second argument WHICH-FRAMES controls which frames are affected.
3107 If nil or omitted, all frames are affected.
3108 If t, only the selected frame is affected.
3109 If `visible', all visible frames are affected.
3110 If a frame, only that frame is affected.
3111 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3112 except that the meanings of nil and t are reversed.
3114 The optional third argument WHICH-DEVICES further clarifies on which
3115 devices to search for frames as specified by WHICH-FRAMES. This value
3116 is only meaningful if WHICH-FRAMES is not t.
3117 If nil or omitted, search only the selected console.
3118 If a device, only search that device.
3119 If a console, search all devices on that console.
3120 If a device type, search all devices of that type.
3121 If `window-system', search all devices on a window system.
3122 Any other non-nil value means search all devices.
3124 (buffer, which_frames, which_devices))
3126 /* This function can GC */
3127 buffer = Fget_buffer (buffer);
3128 CHECK_BUFFER (buffer);
3130 /* WHICH-FRAMES values t and nil mean the opposite of what
3131 window_loop expects. */
3132 if (EQ (which_frames, Qnil))
3134 else if (EQ (which_frames, Qt))
3135 which_frames = Qnil;
3137 /* Ignore dedicated windows. */
3138 window_loop (UNSHOW_BUFFER, buffer, 0, which_frames, 0, which_devices);
3142 /* The smallest acceptable dimensions for a window. Anything smaller
3143 might crash Emacs. */
3144 #define MIN_SAFE_WINDOW_WIDTH (2)
3145 #define MIN_SAFE_WINDOW_HEIGHT (2)
3147 /* Make sure that window_min_height and window_min_width are
3148 not too small; if they are, set them to safe minima. */
3151 check_min_window_sizes (void)
3153 /* Smaller values might permit a crash. */
3154 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3155 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3156 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3157 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3161 frame_min_height (struct frame *frame)
3163 /* For height, we have to see whether the frame has a minibuffer, and
3164 whether it wants a modeline. */
3165 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3166 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3167 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3170 /* Return non-zero if both frame sizes are less than or equal to
3171 minimal allowed values. ROWS and COLS are in characters */
3173 frame_size_valid_p (struct frame *frame, int rows, int cols)
3175 return (rows >= frame_min_height (frame)
3176 && cols >= MIN_SAFE_WINDOW_WIDTH);
3179 /* Return non-zero if both frame sizes are less than or equal to
3180 minimal allowed values. WIDTH and HEIGHT are in pixels */
3182 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3185 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3186 return frame_size_valid_p (frame, rows, cols);
3189 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3190 minimum allowable size. */
3192 check_frame_size (struct frame *frame, int *rows, int *cols)
3194 int min_height = frame_min_height (frame);
3196 if (*rows < min_height)
3198 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3199 *cols = MIN_SAFE_WINDOW_WIDTH;
3202 /* Normally the window is deleted if it gets too small.
3203 nodelete nonzero means do not do this.
3204 (The caller should check later and do so if appropriate) */
3206 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3209 struct window *w = XWINDOW (window);
3210 struct frame *f = XFRAME (w->frame);
3212 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3213 Lisp_Object child, minor_kid, major_kid;
3216 int defheight, defwidth;
3218 /* #### This is very likely incorrect and instead the char_to_pixel_
3219 functions should be called. */
3220 default_face_height_and_width (window, &defheight, &defwidth);
3221 line_size = (set_height ? defheight : defwidth);
3223 check_min_window_sizes ();
3225 minsize = (set_height ? window_min_height : window_min_width);
3226 minsize *= line_size;
3229 && !TOP_LEVEL_WINDOW_P (w)
3230 && new_pixsize < minsize)
3232 Fdelete_window (window, Qnil);
3236 SET_LAST_MODIFIED (w, 0);
3237 SET_LAST_FACECHANGE (w);
3238 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3241 WINDOW_HEIGHT (w) = new_pixsize;
3242 major_kid = w->vchild;
3243 minor_kid = w->hchild;
3247 WINDOW_WIDTH (w) = new_pixsize;
3248 major_kid = w->hchild;
3249 minor_kid = w->vchild;
3252 if (!NILP (minor_kid))
3254 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3257 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3259 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3261 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3264 else if (!NILP (major_kid))
3266 int last_pos, last_old_pos, pos, old_pos, first;
3267 int pixel_adj_left = new_pixsize - old_pixsize;
3268 int div_val = old_pixsize << 1;
3271 * Previously we bailed out here if there was no size change.
3272 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3273 * toolbar appears or disappears, windows may not change size,
3274 * but their top and left coordinates need to be updated.
3276 * So we don't bail until after the loop below.
3279 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3282 for (child = major_kid; !NILP (child); child = c->next)
3284 c = XWINDOW (child);
3288 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3289 WINDOW_TOP (c) = last_pos;
3293 old_pos = last_old_pos + WINDOW_WIDTH (c);
3294 WINDOW_LEFT (c) = last_pos;
3297 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3298 /* All but the last window should have a height which is
3299 a multiple of the default line height. */
3300 if (!NILP (c->next))
3301 pos = (pos / line_size) * line_size;
3303 /* Avoid confusion: don't delete child if it becomes too small */
3304 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3306 last_pos = pos + first;
3307 last_old_pos = old_pos;
3310 /* Sometimes we may get called with our old size. In that case
3311 we don't need to do anything else. */
3312 if (!pixel_adj_left)
3315 /* Now delete any children that became too small. */
3317 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3320 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3322 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3327 /* Set the height of WINDOW and all its inferiors. */
3329 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3331 set_window_pixsize (window, new_pixheight, nodelete, 1);
3334 /* Recursively set width of WINDOW and its inferiors. */
3336 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3338 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3342 static int window_select_count;
3344 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3345 Make WINDOW display BUFFER as its contents.
3346 BUFFER can be a buffer or buffer name.
3348 With non-nil optional argument NORECORD, do not modify the
3349 global or per-frame buffer ordering.
3351 (window, buffer, norecord))
3354 struct window *w = decode_window (window);
3356 buffer = Fget_buffer (buffer);
3357 CHECK_BUFFER (buffer);
3359 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3360 error ("Attempt to display deleted buffer");
3364 error ("Window is deleted");
3366 /* While this seems like a logical thing to do, it causes problems
3367 because of saved window configurations. It is possible for a
3368 buffer to get restored into a window in which it is already being
3369 displayed, but start and point are actually at completely
3370 different locations. So we let this function complete fully and
3371 it will then make sure redisplay correctly updates things.
3373 #### This is a kludge. The correct approach is not to do this
3374 but to fix set-window-configuration. */
3376 else if (EQ (tem, buffer))
3379 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3380 is first being set up. */
3382 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3383 error ("Window is dedicated to buffer %s",
3384 XSTRING_DATA (XBUFFER (tem)->name));
3390 w->window_end_pos[CURRENT_DISP] = 0;
3392 w->modeline_hscroll = 0;
3393 Fset_marker (w->pointm[CURRENT_DISP],
3394 make_int (BUF_PT (XBUFFER (buffer))),
3396 set_marker_restricted (w->start[CURRENT_DISP],
3397 make_int (XBUFFER (buffer)->last_window_start),
3399 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3400 /* set start_at_line_beg correctly. GE */
3401 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3402 marker_position (w->start[CURRENT_DISP]));
3403 w->force_start = 0; /* Lucid fix */
3404 SET_LAST_MODIFIED (w, 1);
3405 SET_LAST_FACECHANGE (w);
3406 MARK_WINDOWS_CHANGED (w);
3407 recompute_all_cached_specifiers_in_window (w);
3408 if (EQ (window, Fselected_window (Qnil)))
3410 if (NILP (norecord))
3411 Frecord_buffer (buffer);
3413 Fset_buffer (buffer);
3418 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3419 Select WINDOW. Most editing will apply to WINDOW's buffer.
3420 The main editor command loop selects the buffer of the selected window
3421 before each command.
3423 With non-nil optional argument NORECORD, do not modify the
3424 global or per-frame buffer ordering.
3429 Lisp_Object old_selected_window = Fselected_window (Qnil);
3431 CHECK_LIVE_WINDOW (window);
3432 w = XWINDOW (window);
3434 /* we have already caught dead-window errors */
3435 if (!NILP (w->hchild) || !NILP (w->vchild))
3436 error ("Trying to select non-leaf window");
3438 w->use_time = make_int (++window_select_count);
3440 if (EQ (window, old_selected_window))
3443 /* deselect the old window, if it exists (it might not exist if
3444 the selected device has no frames, which occurs at startup) */
3445 if (!NILP (old_selected_window))
3447 struct window *ow = XWINDOW (old_selected_window);
3449 Fset_marker (ow->pointm[CURRENT_DISP],
3450 make_int (BUF_PT (XBUFFER (ow->buffer))),
3453 MARK_WINDOWS_CHANGED (ow);
3456 /* now select the window's frame */
3457 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3459 select_frame_1 (WINDOW_FRAME (w));
3461 /* also select the window's buffer */
3462 if (NILP (norecord))
3463 Frecord_buffer (w->buffer);
3464 Fset_buffer (w->buffer);
3466 /* Go to the point recorded in the window.
3467 This is important when the buffer is in more
3468 than one window. It also matters when
3469 redisplay_window has altered point after scrolling,
3470 because it makes the change only in the window. */
3472 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3473 if (new_point < BUF_BEGV (current_buffer))
3474 new_point = BUF_BEGV (current_buffer);
3475 else if (new_point > BUF_ZV (current_buffer))
3476 new_point = BUF_ZV (current_buffer);
3478 BUF_SET_PT (current_buffer, new_point);
3481 MARK_WINDOWS_CHANGED (w);
3487 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3488 Lisp_Object override_frame)
3490 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3494 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3496 /* This function can GC */
3499 struct buffer *b = XBUFFER (buf);
3501 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3502 widen_buffer (b, 0);
3503 BUF_SET_PT (b, BUF_BEG (b));
3505 if (!NILP (Vtemp_buffer_show_function))
3506 call1 (Vtemp_buffer_show_function, buf);
3509 window = display_buffer (buf, Qnil, same_frame);
3511 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3512 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3514 Vminibuffer_scroll_window = window;
3515 w = XWINDOW (window);
3517 w->modeline_hscroll = 0;
3518 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3519 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3520 set_marker_restricted (w->sb_point, make_int (1), buf);
3522 /* Run temp-buffer-show-hook, with the chosen window selected. */
3523 if (!preparing_for_armageddon)
3526 tem = Fboundp (Qtemp_buffer_show_hook);
3529 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3532 int count = specpdl_depth ();
3534 /* Select the window that was chosen, for running
3536 record_unwind_protect (save_window_excursion_unwind,
3537 Fcurrent_window_configuration (Qnil));
3539 Fselect_window (window, Qnil);
3540 run_hook (Qtemp_buffer_show_hook);
3541 unbind_to (count, Qnil);
3549 make_dummy_parent (Lisp_Object window)
3552 struct window *o = XWINDOW (window);
3553 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3555 XSETWINDOW (new, p);
3556 copy_lcrecord (p, o);
3558 /* Don't copy the pointers to the line start cache or the face
3560 p->line_start_cache = Dynarr_new (line_start_cache);
3561 p->face_cachels = Dynarr_new (face_cachel);
3562 p->glyph_cachels = Dynarr_new (glyph_cachel);
3563 p->subwindow_instance_cache =
3564 make_lisp_hash_table (30,
3565 HASH_TABLE_KEY_VALUE_WEAK,
3568 /* Put new into window structure in place of window */
3569 replace_window (window, new);
3577 p->start[CURRENT_DISP] = Qnil;
3578 p->start[DESIRED_DISP] = Qnil;
3579 p->start[CMOTION_DISP] = Qnil;
3580 p->pointm[CURRENT_DISP] = Qnil;
3581 p->pointm[DESIRED_DISP] = Qnil;
3582 p->pointm[CMOTION_DISP] = Qnil;
3587 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3588 Split WINDOW, putting SIZE lines in the first of the pair.
3589 WINDOW defaults to the selected one and SIZE to half its size.
3590 If optional third arg HORFLAG is non-nil, split side by side
3591 and put SIZE columns in the first of the pair.
3593 (window, size, horflag))
3596 struct window *o, *p;
3602 window = Fselected_window (Qnil);
3604 CHECK_LIVE_WINDOW (window);
3606 o = XWINDOW (window);
3607 f = XFRAME (WINDOW_FRAME (o));
3611 if (!NILP (horflag))
3612 /* In the new scheme, we are symmetric with respect to separators
3613 so there is no need to do weird things here. */
3615 psize = WINDOW_WIDTH (o) >> 1;
3616 csize = window_pixel_width_to_char_width (o, psize, 0);
3620 psize = WINDOW_HEIGHT (o) >> 1;
3621 csize = window_pixel_height_to_char_height (o, psize, 1);
3627 csize = XINT (size);
3628 if (!NILP (horflag))
3629 psize = window_char_width_to_pixel_width (o, csize, 0);
3631 psize = window_char_height_to_pixel_height (o, csize, 1);
3634 if (MINI_WINDOW_P (o))
3635 error ("Attempt to split minibuffer window");
3636 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3637 error ("Attempt to split unsplittable frame");
3639 check_min_window_sizes ();
3643 if (csize < window_min_height)
3644 error ("Window height %d too small (after splitting)", csize);
3645 if (csize + window_min_height > window_char_height (o, 1))
3646 error ("Window height %d too small (after splitting)",
3647 window_char_height (o, 1) - csize);
3648 if (NILP (o->parent)
3649 || NILP (XWINDOW (o->parent)->vchild))
3651 make_dummy_parent (window);
3652 reset_face_cachels (XWINDOW (window));
3654 XWINDOW (new)->vchild = window;
3655 XFRAME (o->frame)->mirror_dirty = 1;
3660 if (csize < window_min_width)
3661 error ("Window width %d too small (after splitting)", csize);
3662 if (csize + window_min_width > window_char_width (o, 0))
3663 error ("Window width %d too small (after splitting)",
3664 window_char_width (o, 0) - csize);
3665 if (NILP (o->parent)
3666 || NILP (XWINDOW (o->parent)->hchild))
3668 make_dummy_parent (window);
3669 reset_face_cachels (XWINDOW (window));
3671 XWINDOW (new)->hchild = window;
3672 XFRAME (o->frame)->mirror_dirty = 1;
3676 /* Now we know that window's parent is a vertical combination
3677 if we are dividing vertically, or a horizontal combination
3678 if we are making side-by-side windows */
3680 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3681 new = allocate_window ();
3684 p->frame = o->frame;
3686 if (!NILP (p->next))
3687 XWINDOW (p->next)->prev = new;
3690 p->parent = o->parent;
3693 reset_face_cachels (p);
3694 reset_glyph_cachels (p);
3697 /* Apportion the available frame space among the two new windows */
3699 if (!NILP (horflag))
3701 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3702 WINDOW_TOP (p) = WINDOW_TOP (o);
3703 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3704 WINDOW_WIDTH (o) = psize;
3705 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3709 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3710 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3711 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3712 WINDOW_HEIGHT (o) = psize;
3713 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3716 XFRAME (p->frame)->mirror_dirty = 1;
3717 /* do this last (after the window is completely initialized and
3718 the mirror-dirty flag is set) so that specifier recomputation
3719 caused as a result of this will work properly and not abort. */
3720 Fset_window_buffer (new, o->buffer, Qt);
3725 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3726 Make the selected window COUNT lines taller.
3727 From program, optional second arg HORIZONTALP non-nil means grow
3728 sideways COUNT columns, and optional third arg WINDOW specifies the
3729 window to change instead of the selected window.
3731 (count, horizontalp, window))
3734 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0);
3738 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3739 Make the selected window COUNT pixels taller.
3740 From program, optional second arg HORIZONTALP non-nil means grow
3741 sideways COUNT pixels, and optional third arg WINDOW specifies the
3742 window to change instead of the selected window.
3744 (count, horizontalp, window))
3747 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1);
3751 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3752 Make the selected window COUNT lines shorter.
3753 From program, optional second arg HORIZONTALP non-nil means shrink
3754 sideways COUNT columns, and optional third arg WINDOW specifies the
3755 window to change instead of the selected window.
3757 (count, horizontalp, window))
3760 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0);
3764 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3765 Make the selected window COUNT pixels smaller.
3766 From program, optional second arg HORIZONTALP non-nil means shrink
3767 sideways COUNT pixels, and optional third arg WINDOW specifies the
3768 window to change instead of the selected window.
3770 (count, horizontalp, window))
3773 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1);
3778 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3779 int include_gutters_p)
3782 int defheight, defwidth;
3786 XSETWINDOW (window, w);
3788 avail_height = (pixel_height -
3789 (include_gutters_p ? 0 :
3790 window_top_window_gutter_height (w) +
3791 window_bottom_window_gutter_height (w)));
3793 default_face_height_and_width (window, &defheight, &defwidth);
3795 char_height = avail_height / defheight;
3797 /* It's the calling function's responsibility to check these values
3798 and make sure they're not out of range.
3800 #### We need to go through the calling functions and actually
3802 return max (0, char_height);
3806 window_char_height_to_pixel_height (struct window *w, int char_height,
3807 int include_gutters_p)
3810 int defheight, defwidth;
3815 XSETWINDOW (window, w);
3817 default_face_height_and_width (window, &defheight, &defwidth);
3819 avail_height = char_height * defheight;
3820 pixel_height = (avail_height +
3821 (include_gutters_p ? 0 :
3822 window_top_window_gutter_height (w) +
3823 window_bottom_window_gutter_height (w)));
3825 /* It's the calling function's responsibility to check these values
3826 and make sure they're not out of range.
3828 #### We need to go through the calling functions and actually
3830 return max (0, pixel_height);
3833 /* Return number of default lines of text can fit in the window W.
3834 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3835 horizontal scrollbar) in the space that is used for the calculation.
3836 This doesn't include space used by the frame gutters.
3839 window_char_height (struct window *w, int include_gutters_p)
3841 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3846 * Return number of lines currently displayed in window w. If
3847 * end-of-buffer is displayed then the area below end-of-buffer is assume
3848 * to be blank lines of default height.
3849 * Does not include the modeline.
3852 window_displayed_height (struct window *w)
3854 struct buffer *b = XBUFFER (w->buffer);
3855 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3857 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3859 : w->window_end_pos[CURRENT_DISP]);
3861 if (!Dynarr_length (dla))
3862 return window_char_height (w, 0);
3864 num_lines = Dynarr_length (dla);
3866 /* #### Document and assert somewhere that w->window_end_pos == -1
3867 indicates that end-of-buffer is being displayed. */
3870 struct display_line *dl = Dynarr_atp (dla, 0);
3871 int ypos1 = dl->ypos + dl->descent;
3872 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3874 int defheight, defwidth;
3876 XSETWINDOW (window, w);
3882 if (Dynarr_length (dla) == 1)
3883 ypos1 = WINDOW_TEXT_TOP (w);
3886 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3887 /* If this line is clipped then we know that there is no
3888 blank room between eob and the modeline. If we are
3889 scrolling on clipped lines just know off the clipped
3891 if (scroll_on_clipped_lines && dl->clip)
3892 return num_lines - 1;
3893 ypos1 = dl->ypos + dl->descent - dl->clip;
3897 default_face_height_and_width (window, &defheight, &defwidth);
3898 /* #### This probably needs to know about the clipping area once a
3899 final definition is decided on. */
3900 num_lines += ((ypos2 - ypos1) / defheight);
3904 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3907 if (scroll_on_clipped_lines
3908 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3916 window_pixel_width (Lisp_Object window)
3918 return WINDOW_WIDTH (XWINDOW (window));
3921 /* Calculate the pixel of a window, optionally including margin space
3922 but no vertical gutters. */
3924 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3925 int include_margins_p)
3929 int defheight, defwidth;
3932 XSETWINDOW (window, w);
3934 avail_width = (pixel_width -
3935 window_left_gutter_width (w, 0) -
3936 window_right_gutter_width (w, 0) -
3937 (include_margins_p ? 0 : window_left_margin_width (w)) -
3938 (include_margins_p ? 0 : window_right_margin_width (w)));
3940 default_face_height_and_width (window, &defheight, &defwidth);
3942 char_width = (avail_width / defwidth);
3944 /* It's the calling function's responsibility to check these values
3945 and make sure they're not out of range.
3947 #### We need to go through the calling functions and actually
3949 return max (0, char_width);
3953 window_char_width_to_pixel_width (struct window *w, int char_width,
3954 int include_margins_p)
3958 int defheight, defwidth;
3961 XSETWINDOW (window, w);
3963 default_face_height_and_width (window, &defheight, &defwidth);
3965 avail_width = char_width * defwidth;
3966 pixel_width = (avail_width +
3967 window_left_window_gutter_width (w, 0) +
3968 window_right_window_gutter_width (w, 0) +
3969 (include_margins_p ? 0 : window_left_margin_width (w)) +
3970 (include_margins_p ? 0 : window_right_margin_width (w)));
3972 /* It's the calling function's responsibility to check these values
3973 and make sure they're not out of range.
3975 #### We need to go through the calling functions and actually
3977 return max (0, pixel_width);
3980 /* This returns the usable space which doesn't include space needed by
3981 scrollbars or divider lines. */
3983 window_char_width (struct window *w, int include_margins_p)
3985 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3989 #define MINSIZE(w) \
3991 ? window_min_width * defwidth \
3992 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3995 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3997 #define CURSIZE(w) \
3998 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4000 #define CURCHARSIZE(w) \
4001 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4003 #define MINCHARSIZE(window) \
4004 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4005 ? 1 : window_min_height)
4008 window_pixheight (Lisp_Object w)
4010 return window_pixel_height (XWINDOW (w));
4013 /* Unlike set_window_pixheight, this function
4014 also changes the heights of the siblings so as to
4015 keep everything consistent. */
4018 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp,
4021 struct window *win = decode_window (window);
4022 int widthflag = !NILP (horizontalp);
4027 int (*sizefun) (Lisp_Object) = (widthflag
4028 ? window_pixel_width
4029 : window_pixheight);
4030 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4031 ? set_window_pixwidth
4032 : set_window_pixheight);
4034 int defheight, defwidth;
4039 check_min_window_sizes ();
4041 XSETWINDOW (window, win);
4042 f = XFRAME (win->frame);
4043 if (EQ (window, FRAME_ROOT_WINDOW (f)))
4044 error ("Won't change only window");
4046 /* #### This is very likely incorrect and instead the char_to_pixel_
4047 functions should be called. */
4048 default_face_height_and_width (window, &defheight, &defwidth);
4052 w = XWINDOW (window);
4057 error ("No other window to side of this one");
4061 ? !NILP (XWINDOW (parent)->hchild)
4062 : !NILP (XWINDOW (parent)->vchild))
4067 sizep = &CURSIZE (w);
4068 dim = CURCHARSIZE (w);
4070 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4071 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4073 if (MINI_WINDOW_P (XWINDOW (window)))
4075 else if (!NILP (parent))
4077 Fdelete_window (window, Qnil);
4083 delta *= (widthflag ? defwidth : defheight);
4088 maxdelta = ((!NILP (parent))
4089 ? (*sizefun) (parent) - *sizep
4090 : ((!NILP (w->next))
4091 ? (*sizefun) (w->next) - MINSIZE (w->next)
4092 : ((!NILP (w->prev))
4093 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4094 /* This is a frame with only one window,
4095 a minibuffer-only or a minibufferless frame. */
4098 if (delta > maxdelta)
4099 /* This case traps trying to make the minibuffer
4100 the full frame, or make the only window aside from the
4101 minibuffer the full frame. */
4108 /* #### Chuck: is this correct? */
4109 if (*sizep + delta < MINSIZE (window))
4111 Fdelete_window (window);
4117 if (!NILP (w->next) &&
4118 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4120 CURBEG (XWINDOW (w->next)) += delta;
4121 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4122 (*setsizefun) (window, *sizep + delta, 0);
4124 else if (!NILP (w->prev) &&
4125 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4127 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4128 CURBEG (w) -= delta;
4129 (*setsizefun) (window, *sizep + delta, 0);
4134 int opht = (*sizefun) (parent);
4136 /* If trying to grow this window to or beyond size of the parent,
4137 make delta1 so big that, on shrinking back down,
4138 all the siblings end up with less than one line and are deleted. */
4139 if (opht <= *sizep + delta)
4140 delta1 = opht * opht * 2;
4141 /* Otherwise, make delta1 just right so that if we add delta1
4142 lines to this window and to the parent, and then shrink
4143 the parent back to its original size, the new proportional
4144 size of this window will increase by delta. */
4146 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4148 /* Add delta1 lines or columns to this window, and to the parent,
4149 keeping things consistent while not affecting siblings. */
4150 CURSIZE (XWINDOW (parent)) = opht + delta1;
4151 (*setsizefun) (window, *sizep + delta1, 0);
4153 /* Squeeze out delta1 lines or columns from our parent,
4154 shrinking this window and siblings proportionately.
4155 This brings parent back to correct size.
4156 Delta1 was calculated so this makes this window the desired size,
4157 taking it all out of the siblings. */
4158 (*setsizefun) (parent, opht, 0);
4161 SET_LAST_MODIFIED (w, 0);
4162 SET_LAST_FACECHANGE (w);
4163 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4164 /* overkill maybe, but better to be correct */
4165 MARK_FRAME_GUTTERS_CHANGED (f);
4175 /* Scroll contents of window WINDOW up COUNT lines.
4176 If COUNT < (top line height / average line height) then we just adjust
4179 window_scroll (Lisp_Object window, Lisp_Object count, int direction,
4180 Error_behavior errb)
4182 struct window *w = XWINDOW (window);
4183 struct buffer *b = XBUFFER (w->buffer);
4184 int selected = EQ (window, Fselected_window (Qnil));
4186 Lisp_Object point, tem;
4187 display_line_dynarr *dla;
4188 int fheight, fwidth, modeline = 0;
4189 struct display_line* dl;
4192 point = make_int (BUF_PT (b));
4195 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4197 if (pos < BUF_BEGV (b))
4199 else if (pos > BUF_ZV (b))
4202 point = make_int (pos);
4205 /* Always set force_start so that redisplay_window will run
4206 the window-scroll-functions. */
4209 /* #### When the fuck does this happen? I'm so glad that history has
4210 completely documented the behavior of the scrolling functions under
4211 all circumstances. */
4212 tem = Fpos_visible_in_window_p (point, window);
4215 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4217 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4218 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4219 WINDOW_TEXT_TOP_CLIP (w) = 0;
4220 MARK_WINDOWS_CHANGED (w);
4225 if (EQ (count, Qminus))
4229 count = Fprefix_numeric_value (count);
4230 value = XINT (count) * direction;
4233 return; /* someone just made a pointless call */
4237 /* If the user didn't specify how far to scroll then we have to figure it
4238 out by ourselves. */
4239 if (NILP (count) || EQ (count, Qminus))
4241 /* Going forwards is easy. If that is what we are doing then just
4242 set value and the section which handles the user specifying a
4243 positive value will work. */
4246 value = window_displayed_height (w) - next_screen_context_lines;
4247 value = (value < 1 ? 1 : value);
4250 /* Going backwards is hard. We can't use the same loop used if the
4251 user specified a negative value because we care about
4252 next_screen_context_lines. In a variable height world you don't
4253 know how many lines above you can actually be displayed and still
4254 have the context lines appear. So we leave value set to 0 and add
4255 a separate section to deal with this. */
4259 if (direction == 1 && !value)
4264 /* Determine parameters to test for partial line scrolling with. */
4265 dla = window_display_lines (w, CURRENT_DISP);
4267 if (INTP (Vwindow_pixel_scroll_increment))
4268 fheight = XINT (Vwindow_pixel_scroll_increment);
4269 else if (!NILP (Vwindow_pixel_scroll_increment))
4270 default_face_height_and_width (window, &fheight, &fwidth);
4272 if (Dynarr_length (dla) >= 1)
4273 modeline = Dynarr_atp (dla, 0)->modeline;
4275 dl = Dynarr_atp (dla, modeline);
4279 /* Go for partial display line scrolling. This just means bumping
4280 the clip by a reasonable amount and redisplaying, everything else
4281 remains unchanged. */
4282 if (!NILP (Vwindow_pixel_scroll_increment)
4284 Dynarr_length (dla) >= (1 + modeline)
4286 (dl->ascent - dl->top_clip) - fheight * value > 0)
4288 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4289 MARK_WINDOWS_CHANGED (w);
4294 Bufpos startp, old_start;
4296 if (WINDOW_TEXT_TOP_CLIP (w))
4298 WINDOW_TEXT_TOP_CLIP (w) = 0;
4299 MARK_WINDOWS_CHANGED (w);
4302 old_start = marker_position (w->start[CURRENT_DISP]);
4303 startp = vmotion (w, old_start, value, &vtarget);
4305 if (vtarget < value &&
4306 (w->window_end_pos[CURRENT_DISP] == -1
4307 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4309 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4314 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4317 w->start_at_line_beg = beginning_of_line_p (b, startp);
4318 MARK_WINDOWS_CHANGED (w);
4320 if (!point_would_be_visible (w, startp, XINT (point)))
4323 BUF_SET_PT (b, startp);
4325 set_marker_restricted (w->pointm[CURRENT_DISP],
4334 /* Go for partial display line scrolling. This just means bumping
4335 the clip by a reasonable amount and redisplaying, everything else
4336 remains unchanged. */
4337 if (!NILP (Vwindow_pixel_scroll_increment)
4339 Dynarr_length (dla) >= (1 + modeline)
4341 (dl->ascent - dl->top_clip) - fheight * value <
4342 (dl->ascent + dl->descent - dl->clip)
4344 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4346 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4347 MARK_WINDOWS_CHANGED (w);
4352 Bufpos startp, old_start;
4354 if (WINDOW_TEXT_TOP_CLIP (w))
4356 WINDOW_TEXT_TOP_CLIP (w) = 0;
4357 MARK_WINDOWS_CHANGED (w);
4360 old_start = marker_position (w->start[CURRENT_DISP]);
4361 startp = vmotion (w, old_start, value, &vtarget);
4364 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4366 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4371 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4374 w->start_at_line_beg = beginning_of_line_p (b, startp);
4375 MARK_WINDOWS_CHANGED (w);
4377 /* #### Scroll back by less than a line. This code was
4378 originally for scrolling over large pixmaps and it
4379 loses when a line being *exposed* at the top of the
4380 window is bigger than the current one. However, for
4381 pixel based scrolling in general we can guess that
4382 the line we are going to display is probably the same
4383 size as the one we are on. In that instance we can
4384 have a reasonable stab at a suitable top clip. Fixing
4385 this properly is hard (and probably slow) as we would
4386 have to call redisplay to figure out the exposed line
4388 if (!NILP (Vwindow_pixel_scroll_increment)
4389 && Dynarr_length (dla) >= (1 + modeline)
4390 && dl->ascent + fheight * value > 0)
4392 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4395 if (!point_would_be_visible (w, startp, XINT (point)))
4399 if (MINI_WINDOW_P (w))
4402 new_point = start_of_last_line (w, startp);
4405 BUF_SET_PT (b, new_point);
4407 set_marker_restricted (w->pointm[CURRENT_DISP],
4408 make_int (new_point),
4414 else /* value == 0 && direction == -1 */
4416 if (WINDOW_TEXT_TOP_CLIP (w))
4418 WINDOW_TEXT_TOP_CLIP (w) = 0;
4419 MARK_WINDOWS_CHANGED (w);
4421 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4423 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4429 int movement = next_screen_context_lines - 1;
4430 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4431 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4433 start_with_point_on_display_line (w, bottom,
4434 -1 - (movement - vtarget));
4436 if (startp >= old_startp)
4437 startp = vmotion (w, old_startp, -1, NULL);
4439 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4442 w->start_at_line_beg = beginning_of_line_p (b, startp);
4443 MARK_WINDOWS_CHANGED (w);
4445 if (!point_would_be_visible (w, startp, XINT (point)))
4447 Bufpos new_point = start_of_last_line (w, startp);
4450 BUF_SET_PT (b, new_point);
4452 set_marker_restricted (w->pointm[CURRENT_DISP],
4453 make_int (new_point),
4460 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4461 Scroll text of current window up COUNT lines; or near full screen if no arg.
4462 A near full screen is `next-screen-context-lines' less than a full screen.
4463 Negative COUNT means scroll downward.
4464 When calling from a program, supply an integer as argument or nil.
4465 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4466 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4471 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME);
4475 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4476 Scroll text of current window down COUNT lines; or near full screen if no arg.
4477 A near full screen is `next-screen-context-lines' less than a full screen.
4478 Negative COUNT means scroll upward.
4479 When calling from a program, supply a number as argument or nil.
4480 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4481 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4486 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME);
4490 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4491 Return the other window for "other window scroll" commands.
4492 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4493 specifies the window.
4494 If `other-window-scroll-buffer' is non-nil, a window
4495 showing that buffer is used.
4500 Lisp_Object selected_window = Fselected_window (Qnil);
4502 if (MINI_WINDOW_P (XWINDOW (selected_window))
4503 && !NILP (Vminibuffer_scroll_window))
4504 window = Vminibuffer_scroll_window;
4505 /* If buffer is specified, scroll that buffer. */
4506 else if (!NILP (Vother_window_scroll_buffer))
4508 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4510 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4514 /* Nothing specified; look for a neighboring window on the same
4516 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4518 if (EQ (window, selected_window))
4519 /* That didn't get us anywhere; look for a window on another
4522 window = Fnext_window (window, Qnil, Qt, Qnil);
4523 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4524 && ! EQ (window, selected_window));
4527 CHECK_LIVE_WINDOW (window);
4529 if (EQ (window, selected_window))
4530 error ("There is no other window");
4535 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4536 Scroll next window upward COUNT lines; or near full frame if no arg.
4537 The next window is the one below the current one; or the one at the top
4538 if the current one is at the bottom. Negative COUNT means scroll downward.
4539 When calling from a program, supply a number as argument or nil.
4541 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4542 specifies the window to scroll.
4543 If `other-window-scroll-buffer' is non-nil, scroll the window
4544 showing that buffer, popping the buffer up if necessary.
4548 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME);
4552 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4553 Scroll selected window display COUNT columns left.
4554 Default for COUNT is window width minus 2.
4558 Lisp_Object window = Fselected_window (Qnil);
4559 struct window *w = XWINDOW (window);
4560 int n = (NILP (count) ?
4561 window_char_width (w, 0) - 2 :
4562 XINT (Fprefix_numeric_value (count)));
4564 return Fset_window_hscroll (window, make_int (w->hscroll + n));
4567 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4568 Scroll selected window display COUNT columns right.
4569 Default for COUNT is window width minus 2.
4573 Lisp_Object window = Fselected_window (Qnil);
4574 struct window *w = XWINDOW (window);
4575 int n = (NILP (count) ?
4576 window_char_width (w, 0) - 2 :
4577 XINT (Fprefix_numeric_value (count)));
4579 return Fset_window_hscroll (window, make_int (w->hscroll - n));
4582 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4583 Center point in WINDOW. With N, put point on line N.
4584 The desired position of point is always relative to the window.
4585 If WINDOW is nil, the selected window is used.
4589 struct window *w = decode_window (window);
4590 struct buffer *b = XBUFFER (w->buffer);
4591 Bufpos opoint = BUF_PT (b);
4595 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4598 n = Fprefix_numeric_value (n);
4600 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4603 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4605 w->start_at_line_beg = beginning_of_line_p (b, startp);
4607 MARK_WINDOWS_CHANGED (w);
4611 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4612 Position point relative to WINDOW.
4613 With no argument, position text at center of window.
4614 An argument specifies window line; zero means top of window,
4615 negative means relative to bottom of window.
4616 If WINDOW is nil, the selected window is used.
4623 Bufpos start, new_point;
4626 /* Don't use decode_window() because we need the new value of
4629 window = Fselected_window (Qnil);
4631 CHECK_LIVE_WINDOW (window);
4632 w = XWINDOW (window);
4633 b = XBUFFER (w->buffer);
4635 height = window_displayed_height (w);
4636 selected = EQ (window, Fselected_window (w->frame));
4642 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4643 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4645 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4648 BUF_SET_PT (b, new_point);
4650 Fset_window_point (window, make_int (new_point));
4652 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4656 start = marker_position (w->start[CURRENT_DISP]);
4657 if (start < BUF_BEGV (b))
4658 start = BUF_BEGV (b);
4659 else if (start > BUF_ZV (b))
4663 new_point = BUF_PT (b);
4665 new_point = marker_position (w->pointm[CURRENT_DISP]);
4667 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4670 BUF_SET_PT (b, new_point);
4672 Fset_window_point (window, make_int (new_point));
4674 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4677 return make_int (retval);
4681 /* #### Is this going to work right when at eob? */
4682 arg = Fprefix_numeric_value (arg);
4684 XSETINT (arg, XINT (arg) + height);
4687 start = marker_position (w->start[CURRENT_DISP]);
4688 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4691 new_point = BUF_PT (b);
4693 new_point = marker_position (w->pointm[CURRENT_DISP]);
4695 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4698 BUF_SET_PT (b, new_point);
4700 Fset_window_point (window, make_int (new_point));
4702 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4704 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4710 BUF_SET_PT (b, start);
4712 Fset_window_point (window, make_int (start));
4716 return Fvertical_motion (arg, window, Qnil);
4720 new_point = vmotion (XWINDOW (window),
4721 marker_position (w->pointm[CURRENT_DISP]),
4723 Fset_window_point (window, make_int (new_point));
4724 return make_int (vpos);
4730 map_windows_1 (Lisp_Object window,
4731 int (*mapfun) (struct window *w, void *closure),
4734 for (; !NILP (window); window = XWINDOW (window)->next)
4737 struct window *w = XWINDOW (window);
4739 if (!NILP (w->vchild))
4740 retval = map_windows_1 (w->vchild, mapfun, closure);
4741 else if (!NILP (w->hchild))
4742 retval = map_windows_1 (w->hchild, mapfun, closure);
4744 retval = (mapfun) (w, closure);
4753 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4754 invocation of MAPFUN. If any invocation of MAPFUN returns
4755 non-zero, the mapping is halted. Otherwise, map_windows() maps
4756 over all windows in F.
4758 If MAPFUN creates or deletes windows, the behavior is undefined. */
4761 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4765 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4768 Lisp_Object frmcons, devcons, concons;
4770 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4772 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4784 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4787 w->shadow_thickness_changed = 1;
4788 MARK_WINDOWS_CHANGED (w);
4792 vertical_divider_changed_in_window (Lisp_Object specifier,
4796 MARK_WINDOWS_CHANGED (w);
4797 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4800 /* also used in scrollbar.c */
4802 some_window_value_changed (Lisp_Object specifier, struct window *w,
4805 MARK_WINDOWS_CHANGED (w);
4808 #ifdef MEMORY_USAGE_STATS
4814 #ifdef HAVE_SCROLLBARS
4818 int other_redisplay;
4823 compute_window_mirror_usage (struct window_mirror *mir,
4824 struct window_stats *stats,
4825 struct overhead_stats *ovstats)
4829 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4831 #ifdef HAVE_SCROLLBARS
4833 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4836 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4839 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4842 #endif /* HAVE_SCROLLBARS */
4843 stats->other_redisplay +=
4844 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4845 stats->other_redisplay +=
4846 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4850 compute_window_usage (struct window *w, struct window_stats *stats,
4851 struct overhead_stats *ovstats)
4854 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4855 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4856 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4857 stats->line_start +=
4858 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4859 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4862 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4863 Return stats about the memory usage of window WINDOW.
4864 The values returned are in the form of an alist of usage types and byte
4865 counts. The byte counts attempt to encompass all the memory used
4866 by the window (separate from the memory logically associated with a
4867 buffer or frame), including internal structures and any malloc()
4868 overhead associated with them. In practice, the byte counts are
4869 underestimated because certain memory usage is very hard to determine
4870 \(e.g. the amount of memory used inside the Xt library or inside the
4871 X server) and because there is other stuff that might logically
4872 be associated with a window, buffer, or frame (e.g. window configurations,
4873 glyphs) but should not obviously be included in the usage counts.
4875 Multiple slices of the total memory usage may be returned, separated
4876 by a nil. Each slice represents a particular view of the memory, a
4877 particular way of partitioning it into groups. Within a slice, there
4878 is no overlap between the groups of memory, and each slice collectively
4879 represents all the memory concerned.
4883 struct window_stats stats;
4884 struct overhead_stats ovstats;
4885 Lisp_Object val = Qnil;
4887 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4889 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4891 val = acons (Qface_cache, make_int (stats.face), val);
4892 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4893 #ifdef HAVE_SCROLLBARS
4894 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4896 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4897 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4898 val = acons (Qother, make_int (stats.other), val);
4899 val = Fcons (Qnil, val);
4900 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4901 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4902 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4904 return Fnreverse (val);
4907 #endif /* MEMORY_USAGE_STATS */
4910 /************************************************************************/
4911 /* Window configurations */
4912 /************************************************************************/
4914 /* #### This window configuration stuff has had serious bugs lurking in it
4915 for years; it would be a -huge- win if this was reimplemented in lisp.
4918 /* If you add anything to this structure make sure saved_window_equal
4922 Lisp_Object window; /* window */
4923 Lisp_Object buffer; /* buffer */
4924 Lisp_Object start; /* copied marker */
4925 Lisp_Object pointm; /* copied marker */
4926 Lisp_Object sb_point; /* copied marker */
4927 Lisp_Object mark; /* copied marker */
4933 Charcount modeline_hscroll;
4934 int parent_index; /* index into saved_windows */
4935 int prev_index; /* index into saved_windows */
4936 char start_at_line_beg; /* boolean */
4938 #define WINDOW_SLOT_DECLARATION
4939 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4940 #include "winslots.h"
4943 /* If you add anything to this structure make sure window_config_equal
4945 struct window_config
4947 struct lcrecord_header header;
4948 /* int frame_width; No longer needed, JV
4949 int frame_height; */
4951 Lisp_Object selected_frame;
4953 Lisp_Object current_window;
4954 Lisp_Object current_buffer;
4955 Lisp_Object minibuffer_scroll_window;
4956 Lisp_Object root_window;
4957 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4958 /* Record the values of window-min-width and window-min-height
4959 so that window sizes remain consistent with them. */
4960 int min_width, min_height;
4961 int saved_windows_count;
4962 /* Zero-sized arrays aren't ANSI C */
4963 struct saved_window saved_windows[1];
4966 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4967 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4968 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4969 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4970 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4973 mark_window_config (Lisp_Object obj)
4975 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4977 mark_object (config->current_window);
4978 mark_object (config->current_buffer);
4979 mark_object (config->minibuffer_scroll_window);
4980 mark_object (config->root_window);
4982 for (i = 0; i < config->saved_windows_count; i++)
4984 struct saved_window *s = SAVED_WINDOW_N (config, i);
4985 mark_object (s->window);
4986 mark_object (s->buffer);
4987 mark_object (s->start);
4988 mark_object (s->pointm);
4989 mark_object (s->sb_point);
4990 mark_object (s->mark);
4992 /* #### This looked like this. I do not see why specifier cached
4993 values should not be marked, as such specifiers as toolbars
4994 might have GC-able instances. Freed configs are not marked,
4995 aren't they? -- kkm */
4996 mark_object (s->dedicated);
4998 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
4999 #include "winslots.h"
5006 sizeof_window_config_for_n_windows (int n)
5008 return (sizeof (struct window_config) +
5009 /* n - 1 because zero-sized arrays aren't ANSI C */
5010 (n - 1) *sizeof (struct saved_window));
5014 sizeof_window_config (const void *h)
5016 const struct window_config *c = (const struct window_config *) h;
5017 return sizeof_window_config_for_n_windows (c->saved_windows_count);
5021 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5023 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5026 error ("printing unreadable object #<window-configuration 0x%x>",
5027 config->header.uid);
5028 write_c_string ("#<window-configuration ", printcharfun);
5029 sprintf (buf, "0x%x>", config->header.uid);
5030 write_c_string (buf, printcharfun);
5033 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
5034 window_configuration,
5036 print_window_config,
5037 0, 0, 0, 0, sizeof_window_config,
5038 struct window_config);
5041 /* Returns a boolean indicating whether the two saved windows are
5044 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
5046 #define WINDOW_SLOT(slot, compare) \
5047 if (!compare (win1->slot, win2->slot)) \
5049 #include "winslots.h"
5052 EQ (win1->window, win2->window) &&
5053 EQ (win1->buffer, win2->buffer) &&
5054 internal_equal (win1->start, win2->start, 0) &&
5055 internal_equal (win1->pointm, win2->pointm, 0) &&
5056 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5057 internal_equal (win1->mark, win2->mark, 0) &&
5058 win1->pixel_left == win2->pixel_left &&
5059 win1->pixel_top == win2->pixel_top &&
5060 win1->pixel_width == win2->pixel_width &&
5061 win1->pixel_height == win2->pixel_height &&
5062 win1->hscroll == win2->hscroll &&
5063 win1->modeline_hscroll == win2->modeline_hscroll &&
5064 win1->parent_index == win2->parent_index &&
5065 win1->prev_index == win2->prev_index &&
5066 win1->start_at_line_beg == win2->start_at_line_beg;
5069 /* Returns a boolean indicating whether the two given configurations
5072 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5074 struct window_config *fig1, *fig2;
5077 /* First check if they are truly the same. */
5078 if (EQ (conf1, conf2))
5081 fig1 = XWINDOW_CONFIGURATION (conf1);
5082 fig2 = XWINDOW_CONFIGURATION (conf2);
5084 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5085 EQ (fig1->current_window, fig2->current_window) &&
5086 EQ (fig1->current_buffer, fig2->current_buffer) &&
5087 EQ (fig1->root_window, fig2->root_window) &&
5088 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5090 fig1->frame_width == fig2->frame_width &&
5091 fig1->frame_height == fig2->frame_height)) */
5094 for (i = 0; i < fig1->saved_windows_count; i++)
5096 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5097 SAVED_WINDOW_N (fig2, i)))
5104 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5105 Return t if OBJECT is a window-configuration object.
5109 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5113 mark_windows_in_use_closure (struct window *w, void *closure)
5115 int mark = *(int *)closure;
5116 w->config_mark = mark;
5121 mark_windows_in_use (struct frame *f, int mark)
5123 map_windows (f, mark_windows_in_use_closure, &mark);
5126 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5128 free_window_configuration (Lisp_Object window_config)
5131 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5133 /* Free all the markers. It's not completely necessary that
5134 we do this (window configs sitting in a free list aren't
5135 marked normally so the markers wouldn't be marked anyway)
5136 but it's more efficient. */
5137 for (i = 0; i < config->saved_windows_count; i++)
5139 struct saved_window *p = SAVED_WINDOW_N (config, i);
5141 if (!NILP (p->pointm))
5143 free_marker (XMARKER (p->pointm));
5146 if (!NILP (p->start))
5148 free_marker (XMARKER (p->start));
5151 if (!NILP (p->sb_point))
5153 free_marker (XMARKER (p->sb_point));
5156 if (!NILP (p->mark))
5158 free_marker (XMARKER (p->mark));
5163 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5164 free_managed_lcrecord (Vwindow_configuration_free_list
5165 [config->saved_windows_count - 1],
5171 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5172 Set the configuration of windows and buffers as specified by CONFIGURATION.
5173 CONFIGURATION must be a value previously returned
5174 by `current-window-configuration' (which see).
5179 struct window_config *config;
5180 struct saved_window *p;
5181 Lisp_Object new_current_buffer;
5185 struct gcpro gcpro1;
5186 Lisp_Object old_window_config;
5187 /* int previous_frame_height;
5188 int previous_frame_width;*/
5189 int previous_pixel_top;
5190 int previous_pixel_height;
5191 int previous_pixel_left;
5192 int previous_pixel_width;
5193 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5194 int real_font_height;
5195 int converted_minibuf_height,target_minibuf_height;
5196 int specpdl_count = specpdl_depth ();
5198 GCPRO1 (configuration);
5200 CHECK_WINDOW_CONFIGURATION (configuration);
5201 config = XWINDOW_CONFIGURATION (configuration);
5203 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5206 /* Do not signal an error here if the frame was deleted. There are
5207 reasonable cases where we could get here with a deleted frame and
5208 just want to do close to nothing instead. */
5210 if (FRAME_LIVE_P (f))
5212 /* restore the frame characteristics */
5214 new_current_buffer = config->current_buffer;
5215 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5216 new_current_buffer = Qnil;
5219 * Assumed precondition: w->config_mark = 0 for all w
5220 * This procedure should ensure this is true by the time it exits
5221 * to ensure the precondition for future calls.
5223 * We use w->config_mark to know whether we're modifying a
5224 * window that is currently visible on the frame (#### we
5225 * should just be able to check whether the window is dead
5226 * or not, but this way is safer?). As we process each
5227 * window, we set its config_mark to 0. At the end, we
5228 * go through all the windows that used to be on the frame,
5229 * set each one's config_mark to 0 (to maintain the
5230 * assumed precondition) and delete each one that's no
5233 * #### Using a window-configuration to keep track of
5234 * the current windows is wasteful. All we need is the
5235 * list of windows, so we could just use a dynarr.
5237 old_window_config = Fcurrent_window_configuration (frame);
5239 /* If the new configuration is already equal to the old, then stop
5240 right here. This saves the work below and it also saves
5241 triggering a full redisplay of this window. This is a huge win
5242 when using the mouse since the mode motion code uses
5243 save-window-excursion extensively but will rarely cause the
5244 configuration to actually change. */
5245 if (window_config_equal (configuration, old_window_config))
5247 free_window_configuration (old_window_config);
5252 /* We can't quit or even check for quit because that may cause
5253 investigation of the frame state, which may crash if the frame is
5254 in an inconsistent state. */
5255 begin_dont_check_for_quit ();
5256 record_unwind_protect (free_window_configuration, old_window_config);
5258 mark_windows_in_use (f, 1);
5259 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5260 /* Force subwindows to be remapped. This is overkill but saves
5261 us having to rely on the redisplay code to unmap any extant
5264 #### It does cause some extra flashing though which we could
5265 possibly avoid. So consider trying to get redisplay to work
5268 Removing the instances from the frame cache is wrong because
5269 an instance is only put in the frame cache when it is
5270 instantiated. So if we do this there is a chance that stuff
5271 will never get put back in the frame cache. */
5272 reset_frame_subwindow_instance_cache (f);
5275 /* JV: This is bogus,
5276 First of all, the units are inconsistent. The frame sizes are measured
5277 in characters but the window sizes are stored in pixels. So if a
5278 font size change happened between saving and restoring, the
5279 frame "sizes" maybe equal but the windows still should be
5280 resized. This is tickled a lot by the new "character size
5281 stays constant" policy in 21.0. It leads to very weird
5282 glitches (and possibly crashes when asserts are tickled).
5284 Just changing the units doesn't help because changing the
5285 toolbar configuration can also change the pixel positions.
5286 Luckily there is a much simpler way of doing this, see below.
5288 previous_frame_width = FRAME_WIDTH (f);
5289 previous_frame_height = FRAME_HEIGHT (f);
5290 /* If the frame has been resized since this window configuration was
5291 made, we change the frame to the size specified in the
5292 configuration, restore the configuration, and then resize it
5293 back. We keep track of the prevailing height in these variables. */
5294 if (config->frame_height != FRAME_HEIGHT (f)
5295 || config->frame_width != FRAME_WIDTH (f))
5296 change_frame_size (f, config->frame_height, config->frame_width, 0);
5299 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5300 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5301 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5302 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5304 /* remember some properties of the minibuffer */
5306 default_face_height_and_width (frame, &real_font_height, 0);
5307 assert(real_font_height > 0);
5309 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5311 previous_minibuf_height
5312 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5313 previous_minibuf_top
5314 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5315 previous_minibuf_width
5316 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5320 previous_minibuf_height = 0;
5321 previous_minibuf_top = 0;
5322 previous_minibuf_width = 0;
5324 converted_minibuf_height =
5325 (previous_minibuf_height % real_font_height) == 0 ?
5326 - (previous_minibuf_height / real_font_height ) : /* lines */
5327 previous_minibuf_height; /* pixels */
5329 /* Temporarily avoid any problems with windows that are smaller
5330 than they are supposed to be. */
5331 window_min_height = 1;
5332 window_min_width = 1;
5334 /* OK, now restore all the windows in the window config.
5335 This may involve "undeleting" windows, since the
5336 windows in the window config may be deleted.
5338 for (k = 0; k < config->saved_windows_count; k++)
5340 p = SAVED_WINDOW_N (config, k);
5341 w = XWINDOW (p->window);
5344 /* The window might be dead. In this case, its redisplay
5345 structures were freed, so we need to reallocate them. */
5346 if (!w->face_cachels)
5348 w->face_cachels = Dynarr_new (face_cachel);
5349 reset_face_cachels (w);
5351 if (!w->glyph_cachels)
5352 w->glyph_cachels = Dynarr_new (glyph_cachel);
5353 if (!w->line_start_cache)
5354 w->line_start_cache = Dynarr_new (line_start_cache);
5355 w->gutter_extent_modiff[0] = 0;
5356 w->gutter_extent_modiff[1] = 0;
5357 w->gutter_extent_modiff[2] = 0;
5358 w->gutter_extent_modiff[3] = 0;
5361 if (p->parent_index >= 0)
5362 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5366 if (p->prev_index >= 0)
5368 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5370 /* This is true for a minibuffer-only frame. */
5371 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5374 XWINDOW (w->prev)->next = p->window;
5379 if (!NILP (w->parent))
5381 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5383 XWINDOW (w->parent)->vchild = p->window;
5384 XWINDOW (w->parent)->hchild = Qnil;
5388 XWINDOW (w->parent)->hchild = p->window;
5389 XWINDOW (w->parent)->vchild = Qnil;
5393 if (!w->config_mark)
5395 /* #### This should be equivalent to the window previously
5396 having been dead. If we're brave, we'll put in an
5397 assertion to this effect. */
5398 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5400 else /* if (!EQ (w->buffer, p->buffer)) */
5402 /* With the new redisplay we let it know that a change has
5403 been made and it will take care of the rest. If we don't
5404 tell it something has possibly changed it could lead to
5405 incorrect display. */
5406 MARK_WINDOWS_CHANGED (w);
5409 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5410 WINDOW_TOP (w) = WINDOW_TOP (p);
5411 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5412 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5413 w->hscroll = p->hscroll;
5414 w->modeline_hscroll = p->modeline_hscroll;
5415 w->line_cache_last_updated = Qzero;
5416 /* When we restore a window's configuration, the identity of
5417 the window hasn't actually changed - so there is no
5418 reason why we shouldn't preserve the instance cache for
5419 it - unless it was originally deleted. This will often
5420 buy us something as we will not have to re-instantiate
5421 all the instances. This is because this is an instance
5422 cache - not a display cache. Preserving the display cache
5423 would definitely be wrong.
5425 We specifically want to do this for tabs, since for some
5426 reason finding a file will cause the configuration to be
5428 if (NILP (w->subwindow_instance_cache))
5429 w->subwindow_instance_cache =
5430 make_lisp_hash_table (30,
5431 HASH_TABLE_KEY_VALUE_WEAK,
5433 SET_LAST_MODIFIED (w, 1);
5434 SET_LAST_FACECHANGE (w);
5437 /* #### Consider making the instance cache a winslot. */
5438 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5439 #include "winslots.h"
5441 /* Reinstall the saved buffer and pointers into it. */
5442 if (NILP (p->buffer))
5443 w->buffer = p->buffer;
5446 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5447 /* If saved buffer is alive, install it. */
5449 w->buffer = p->buffer;
5450 w->start_at_line_beg = p->start_at_line_beg;
5451 set_marker_restricted (w->start[CURRENT_DISP],
5452 Fmarker_position (p->start),
5454 set_marker_restricted (w->pointm[CURRENT_DISP],
5455 Fmarker_position (p->pointm),
5457 set_marker_restricted (w->sb_point,
5458 Fmarker_position (p->sb_point),
5460 Fset_marker (XBUFFER (w->buffer)->mark,
5461 Fmarker_position (p->mark), w->buffer);
5463 /* As documented in Fcurrent_window_configuration, don't
5464 save the location of point in the buffer which was current
5465 when the window configuration was recorded. */
5466 if (!EQ (p->buffer, new_current_buffer) &&
5467 XBUFFER (p->buffer) == current_buffer)
5468 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5470 else if (NILP (w->buffer) ||
5471 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5472 /* Else if window's old buffer is dead too, get a live one. */
5474 /* #### The following line makes me nervous... */
5475 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5476 w->buffer = Fget_buffer_create (QSscratch);
5477 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5478 /* This will set the markers to beginning of visible
5480 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5481 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5483 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5484 w->start_at_line_beg = 1;
5487 /* Keeping window's old buffer; make sure the markers
5490 /* Set window markers at start of visible range. */
5491 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5492 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5494 if (XMARKER (w->sb_point)->buffer == 0)
5495 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5496 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5497 set_marker_restricted (w->pointm[CURRENT_DISP],
5499 (BUF_PT (XBUFFER (w->buffer))),
5501 w->start_at_line_beg = 1;
5506 FRAME_ROOT_WINDOW (f) = config->root_window;
5507 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5508 then calls do_switch_frame() below to select the frame that was
5509 recorded in the window config as being selected.
5511 Instead, we don't ever change the selected frame, and either
5512 call Fselect_window() below if the window config's frame is
5513 currently selected, or just set the selected window of the
5514 window config's frame. */
5517 /* Set the frame height to the value it had before this function. */
5518 if (previous_frame_height != FRAME_HEIGHT (f)
5519 || previous_frame_width != FRAME_WIDTH (f))
5520 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5522 /* We just reset the size and position of the minibuffer, to its old
5523 value, which needn't be valid. So we do some magic to see which value
5524 to actually take. Then we set it.
5527 We take the old value if is in the same units but differs from the
5530 #### Now we get more cases correct then ever before, but
5531 are we treating all? For instance what if the frames minibuf window
5532 is no longer the same one?
5534 target_minibuf_height = previous_minibuf_height;
5535 if (converted_minibuf_height &&
5536 (converted_minibuf_height * config->minibuf_height) > 0 &&
5537 (converted_minibuf_height != config->minibuf_height))
5539 target_minibuf_height = config->minibuf_height < 0 ?
5540 - (config->minibuf_height * real_font_height) :
5541 config->minibuf_height;
5542 target_minibuf_height =
5543 max(target_minibuf_height,real_font_height);
5545 if (previous_minibuf_height)
5547 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5548 = previous_minibuf_top -
5549 (target_minibuf_height - previous_minibuf_height);
5550 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5551 target_minibuf_height, 0);
5552 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5553 previous_minibuf_width, 0);
5556 /* This is a better way to deal with frame resizing, etc.
5557 What we _actually_ want is for the old (just restored)
5559 into the place of the new one. So we just do that. Simple! */
5560 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5561 /* Note that this function also updates the subwindow
5563 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5564 previous_pixel_height -
5565 (target_minibuf_height - previous_minibuf_height), 0);
5566 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5567 /* Note that this function also updates the subwindow
5569 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5571 /* If restoring in the current frame make the window current,
5572 otherwise just update the frame selected_window slot to be
5573 the restored current_window. */
5574 if (f == selected_frame ())
5577 /* When using `pop-window-configuration', often the minibuffer
5578 ends up as the selected window even though it's not active ...
5579 I really don't know the cause of this, but it should never
5580 happen. This kludge should fix it.
5582 #### Find out why this is really going wrong. */
5583 if (!minibuf_level &&
5584 MINI_WINDOW_P (XWINDOW (config->current_window)))
5585 window_to_select = Fnext_window (config->current_window,
5588 window_to_select = config->current_window;
5590 /* Do this last so that buffer stacking is calculated
5592 Fselect_window (config->current_window, Qnil);
5594 if (!NILP (new_current_buffer))
5596 Fset_buffer (new_current_buffer);
5597 Frecord_buffer (new_current_buffer);
5601 Fset_buffer (XWINDOW (config->current_window)->buffer);
5602 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5606 set_frame_selected_window (f, config->current_window);
5609 old_window_config = Qnil; /* Warning suppression */
5611 /* Restore the minimum heights recorded in the configuration. */
5612 window_min_height = config->min_height;
5613 window_min_width = config->min_width;
5616 /* see above comment */
5617 /* Fselect_window will have made f the selected frame, so we
5618 reselect the proper frame here. Fhandle_switch_frame will change the
5619 selected window too, but that doesn't make the call to
5620 Fselect_window above totally superfluous; it still sets f's
5622 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5623 do_switch_frame (config->selected_frame, Qnil, 0);
5626 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5628 if (FRAME_LIVE_P (f))
5630 /* Do this before calling recompute_all_cached_specifiers_in_window()
5631 so that things like redisplay_redraw_cursor() won't abort due
5632 to no window mirror present. */
5633 f->mirror_dirty = 1;
5635 config = XWINDOW_CONFIGURATION (old_window_config);
5636 for (k = 0; k < config->saved_windows_count; k++)
5638 p = SAVED_WINDOW_N (config, k);
5639 w = XWINDOW (p->window);
5640 /* Remember, we set w->config_mark on all currently visible
5641 windows, and reset it on all newly visible windows.
5642 Any windows still marked need to be deleted. */
5645 mark_window_as_deleted (w);
5650 /* We just potentially changed the window's buffer and
5651 potentially turned a dead window into a live one,
5652 so we need to recompute the cached specifier values. */
5653 recompute_all_cached_specifiers_in_window (w);
5658 /* Now restore things, when everything else if OK. */
5660 unbind_to (specpdl_count, Qnil);
5667 /* Mark all subwindows of a window as deleted. The argument
5668 W is actually the subwindow tree of the window in question. */
5671 delete_all_subwindows (struct window *w)
5673 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5674 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5675 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5677 mark_window_as_deleted (w);
5682 count_windows (struct window *window)
5685 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5686 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5687 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5691 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5694 for (j = 0; j < lim; j++)
5696 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5700 return 0; /* suppress compiler warning */
5704 save_window_save (Lisp_Object window, struct window_config *config, int i)
5708 for (; !NILP (window); window = w->next)
5710 struct saved_window *p = SAVED_WINDOW_N (config, i);
5712 w = XWINDOW (window);
5715 p->buffer = w->buffer;
5716 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5717 WINDOW_TOP (p) = WINDOW_TOP (w);
5718 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5719 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5720 p->hscroll = w->hscroll;
5721 p->modeline_hscroll = w->modeline_hscroll;
5723 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5724 #include "winslots.h"
5726 if (!NILP (w->buffer))
5728 /* Save w's value of point in the window configuration.
5729 If w is the selected window, then get the value of point
5730 from the buffer; pointm is garbage in the selected window. */
5731 if (EQ (window, Fselected_window (Qnil)))
5733 p->pointm = noseeum_make_marker ();
5734 Fset_marker (p->pointm,
5735 make_int (BUF_PT (XBUFFER (w->buffer))),
5739 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5741 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5742 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5743 p->start_at_line_beg = w->start_at_line_beg;
5745 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5753 p->start_at_line_beg = 0;
5756 if (NILP (w->parent))
5757 p->parent_index = -1;
5759 p->parent_index = saved_window_index (w->parent, config, i);
5763 p->prev_index = saved_window_index (w->prev, config, i);
5764 if (!NILP (w->vchild))
5765 i = save_window_save (w->vchild, config, i);
5766 if (!NILP (w->hchild))
5767 i = save_window_save (w->hchild, config, i);
5774 /* Added to doc string:
5776 This also records the currently selected frame, and FRAME's focus
5777 redirection (see `redirect-frame-focus').
5782 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5783 Return an object representing the current window configuration of FRAME.
5784 If FRAME is nil or omitted, use the selected frame.
5785 This describes the number of windows, their sizes and current buffers,
5786 and for each window on FRAME the displayed buffer, where display
5787 starts, and the positions of point and mark.
5788 An exception is made for point in the current buffer:
5789 its value is -not- saved.
5794 struct frame *f = decode_frame (frame);
5795 struct window_config *config;
5796 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5798 int real_font_height;
5800 if (n_windows <= countof (Vwindow_configuration_free_list))
5801 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5802 (Vwindow_configuration_free_list
5805 /* More than ten windows; just allocate directly */
5806 config = (struct window_config *)
5807 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5808 &lrecord_window_configuration);
5809 XSETWINDOW_CONFIGURATION (result, config);
5811 config->frame_width = FRAME_WIDTH (f);
5812 config->frame_height = FRAME_HEIGHT (f); */
5813 /* When using `push-window-configuration', often the minibuffer ends
5814 up as the selected window because functions run as the result of
5815 user interaction e.g. hyper-apropos. It seems to me the sensible
5816 thing to do is not record the minibuffer here. */
5817 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5818 config->current_window = FRAME_SELECTED_WINDOW (f);
5820 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5821 XSETBUFFER (config->current_buffer, current_buffer);
5822 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5823 config->root_window = FRAME_ROOT_WINDOW (f);
5824 config->min_height = window_min_height;
5825 config->min_width = window_min_width;
5826 config->saved_windows_count = n_windows;
5827 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5829 /* save the minibuffer height using the heuristics from
5830 change_frame_size_1 */
5832 XSETFRAME (frame, f); /* frame could have been nil ! */
5833 default_face_height_and_width (frame, &real_font_height, 0);
5834 assert(real_font_height > 0);
5836 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5837 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5840 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5841 - (minibuf_height / real_font_height ) : /* lines */
5842 minibuf_height; /* pixels */
5848 save_window_excursion_unwind (Lisp_Object window_config)
5850 Lisp_Object val = Fset_window_configuration (window_config);
5851 free_window_configuration (window_config);
5855 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5856 Execute body, preserving window sizes and contents.
5857 Restores which buffer appears in which window, where display starts,
5858 as well as the current buffer.
5859 Does not restore the value of point in current buffer.
5863 /* This function can GC */
5865 int speccount = specpdl_depth ();
5867 record_unwind_protect (save_window_excursion_unwind,
5868 Fcurrent_window_configuration (Qnil));
5869 val = Fprogn (args);
5870 return unbind_to (speccount, val);
5873 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5874 Return the horizontal pixel position of POS in window.
5875 Beginning of line is column 0. This is calculated using the redisplay
5876 display tables. If WINDOW is nil, the current window is assumed.
5877 If POS is nil, point is assumed. Note that POS must be visible for
5878 a non-nil result to be returned.
5882 struct window* w = decode_window (window);
5883 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5885 struct display_line *dl = 0;
5886 struct display_block *db = 0;
5887 struct rune* rb = 0;
5888 int y = w->last_point_y[CURRENT_DISP];
5889 int x = w->last_point_x[CURRENT_DISP];
5891 if (MINI_WINDOW_P (w))
5894 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5900 pos = Fwindow_point (window);
5905 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5910 for (i = first_line; i < Dynarr_length (dla); i++)
5912 dl = Dynarr_atp (dla, i);
5913 /* find the vertical location first */
5914 if (point >= dl->bufpos && point <= dl->end_bufpos)
5916 db = get_display_block_from_line (dl, TEXT);
5917 for (i = 0; i < Dynarr_length (db->runes); i++)
5919 rb = Dynarr_atp (db->runes, i);
5920 if (point <= rb->bufpos)
5932 /* optimized case */
5933 dl = Dynarr_atp (dla, y);
5934 db = get_display_block_from_line (dl, TEXT);
5936 if (x >= Dynarr_length (db->runes))
5939 rb = Dynarr_atp (db->runes, x);
5942 return make_int (rb->xpos - WINDOW_LEFT (w));
5947 /* This is short and simple in elisp, but... it was written to debug
5948 problems purely on the C side. That is where we need to call it so
5951 debug_print_window (Lisp_Object window, int level)
5954 Lisp_Object child = Fwindow_first_vchild (window);
5957 child = Fwindow_first_hchild (window);
5959 for (i = level; i > 0; i--)
5962 stderr_out ("#<window");
5964 Lisp_Object buffer = XWINDOW (window)->buffer;
5965 if (!NILP (buffer) && BUFFERP (buffer))
5966 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5968 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
5970 while (!NILP (child))
5972 debug_print_window (child, level + 1);
5973 child = Fwindow_next_child (child);
5977 void debug_print_windows (struct frame *f);
5979 debug_print_windows (struct frame *f)
5981 debug_print_window (f->root_window, 0);
5982 putc ('\n', stderr);
5984 #endif /* DEBUG_XEMACS */
5987 /************************************************************************/
5988 /* initialization */
5989 /************************************************************************/
5992 syms_of_window (void)
5994 INIT_LRECORD_IMPLEMENTATION (window);
5995 INIT_LRECORD_IMPLEMENTATION (window_configuration);
5997 defsymbol (&Qwindowp, "windowp");
5998 defsymbol (&Qwindow_live_p, "window-live-p");
5999 defsymbol (&Qwindow_configurationp, "window-configuration-p");
6000 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6001 defsymbol (&Qdisplay_buffer, "display-buffer");
6003 #ifdef MEMORY_USAGE_STATS
6004 defsymbol (&Qface_cache, "face-cache");
6005 defsymbol (&Qglyph_cache, "glyph-cache");
6006 defsymbol (&Qline_start_cache, "line-start-cache");
6007 #ifdef HAVE_SCROLLBARS
6008 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
6010 defsymbol (&Qother_redisplay, "other-redisplay");
6011 /* Qother in general.c */
6014 DEFSUBR (Fselected_window);
6015 DEFSUBR (Flast_nonminibuf_window);
6016 DEFSUBR (Fminibuffer_window);
6017 DEFSUBR (Fwindow_minibuffer_p);
6019 DEFSUBR (Fwindow_live_p);
6020 DEFSUBR (Fwindow_first_hchild);
6021 DEFSUBR (Fwindow_first_vchild);
6022 DEFSUBR (Fwindow_next_child);
6023 DEFSUBR (Fwindow_previous_child);
6024 DEFSUBR (Fwindow_parent);
6025 DEFSUBR (Fwindow_lowest_p);
6026 DEFSUBR (Fwindow_truncated_p);
6027 DEFSUBR (Fwindow_highest_p);
6028 DEFSUBR (Fwindow_leftmost_p);
6029 DEFSUBR (Fwindow_rightmost_p);
6030 DEFSUBR (Fpos_visible_in_window_p);
6031 DEFSUBR (Fwindow_buffer);
6032 DEFSUBR (Fwindow_frame);
6033 DEFSUBR (Fwindow_height);
6034 DEFSUBR (Fwindow_displayed_height);
6035 DEFSUBR (Fwindow_width);
6036 DEFSUBR (Fwindow_full_width);
6037 DEFSUBR (Fwindow_pixel_height);
6038 DEFSUBR (Fwindow_pixel_width);
6039 DEFSUBR (Fwindow_text_area_height);
6040 DEFSUBR (Fwindow_text_area_pixel_height);
6041 DEFSUBR (Fwindow_displayed_text_pixel_height);
6042 DEFSUBR (Fwindow_text_area_pixel_width);
6043 DEFSUBR (Fwindow_hscroll);
6044 DEFSUBR (Fset_window_hscroll);
6045 DEFSUBR (Fmodeline_hscroll);
6046 DEFSUBR (Fset_modeline_hscroll);
6047 #if 0 /* bogus FSF crock */
6048 DEFSUBR (Fwindow_redisplay_end_trigger);
6049 DEFSUBR (Fset_window_redisplay_end_trigger);
6051 DEFSUBR (Fwindow_pixel_edges);
6052 DEFSUBR (Fwindow_text_area_pixel_edges);
6053 DEFSUBR (Fwindow_point);
6054 DEFSUBR (Fwindow_start);
6055 DEFSUBR (Fwindow_end);
6056 DEFSUBR (Fwindow_last_line_visible_height);
6057 DEFSUBR (Fset_window_point);
6058 DEFSUBR (Fset_window_start);
6059 DEFSUBR (Fwindow_dedicated_p);
6060 DEFSUBR (Fset_window_dedicated_p);
6061 DEFSUBR (Fnext_window);
6062 DEFSUBR (Fprevious_window);
6063 DEFSUBR (Fnext_vertical_window);
6064 DEFSUBR (Fother_window);
6065 DEFSUBR (Fget_lru_window);
6066 DEFSUBR (Fget_largest_window);
6067 DEFSUBR (Fget_buffer_window);
6068 DEFSUBR (Fwindow_left_margin_pixel_width);
6069 DEFSUBR (Fwindow_right_margin_pixel_width);
6070 DEFSUBR (Fdelete_other_windows);
6071 DEFSUBR (Fdelete_windows_on);
6072 DEFSUBR (Freplace_buffer_in_windows);
6073 DEFSUBR (Fdelete_window);
6074 DEFSUBR (Fset_window_buffer);
6075 DEFSUBR (Fselect_window);
6076 DEFSUBR (Fsplit_window);
6077 DEFSUBR (Fenlarge_window);
6078 DEFSUBR (Fenlarge_window_pixels);
6079 DEFSUBR (Fshrink_window);
6080 DEFSUBR (Fshrink_window_pixels);
6081 DEFSUBR (Fscroll_up);
6082 DEFSUBR (Fscroll_down);
6083 DEFSUBR (Fscroll_left);
6084 DEFSUBR (Fscroll_right);
6085 DEFSUBR (Fother_window_for_scrolling);
6086 DEFSUBR (Fscroll_other_window);
6087 DEFSUBR (Fcenter_to_window_line);
6088 DEFSUBR (Fmove_to_window_line);
6089 #ifdef MEMORY_USAGE_STATS
6090 DEFSUBR (Fwindow_memory_usage);
6092 DEFSUBR (Fwindow_configuration_p);
6093 DEFSUBR (Fset_window_configuration);
6094 DEFSUBR (Fcurrent_window_configuration);
6095 DEFSUBR (Fsave_window_excursion);
6096 DEFSUBR (Fcurrent_pixel_column);
6100 reinit_vars_of_window (void)
6103 /* Make sure all windows get marked */
6104 minibuf_window = Qnil;
6105 staticpro_nodump (&minibuf_window);
6107 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6109 Vwindow_configuration_free_list[i] =
6110 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6111 &lrecord_window_configuration);
6112 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6117 vars_of_window (void)
6119 reinit_vars_of_window ();
6121 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6122 *Non-nil means to scroll if point lands on a line which is clipped.
6124 scroll_on_clipped_lines = 1;
6126 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6127 See `temp-buffer-show-function'.
6129 Vtemp_buffer_show_hook = Qnil;
6131 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6132 Non-nil means call as function to display a help buffer.
6133 The function is called with one argument, the buffer to be displayed.
6134 Used by `with-output-to-temp-buffer'.
6135 If this function is used, then it must do the entire job of showing
6136 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6137 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6139 Vtemp_buffer_show_function = Qnil;
6141 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6142 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6144 Vminibuffer_scroll_window = Qnil;
6146 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6147 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6149 Vother_window_scroll_buffer = Qnil;
6151 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6152 *Number of pixels to scroll by per requested line.
6153 If nil then normal line scrolling occurs regardless of line height.
6154 If t then scrolling is done in increments equal to the height of the default face.
6156 Vwindow_pixel_scroll_increment = Qt;
6158 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6159 *Number of lines of continuity when scrolling by screenfuls.
6161 next_screen_context_lines = 2;
6163 DEFVAR_INT ("window-min-height", &window_min_height /*
6164 *Delete any window less than this tall (including its modeline).
6166 window_min_height = 4;
6168 DEFVAR_INT ("window-min-width", &window_min_width /*
6169 *Delete any window less than this wide.
6171 window_min_width = 10;
6175 specifier_vars_of_window (void)
6177 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6178 *How thick to draw 3D shadows around modelines.
6179 If this is set to 0, modelines will be the traditional 2D. Sizes above
6180 10 will be accepted but the maximum thickness that will be drawn is 10.
6181 This is a specifier; use `set-specifier' to change it.
6183 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6184 /* The initial value for modeline-shadow-thickness is 2, but if the
6185 user removes all specifications we provide a fallback value of 0,
6186 which is probably what was expected. */
6187 set_specifier_fallback (Vmodeline_shadow_thickness,
6188 list1 (Fcons (Qnil, Qzero)));
6189 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6191 set_specifier_caching (Vmodeline_shadow_thickness,
6192 offsetof (struct window, modeline_shadow_thickness),
6193 modeline_shadow_thickness_changed,
6196 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6197 *Whether the modeline should be displayed.
6198 This is a specifier; use `set-specifier' to change it.
6200 Vhas_modeline_p = Fmake_specifier (Qboolean);
6201 set_specifier_fallback (Vhas_modeline_p,
6202 list1 (Fcons (Qnil, Qt)));
6203 set_specifier_caching (Vhas_modeline_p,
6204 offsetof (struct window, has_modeline_p),
6205 /* #### It's strange that we need a special
6206 flag to indicate that the shadow-thickness
6207 has changed, but not one to indicate that
6208 the modeline has been turned off or on. */
6209 some_window_value_changed,
6212 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6213 &Vvertical_divider_always_visible_p /*
6214 *Should XEmacs always display vertical dividers between windows.
6216 When this is non-nil, vertical dividers are always shown, and are
6217 draggable. When it is nil, vertical dividers are shown only when
6218 there are no scrollbars in between windows, and are not draggable.
6220 This is a specifier; use `set-specifier' to change it.
6222 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6223 set_specifier_fallback (Vvertical_divider_always_visible_p,
6224 list1 (Fcons (Qnil, Qt)));
6225 set_specifier_caching (Vvertical_divider_always_visible_p,
6226 offsetof (struct window,
6227 vertical_divider_always_visible_p),
6228 vertical_divider_changed_in_window,
6231 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6232 *How thick to draw 3D shadows around vertical dividers.
6233 This is a specifier; use `set-specifier' to change it.
6235 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6236 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6237 list1 (Fcons (Qnil, Qzero)));
6238 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6240 set_specifier_caching (Vvertical_divider_shadow_thickness,
6241 offsetof (struct window,
6242 vertical_divider_shadow_thickness),
6243 vertical_divider_changed_in_window,
6245 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6246 *The width of the vertical dividers, not including shadows.
6248 For TTY windows, divider line is always one character wide. When
6249 instance of this specifier is zero in a TTY window, no divider is
6250 drawn at all between windows. When non-zero, a one character wide
6251 divider is displayed.
6253 This is a specifier; use `set-specifier' to change it.
6256 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6258 Lisp_Object fb = Qnil;
6260 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6262 #ifdef HAVE_X_WINDOWS
6263 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6265 #ifdef HAVE_MS_WINDOWS
6266 /* #### This should be made magic and made to obey system settings */
6267 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6269 set_specifier_fallback (Vvertical_divider_line_width, fb);
6271 set_specifier_caching (Vvertical_divider_line_width,
6272 offsetof (struct window,
6273 vertical_divider_line_width),
6274 vertical_divider_changed_in_window,
6277 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6278 *How much space to leave around the vertical dividers.
6280 In TTY windows, spacing is always zero, and the value of this
6281 specifier is ignored.
6283 This is a specifier; use `set-specifier' to change it.
6285 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6287 Lisp_Object fb = Qnil;
6289 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6291 #ifdef HAVE_X_WINDOWS
6292 /* #### 3D dividers look great on MS Windows with spacing = 0.
6293 Should not the same value be the fallback under X? - kkm */
6294 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6296 #ifdef HAVE_MS_WINDOWS
6297 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6299 set_specifier_fallback (Vvertical_divider_spacing, fb);
6301 set_specifier_caching (Vvertical_divider_spacing,
6302 offsetof (struct window, vertical_divider_spacing),
6303 vertical_divider_changed_in_window,