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 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2540 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2544 window_loop (enum window_loop type,
2547 Lisp_Object which_frames,
2549 Lisp_Object which_devices)
2551 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2553 Lisp_Object best_window = Qnil;
2554 Lisp_Object next_window;
2555 Lisp_Object last_window;
2556 struct frame *frame;
2557 Lisp_Object frame_arg = Qt;
2558 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2559 /* #### I think the change of "precomputing" last_window and next_window
2560 * #### catch the lossage this is meant(?) to punt on...
2563 Lisp_Object devcons, concons;
2565 /* If we're only looping through windows on a particular frame,
2566 FRAME points to that frame. If we're looping through windows
2567 on all frames, FRAME is 0. */
2568 if (FRAMEP (which_frames))
2569 frame = XFRAME (which_frames);
2570 else if (NILP (which_frames))
2571 frame = selected_frame ();
2575 /* FRAME_ARG is Qlambda to stick to one frame,
2576 Qvisible to consider all visible frames,
2579 frame_arg = Qlambda;
2580 else if (ZEROP (which_frames))
2581 frame_arg = which_frames;
2582 else if (EQ (which_frames, Qvisible))
2583 frame_arg = which_frames;
2585 DEVICE_LOOP_NO_BREAK (devcons, concons)
2587 Lisp_Object device = XCAR (devcons);
2588 Lisp_Object the_frame;
2591 XSETFRAME (the_frame, frame);
2593 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2595 if (NILP (the_frame))
2598 if (!device_matches_device_spec (device,
2599 NILP (which_devices) ?
2600 FRAME_CONSOLE (XFRAME (the_frame)) :
2604 /* Pick a window to start with. */
2608 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2610 /* Figure out the last window we're going to mess with. Since
2611 Fnext_window, given the same options, is guaranteed to go in a
2612 ring, we can just use Fprevious_window to find the last one.
2614 We can't just wait until we hit the first window again,
2615 because it might be deleted. */
2617 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2622 struct window *p = XWINDOW (w);
2624 /* Pick the next window now, since some operations will delete
2625 the current window. */
2626 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
2628 /* #### Still needed ?? */
2629 /* Given the outstanding quality of the rest of this code,
2630 I feel no shame about putting this piece of shit in. */
2631 if (++lose_lose >= 500)
2634 /* Note that we do not pay attention here to whether
2635 the frame is visible, since Fnext_window skips non-visible frames
2636 if that is desired, under the control of frame_arg. */
2637 if (! MINI_WINDOW_P (p)
2638 || (mini && minibuf_level > 0))
2641 case GET_BUFFER_WINDOW:
2643 if (XBUFFER (p->buffer) == XBUFFER (obj))
2648 case GET_BUFFER_WINDOW_COUNT:
2650 if (XBUFFER (p->buffer) == XBUFFER (obj))
2655 case GET_LRU_WINDOW:
2657 /* t as arg means consider only full-width windows */
2659 && !window_full_width_p (p))
2661 /* Ignore dedicated windows and minibuffers. */
2662 if (MINI_WINDOW_P (p)
2663 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2665 if (NILP (best_window)
2666 || (XINT (XWINDOW (best_window)->use_time)
2667 > XINT (p->use_time)))
2672 case GET_BUFFER_MRU_WINDOW:
2674 /* #### what about the first check in GET_LRU_WINDOW? */
2675 /* Ignore dedicated windows and minibuffers. */
2676 if (MINI_WINDOW_P (p)
2677 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2680 if (XBUFFER (p->buffer) == XBUFFER (obj))
2682 if (NILP (best_window)
2683 || (XINT (XWINDOW (best_window)->use_time)
2684 < XINT (p->use_time)))
2690 case DELETE_OTHER_WINDOWS:
2692 /* Don't delete the last window on a frame; this can
2693 happen when the minibuffer is selected, and would
2694 cause the frame to be deleted. */
2695 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2696 Fdelete_window (w, Qnil);
2700 case DELETE_BUFFER_WINDOWS:
2702 if (EQ (p->buffer, obj))
2704 struct frame *f = XFRAME (WINDOW_FRAME (p));
2706 /* If this window is dedicated, and in a frame
2707 of its own, kill the frame. */
2708 if (EQ (w, FRAME_ROOT_WINDOW (f))
2709 && !NILP (p->dedicated)
2710 && other_visible_frames (f))
2712 /* Skip the other windows on this frame.
2713 There might be one, the minibuffer! */
2714 if (! EQ (w, last_window))
2715 while (f == XFRAME (WINDOW_FRAME
2716 (XWINDOW (next_window))))
2718 /* As we go, check for the end of the
2719 loop. We mustn't start going
2720 around a second time. */
2721 if (EQ (next_window, last_window))
2726 next_window = Fnext_window (next_window,
2730 /* Now we can safely delete the frame. */
2731 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2734 /* If we're deleting the buffer displayed in
2735 the only window on the frame, find a new
2736 buffer to display there. */
2737 if (NILP (p->parent))
2739 Lisp_Object new_buffer;
2740 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2741 if (NILP (new_buffer))
2742 new_buffer = Fget_buffer_create (QSscratch);
2743 Fset_window_buffer (w, new_buffer, Qnil);
2744 if (EQ (w, Fselected_window (Qnil)))
2745 Fset_buffer (p->buffer);
2748 Fdelete_window (w, Qnil);
2753 case GET_LARGEST_WINDOW:
2755 /* Ignore dedicated windows and minibuffers. */
2756 if (MINI_WINDOW_P (p)
2757 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2760 /* write the check as follows to avoid tripping
2761 error_check_window() --ben */
2762 struct window *b = NILP (best_window) ? 0 :
2763 XWINDOW (best_window);
2764 if (NILP (best_window)
2765 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2766 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2776 if (EQ (w, last_window))
2783 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2786 #if 0 /* not currently used */
2789 buffer_window_count (struct buffer *b, struct frame *f)
2791 Lisp_Object buffer, frame;
2793 XSETFRAME (frame, f);
2794 XSETBUFFER (buffer, b);
2796 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2801 buffer_window_mru (struct window *w)
2803 Lisp_Object window =
2804 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2808 else if (XWINDOW (window) == w)
2817 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2818 Return the window least recently selected or used for display.
2820 By default, only the windows in the selected frame are considered.
2821 The optional argument WHICH-FRAMES changes this behavior:
2822 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2823 If WHICH-FRAMES is 0, search all visible and iconified frames.
2824 If WHICH-FRAMES is t, search all frames.
2825 If WHICH-FRAMES is nil, search only the selected frame.
2826 If WHICH-FRAMES is a frame, search only that frame.
2828 The optional argument WHICH-DEVICES further clarifies on which devices
2829 to search for frames as specified by WHICH-FRAMES. This value is only
2830 meaningful if WHICH-FRAMES is non-nil.
2831 If nil or omitted, search all devices on the selected console.
2832 If a device, only search that device.
2833 If a console, search all devices on that console.
2834 If a device type, search all devices of that type.
2835 If `window-system', search all devices on window-system consoles.
2836 Any other non-nil value means search all devices.
2838 (which_frames, which_devices))
2841 /* First try for a non-dedicated window that is full-width */
2842 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2843 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2846 /* Then try for any non-dedicated window */
2847 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices);
2848 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2852 /* FSFmacs never returns a dedicated window here. If we do,
2853 it makes `display-buffer' not work right. #### All of this
2854 shit is so disgusting and awful that it needs to be rethought
2856 /* then try for a dedicated window that is full-width */
2857 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2858 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2861 /* If none of them, then all windows, dedicated or not. */
2862 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
2864 /* At this point we damn well better have found something. */
2865 if (NILP (w)) abort ();
2871 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2872 Return the window largest in area.
2874 By default, only the windows in the selected frame are considered.
2875 The optional argument WHICH-FRAMES changes this behavior:
2876 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2877 If WHICH-FRAMES is 0, search all visible and iconified frames.
2878 If WHICH-FRAMES is t, search all frames.
2879 If WHICH-FRAMES is nil, search only the selected frame.
2880 If WHICH-FRAMES is a frame, search only that frame.
2882 The optional argument WHICH-DEVICES further clarifies on which devices
2883 to search for frames as specified by WHICH-FRAMES. This value is only
2884 meaningful if WHICH-FRAMES is non-nil.
2885 If nil or omitted, search all devices on the selected console.
2886 If a device, only search that device.
2887 If a console, search all devices on that console.
2888 If a device type, search all devices of that type.
2889 If `window-system', search all devices on window-system consoles.
2890 Any other non-nil value means search all devices.
2892 (which_frames, which_devices))
2894 /* Don't search dedicated windows because FSFmacs doesn't.
2895 This stuff is all black magic so don't try to apply common
2897 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2898 which_frames, 0, which_devices);
2901 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2902 Return a window currently displaying BUFFER, or nil if none.
2904 By default, only the windows in the selected frame are considered.
2905 The optional argument WHICH-FRAMES changes this behavior:
2906 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2907 If WHICH-FRAMES is 0, search all visible and iconified frames.
2908 If WHICH-FRAMES is t, search all frames.
2909 If WHICH-FRAMES is nil, search only the selected frame.
2910 If WHICH-FRAMES is a frame, search only that frame.
2912 The optional argument WHICH-DEVICES further clarifies on which devices
2913 to search for frames as specified by WHICH-FRAMES. This value is only
2914 meaningful if WHICH-FRAMES is non-nil.
2915 If nil or omitted, search all devices on the selected console.
2916 If a device, only search that device.
2917 If a console, search all devices on that console.
2918 If a device type, search all devices of that type.
2919 If `window-system', search all devices on window-system consoles.
2920 Any other non-nil value means search all devices.
2922 (buffer, which_frames, which_devices))
2924 buffer = Fget_buffer (buffer);
2925 if (BUFFERP (buffer))
2926 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2927 return window_loop (GET_BUFFER_WINDOW, buffer, 1,
2928 which_frames, 1, which_devices);
2933 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2934 but there is no sensible way to implement those functions, since
2935 you can't in general derive a window from a buffer. */
2937 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2939 Return the width in pixels of the left outside margin of window WINDOW.
2940 If WINDOW is nil, the selected window is assumed.
2944 return make_int (window_left_margin_width (decode_window (window)));
2947 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2949 Return the width in pixels of the right outside margin of window WINDOW.
2950 If WINDOW is nil, the selected window is assumed.
2954 return make_int (window_right_margin_width (decode_window (window)));
2957 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2958 Make WINDOW (or the selected window) fill its frame.
2959 Only the frame WINDOW is on is affected.
2960 This function tries to reduce display jumps
2961 by keeping the text previously visible in WINDOW
2962 in the same place on the frame. Doing this depends on
2963 the value of (window-start WINDOW), so if calling this function
2964 in a program gives strange scrolling, make sure the window-start
2965 value is reasonable when this function is called.
2969 struct window *w = decode_window (window);
2970 struct buffer *b = XBUFFER (w->buffer);
2972 int old_top = WINDOW_TOP (w);
2974 XSETWINDOW (window, w);
2976 if (MINI_WINDOW_P (w) && old_top > 0)
2977 error ("Can't expand minibuffer to full frame");
2979 /* Ignore dedicated windows. */
2980 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2982 start_pos = marker_position (w->start[CURRENT_DISP]);
2984 /* Try to minimize scrolling, by setting the window start to the
2985 point which will cause the text at the old window start to be at
2986 the same place on the frame. But don't try to do this if the
2987 window start is outside the visible portion (as might happen when
2988 the display is not current, due to typeahead). */
2989 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2990 && !MINI_WINDOW_P (w))
2992 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2994 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2996 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2998 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3000 /* We need to do this, so that the window-scroll-functions
3008 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3009 "bDelete windows on (buffer): ", /*
3010 Delete all windows showing BUFFER.
3012 Optional second argument WHICH-FRAMES controls which frames are affected.
3013 If nil or omitted, delete all windows showing BUFFER in any frame.
3014 If t, delete only windows showing BUFFER in the selected frame.
3015 If `visible', delete all windows showing BUFFER in any visible frame.
3016 If a frame, delete only windows showing BUFFER in that frame.
3017 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3018 except that the meanings of nil and t are reversed.
3020 The optional third argument WHICH-DEVICES further clarifies on which
3021 devices to search for frames as specified by WHICH-FRAMES. This value
3022 is only meaningful if WHICH-FRAMES is not t.
3023 If nil or omitted, search only the selected console.
3024 If a device, only search that device.
3025 If a console, search all devices on that console.
3026 If a device type, search all devices of that type.
3027 If `window-system', search all devices on a window system.
3028 Any other non-nil value means search all devices.
3030 (buffer, which_frames, which_devices))
3032 /* This function can GC */
3033 buffer = Fget_buffer (buffer);
3034 CHECK_BUFFER (buffer);
3036 /* WHICH-FRAMES values t and nil mean the opposite of what
3037 window_loop expects. */
3038 if (EQ (which_frames, Qnil))
3040 else if (EQ (which_frames, Qt))
3041 which_frames = Qnil;
3043 /* Ignore dedicated windows. */
3044 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0,
3045 which_frames, 0, which_devices);
3050 list_windows (struct window *w, Lisp_Object value)
3054 if (!NILP (w->hchild))
3055 value = list_windows (XWINDOW (w->hchild), value);
3056 else if (!NILP (w->vchild))
3057 value = list_windows (XWINDOW (w->vchild), value);
3061 XSETWINDOW (window, w);
3062 value = Fcons (window, value);
3066 w = XWINDOW (w->next);
3072 list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec)
3074 Lisp_Object devcons, concons;
3075 Lisp_Object retval = Qnil;
3077 DEVICE_LOOP_NO_BREAK (devcons, concons)
3079 Lisp_Object frame_list, the_window;
3080 Lisp_Object device, tail;
3082 device = XCAR (devcons);
3083 frame_list = DEVICE_FRAME_LIST (XDEVICE (device));
3085 LIST_LOOP (tail, frame_list)
3087 if ((NILP (frame_spec)
3088 && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device))))
3089 || (EQ (frame_spec, Qvisible)
3090 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail))))
3091 || (FRAMEP (frame_spec)
3092 && !EQ (frame_spec, XCAR (tail)))
3093 || (!NILP (frame_spec)
3094 && !device_matches_device_spec (device,
3095 NILP (device_spec) ?
3099 the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail)));
3100 retval = list_windows (XWINDOW (the_window), retval);
3103 return Fnreverse (retval);
3106 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3,
3107 "bReplace buffer in windows: ", /*
3108 Replace BUFFER with some other buffer in all windows showing it.
3110 Optional second argument WHICH-FRAMES controls which frames are affected.
3111 If nil or omitted, all frames are affected.
3112 If t, only the selected frame is affected.
3113 If `visible', all visible frames are affected.
3114 If a frame, only that frame is affected.
3115 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3116 except that the meanings of nil and t are reversed.
3118 The optional third argument WHICH-DEVICES further clarifies on which
3119 devices to search for frames as specified by WHICH-FRAMES. This value
3120 is only meaningful if WHICH-FRAMES is not t.
3121 If nil or omitted, search only the selected console.
3122 If a device, only search that device.
3123 If a console, search all devices on that console.
3124 If a device type, search all devices of that type.
3125 If `window-system', search all devices on a window system.
3126 Any other non-nil value means search all devices.
3128 (buffer, which_frames, which_devices))
3130 /* This function can GC */
3131 Lisp_Object window_list;
3133 struct gcpro gcpro1, gcpro2;
3135 if (EQ (which_frames, Qnil))
3137 else if (EQ (which_frames, Qt))
3138 which_frames = Qnil;
3139 window_list = list_all_windows (which_frames, which_devices);
3141 buffer = Fget_buffer (buffer);
3142 CHECK_BUFFER (buffer);
3144 GCPRO2 (window_list, buffer);
3145 LIST_LOOP (tail, window_list)
3147 Lisp_Object window = XCAR (tail);
3148 if (!MINI_WINDOW_P (XWINDOW (window))
3149 && EQ (XWINDOW (window)->buffer, buffer))
3151 Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil);
3152 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
3153 if (NILP (another_buffer))
3154 another_buffer = Fget_buffer_create (QSscratch);
3155 if (!NILP (XWINDOW (window)->dedicated)
3157 FRAME_ROOT_WINDOW (XFRAME (frame)))
3158 && other_visible_frames (XFRAME (frame)))
3160 delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */
3164 Fset_window_buffer (window, another_buffer, Qnil);
3165 if (EQ (window, Fselected_window (Qnil)))
3166 Fset_buffer (XWINDOW (window)->buffer);
3174 /* The smallest acceptable dimensions for a window. Anything smaller
3175 might crash Emacs. */
3176 #define MIN_SAFE_WINDOW_WIDTH (2)
3177 #define MIN_SAFE_WINDOW_HEIGHT (2)
3179 /* Make sure that window_min_height and window_min_width are
3180 not too small; if they are, set them to safe minima. */
3183 check_min_window_sizes (void)
3185 /* Smaller values might permit a crash. */
3186 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3187 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3188 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3189 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3193 frame_min_height (struct frame *frame)
3195 /* For height, we have to see whether the frame has a minibuffer, and
3196 whether it wants a modeline. */
3197 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3198 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3199 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3202 /* Return non-zero if both frame sizes are less than or equal to
3203 minimal allowed values. ROWS and COLS are in characters */
3205 frame_size_valid_p (struct frame *frame, int rows, int cols)
3207 return (rows >= frame_min_height (frame)
3208 && cols >= MIN_SAFE_WINDOW_WIDTH);
3211 /* Return non-zero if both frame sizes are less than or equal to
3212 minimal allowed values. WIDTH and HEIGHT are in pixels */
3214 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3217 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3218 return frame_size_valid_p (frame, rows, cols);
3221 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3222 minimum allowable size. */
3224 check_frame_size (struct frame *frame, int *rows, int *cols)
3226 int min_height = frame_min_height (frame);
3228 if (*rows < min_height)
3230 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3231 *cols = MIN_SAFE_WINDOW_WIDTH;
3234 /* Normally the window is deleted if it gets too small.
3235 nodelete nonzero means do not do this.
3236 (The caller should check later and do so if appropriate) */
3238 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3241 struct window *w = XWINDOW (window);
3242 struct frame *f = XFRAME (w->frame);
3244 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3245 Lisp_Object child, minor_kid, major_kid;
3248 int defheight, defwidth;
3250 /* #### This is very likely incorrect and instead the char_to_pixel_
3251 functions should be called. */
3252 default_face_height_and_width (window, &defheight, &defwidth);
3253 line_size = (set_height ? defheight : defwidth);
3255 check_min_window_sizes ();
3257 minsize = (set_height ? window_min_height : window_min_width);
3258 minsize *= line_size;
3261 && !TOP_LEVEL_WINDOW_P (w)
3262 && new_pixsize < minsize)
3264 Fdelete_window (window, Qnil);
3268 SET_LAST_MODIFIED (w, 0);
3269 SET_LAST_FACECHANGE (w);
3270 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3273 WINDOW_HEIGHT (w) = new_pixsize;
3274 major_kid = w->vchild;
3275 minor_kid = w->hchild;
3279 WINDOW_WIDTH (w) = new_pixsize;
3280 major_kid = w->hchild;
3281 minor_kid = w->vchild;
3284 if (!NILP (minor_kid))
3286 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3289 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3291 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3293 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3296 else if (!NILP (major_kid))
3298 int last_pos, last_old_pos, pos, old_pos, first;
3299 int pixel_adj_left = new_pixsize - old_pixsize;
3300 int div_val = old_pixsize << 1;
3303 * Previously we bailed out here if there was no size change.
3304 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3305 * toolbar appears or disappears, windows may not change size,
3306 * but their top and left coordinates need to be updated.
3308 * So we don't bail until after the loop below.
3311 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3314 for (child = major_kid; !NILP (child); child = c->next)
3316 c = XWINDOW (child);
3320 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3321 WINDOW_TOP (c) = last_pos;
3325 old_pos = last_old_pos + WINDOW_WIDTH (c);
3326 WINDOW_LEFT (c) = last_pos;
3329 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3330 /* All but the last window should have a height which is
3331 a multiple of the default line height. */
3332 if (!NILP (c->next))
3333 pos = (pos / line_size) * line_size;
3335 /* Avoid confusion: don't delete child if it becomes too small */
3336 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3338 last_pos = pos + first;
3339 last_old_pos = old_pos;
3342 /* Sometimes we may get called with our old size. In that case
3343 we don't need to do anything else. */
3344 if (!pixel_adj_left)
3347 /* Now delete any children that became too small. */
3349 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3352 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3354 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3359 /* Set the height of WINDOW and all its inferiors. */
3361 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3363 set_window_pixsize (window, new_pixheight, nodelete, 1);
3366 /* Recursively set width of WINDOW and its inferiors. */
3368 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3370 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3374 static int window_select_count;
3376 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3377 Make WINDOW display BUFFER as its contents.
3378 BUFFER can be a buffer or buffer name.
3380 With non-nil optional argument NORECORD, do not modify the
3381 global or per-frame buffer ordering.
3383 (window, buffer, norecord))
3386 struct window *w = decode_window (window);
3387 int old_buffer_local_face_property = 0;
3389 buffer = Fget_buffer (buffer);
3390 CHECK_BUFFER (buffer);
3392 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3393 error ("Attempt to display deleted buffer");
3397 error ("Window is deleted");
3399 /* While this seems like a logical thing to do, it causes problems
3400 because of saved window configurations. It is possible for a
3401 buffer to get restored into a window in which it is already being
3402 displayed, but start and point are actually at completely
3403 different locations. So we let this function complete fully and
3404 it will then make sure redisplay correctly updates things.
3406 #### This is a kludge. The correct approach is not to do this
3407 but to fix set-window-configuration. */
3409 else if (EQ (tem, buffer))
3412 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3413 is first being set up. */
3415 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3416 error ("Window is dedicated to buffer %s",
3417 XSTRING_DATA (XBUFFER (tem)->name));
3419 old_buffer_local_face_property =
3420 XBUFFER (w->buffer)->buffer_local_face_property;
3425 w->window_end_pos[CURRENT_DISP] = 0;
3427 w->modeline_hscroll = 0;
3428 Fset_marker (w->pointm[CURRENT_DISP],
3429 make_int (BUF_PT (XBUFFER (buffer))),
3431 set_marker_restricted (w->start[CURRENT_DISP],
3432 make_int (XBUFFER (buffer)->last_window_start),
3434 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3435 /* set start_at_line_beg correctly. GE */
3436 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3437 marker_position (w->start[CURRENT_DISP]));
3438 w->force_start = 0; /* Lucid fix */
3439 SET_LAST_MODIFIED (w, 1);
3440 SET_LAST_FACECHANGE (w);
3441 MARK_WINDOWS_CHANGED (w);
3443 int new_buffer_local_face_property =
3444 XBUFFER (w->buffer)->buffer_local_face_property;
3446 if (new_buffer_local_face_property
3447 || new_buffer_local_face_property != old_buffer_local_face_property)
3448 MARK_WINDOW_FACES_CHANGED (w);
3450 recompute_all_cached_specifiers_in_window (w);
3451 if (EQ (window, Fselected_window (Qnil)))
3453 if (NILP (norecord))
3454 Frecord_buffer (buffer);
3456 Fset_buffer (buffer);
3461 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3462 Select WINDOW. Most editing will apply to WINDOW's buffer.
3463 The main editor command loop selects the buffer of the selected window
3464 before each command.
3466 With non-nil optional argument NORECORD, do not modify the
3467 global or per-frame buffer ordering.
3472 Lisp_Object old_selected_window = Fselected_window (Qnil);
3474 CHECK_LIVE_WINDOW (window);
3475 w = XWINDOW (window);
3477 /* we have already caught dead-window errors */
3478 if (!NILP (w->hchild) || !NILP (w->vchild))
3479 error ("Trying to select non-leaf window");
3481 w->use_time = make_int (++window_select_count);
3483 if (EQ (window, old_selected_window))
3486 /* deselect the old window, if it exists (it might not exist if
3487 the selected device has no frames, which occurs at startup) */
3488 if (!NILP (old_selected_window))
3490 struct window *ow = XWINDOW (old_selected_window);
3492 Fset_marker (ow->pointm[CURRENT_DISP],
3493 make_int (BUF_PT (XBUFFER (ow->buffer))),
3496 MARK_WINDOWS_CHANGED (ow);
3499 /* now select the window's frame */
3500 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3502 select_frame_1 (WINDOW_FRAME (w));
3504 /* also select the window's buffer */
3505 if (NILP (norecord))
3506 Frecord_buffer (w->buffer);
3507 Fset_buffer (w->buffer);
3509 /* Go to the point recorded in the window.
3510 This is important when the buffer is in more
3511 than one window. It also matters when
3512 redisplay_window has altered point after scrolling,
3513 because it makes the change only in the window. */
3515 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3516 if (new_point < BUF_BEGV (current_buffer))
3517 new_point = BUF_BEGV (current_buffer);
3518 else if (new_point > BUF_ZV (current_buffer))
3519 new_point = BUF_ZV (current_buffer);
3521 BUF_SET_PT (current_buffer, new_point);
3524 MARK_WINDOWS_CHANGED (w);
3530 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3531 Lisp_Object override_frame)
3533 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3537 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3539 /* This function can GC */
3542 struct buffer *b = XBUFFER (buf);
3544 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3545 widen_buffer (b, 0);
3546 BUF_SET_PT (b, BUF_BEG (b));
3548 if (!NILP (Vtemp_buffer_show_function))
3549 call1 (Vtemp_buffer_show_function, buf);
3552 window = display_buffer (buf, Qnil, same_frame);
3554 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3555 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3557 Vminibuffer_scroll_window = window;
3558 w = XWINDOW (window);
3560 w->modeline_hscroll = 0;
3561 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3562 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3563 set_marker_restricted (w->sb_point, make_int (1), buf);
3565 /* Run temp-buffer-show-hook, with the chosen window selected. */
3566 if (!preparing_for_armageddon)
3569 tem = Fboundp (Qtemp_buffer_show_hook);
3572 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3575 int count = specpdl_depth ();
3577 /* Select the window that was chosen, for running
3579 record_unwind_protect (save_window_excursion_unwind,
3580 Fcurrent_window_configuration (Qnil));
3582 Fselect_window (window, Qnil);
3583 run_hook (Qtemp_buffer_show_hook);
3584 unbind_to (count, Qnil);
3592 make_dummy_parent (Lisp_Object window)
3595 struct window *o = XWINDOW (window);
3596 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3598 XSETWINDOW (new, p);
3599 copy_lcrecord (p, o);
3601 /* Don't copy the pointers to the line start cache or the face
3603 p->line_start_cache = Dynarr_new (line_start_cache);
3604 p->face_cachels = Dynarr_new (face_cachel);
3605 p->glyph_cachels = Dynarr_new (glyph_cachel);
3606 p->subwindow_instance_cache =
3607 make_lisp_hash_table (30,
3608 HASH_TABLE_KEY_VALUE_WEAK,
3611 /* Put new into window structure in place of window */
3612 replace_window (window, new);
3620 p->start[CURRENT_DISP] = Qnil;
3621 p->start[DESIRED_DISP] = Qnil;
3622 p->start[CMOTION_DISP] = Qnil;
3623 p->pointm[CURRENT_DISP] = Qnil;
3624 p->pointm[DESIRED_DISP] = Qnil;
3625 p->pointm[CMOTION_DISP] = Qnil;
3630 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3631 Split WINDOW, putting SIZE lines in the first of the pair.
3632 WINDOW defaults to the selected one and SIZE to half its size.
3633 If optional third arg HORFLAG is non-nil, split side by side
3634 and put SIZE columns in the first of the pair.
3636 (window, size, horflag))
3639 struct window *o, *p;
3645 window = Fselected_window (Qnil);
3647 CHECK_LIVE_WINDOW (window);
3649 o = XWINDOW (window);
3650 f = XFRAME (WINDOW_FRAME (o));
3654 if (!NILP (horflag))
3655 /* In the new scheme, we are symmetric with respect to separators
3656 so there is no need to do weird things here. */
3658 psize = WINDOW_WIDTH (o) >> 1;
3659 csize = window_pixel_width_to_char_width (o, psize, 0);
3663 psize = WINDOW_HEIGHT (o) >> 1;
3664 csize = window_pixel_height_to_char_height (o, psize, 1);
3670 csize = XINT (size);
3671 if (!NILP (horflag))
3672 psize = window_char_width_to_pixel_width (o, csize, 0);
3674 psize = window_char_height_to_pixel_height (o, csize, 1);
3677 if (MINI_WINDOW_P (o))
3678 error ("Attempt to split minibuffer window");
3679 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3680 error ("Attempt to split unsplittable frame");
3682 check_min_window_sizes ();
3686 if (csize < window_min_height)
3687 error ("Window height %d too small (after splitting)", csize);
3688 if (csize + window_min_height > window_char_height (o, 1))
3689 error ("Window height %d too small (after splitting)",
3690 window_char_height (o, 1) - csize);
3691 if (NILP (o->parent)
3692 || NILP (XWINDOW (o->parent)->vchild))
3694 make_dummy_parent (window);
3696 /* #### I can't understand why you have to reset face
3697 cachels here. This can cause crash so let's disable it
3698 and see the difference. See redisplay-tests.el --yh */
3699 reset_face_cachels (XWINDOW (window));
3702 XWINDOW (new)->vchild = window;
3703 XFRAME (o->frame)->mirror_dirty = 1;
3708 if (csize < window_min_width)
3709 error ("Window width %d too small (after splitting)", csize);
3710 if (csize + window_min_width > window_char_width (o, 0))
3711 error ("Window width %d too small (after splitting)",
3712 window_char_width (o, 0) - csize);
3713 if (NILP (o->parent)
3714 || NILP (XWINDOW (o->parent)->hchild))
3716 make_dummy_parent (window);
3718 /* #### See above. */
3719 reset_face_cachels (XWINDOW (window));
3722 XWINDOW (new)->hchild = window;
3723 XFRAME (o->frame)->mirror_dirty = 1;
3727 /* Now we know that window's parent is a vertical combination
3728 if we are dividing vertically, or a horizontal combination
3729 if we are making side-by-side windows */
3731 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3732 new = allocate_window ();
3735 p->frame = o->frame;
3737 if (!NILP (p->next))
3738 XWINDOW (p->next)->prev = new;
3741 p->parent = o->parent;
3744 reset_face_cachels (p);
3745 reset_glyph_cachels (p);
3748 /* Apportion the available frame space among the two new windows */
3750 if (!NILP (horflag))
3752 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3753 WINDOW_TOP (p) = WINDOW_TOP (o);
3754 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3755 WINDOW_WIDTH (o) = psize;
3756 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3760 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3761 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3762 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3763 WINDOW_HEIGHT (o) = psize;
3764 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3767 XFRAME (p->frame)->mirror_dirty = 1;
3768 /* do this last (after the window is completely initialized and
3769 the mirror-dirty flag is set) so that specifier recomputation
3770 caused as a result of this will work properly and not abort. */
3771 Fset_window_buffer (new, o->buffer, Qt);
3776 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3777 Make the selected window COUNT lines taller.
3778 From program, optional second arg HORIZONTALP non-nil means grow
3779 sideways COUNT columns, and optional third arg WINDOW specifies the
3780 window to change instead of the selected window.
3782 (count, horizontalp, window))
3785 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0);
3789 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3790 Make the selected window COUNT pixels taller.
3791 From program, optional second arg HORIZONTALP non-nil means grow
3792 sideways COUNT pixels, and optional third arg WINDOW specifies the
3793 window to change instead of the selected window.
3795 (count, horizontalp, window))
3798 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1);
3802 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3803 Make the selected window COUNT lines shorter.
3804 From program, optional second arg HORIZONTALP non-nil means shrink
3805 sideways COUNT columns, and optional third arg WINDOW specifies the
3806 window to change instead of the selected window.
3808 (count, horizontalp, window))
3811 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0);
3815 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3816 Make the selected window COUNT pixels smaller.
3817 From program, optional second arg HORIZONTALP non-nil means shrink
3818 sideways COUNT pixels, and optional third arg WINDOW specifies the
3819 window to change instead of the selected window.
3821 (count, horizontalp, window))
3824 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1);
3829 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3830 int include_gutters_p)
3833 int defheight, defwidth;
3837 XSETWINDOW (window, w);
3839 avail_height = (pixel_height -
3840 (include_gutters_p ? 0 :
3841 window_top_window_gutter_height (w) +
3842 window_bottom_window_gutter_height (w)));
3844 default_face_height_and_width (window, &defheight, &defwidth);
3846 char_height = avail_height / defheight;
3848 /* It's the calling function's responsibility to check these values
3849 and make sure they're not out of range.
3851 #### We need to go through the calling functions and actually
3853 return max (0, char_height);
3857 window_char_height_to_pixel_height (struct window *w, int char_height,
3858 int include_gutters_p)
3861 int defheight, defwidth;
3866 XSETWINDOW (window, w);
3868 default_face_height_and_width (window, &defheight, &defwidth);
3870 avail_height = char_height * defheight;
3871 pixel_height = (avail_height +
3872 (include_gutters_p ? 0 :
3873 window_top_window_gutter_height (w) +
3874 window_bottom_window_gutter_height (w)));
3876 /* It's the calling function's responsibility to check these values
3877 and make sure they're not out of range.
3879 #### We need to go through the calling functions and actually
3881 return max (0, pixel_height);
3884 /* Return number of default lines of text can fit in the window W.
3885 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3886 horizontal scrollbar) in the space that is used for the calculation.
3887 This doesn't include space used by the frame gutters.
3890 window_char_height (struct window *w, int include_gutters_p)
3892 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3897 * Return number of lines currently displayed in window w. If
3898 * end-of-buffer is displayed then the area below end-of-buffer is assume
3899 * to be blank lines of default height.
3900 * Does not include the modeline.
3903 window_displayed_height (struct window *w)
3905 struct buffer *b = XBUFFER (w->buffer);
3906 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3908 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3910 : w->window_end_pos[CURRENT_DISP]);
3912 if (!Dynarr_length (dla))
3913 return window_char_height (w, 0);
3915 num_lines = Dynarr_length (dla);
3917 /* #### Document and assert somewhere that w->window_end_pos == -1
3918 indicates that end-of-buffer is being displayed. */
3921 struct display_line *dl = Dynarr_atp (dla, 0);
3922 int ypos1 = dl->ypos + dl->descent;
3923 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3925 int defheight, defwidth;
3927 XSETWINDOW (window, w);
3933 if (Dynarr_length (dla) == 1)
3934 ypos1 = WINDOW_TEXT_TOP (w);
3937 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3938 /* If this line is clipped then we know that there is no
3939 blank room between eob and the modeline. If we are
3940 scrolling on clipped lines just know off the clipped
3942 if (scroll_on_clipped_lines && dl->clip)
3943 return num_lines - 1;
3944 ypos1 = dl->ypos + dl->descent - dl->clip;
3948 default_face_height_and_width (window, &defheight, &defwidth);
3949 /* #### This probably needs to know about the clipping area once a
3950 final definition is decided on. */
3951 num_lines += ((ypos2 - ypos1) / defheight);
3955 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3958 if (scroll_on_clipped_lines
3959 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3967 window_pixel_width (Lisp_Object window)
3969 return WINDOW_WIDTH (XWINDOW (window));
3972 /* Calculate the pixel of a window, optionally including margin space
3973 but no vertical gutters. */
3975 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3976 int include_margins_p)
3980 int defheight, defwidth;
3983 XSETWINDOW (window, w);
3985 avail_width = (pixel_width -
3986 window_left_gutter_width (w, 0) -
3987 window_right_gutter_width (w, 0) -
3988 (include_margins_p ? 0 : window_left_margin_width (w)) -
3989 (include_margins_p ? 0 : window_right_margin_width (w)));
3991 default_face_height_and_width (window, &defheight, &defwidth);
3993 char_width = (avail_width / defwidth);
3995 /* It's the calling function's responsibility to check these values
3996 and make sure they're not out of range.
3998 #### We need to go through the calling functions and actually
4000 return max (0, char_width);
4004 window_char_width_to_pixel_width (struct window *w, int char_width,
4005 int include_margins_p)
4009 int defheight, defwidth;
4012 XSETWINDOW (window, w);
4014 default_face_height_and_width (window, &defheight, &defwidth);
4016 avail_width = char_width * defwidth;
4017 pixel_width = (avail_width +
4018 window_left_window_gutter_width (w, 0) +
4019 window_right_window_gutter_width (w, 0) +
4020 (include_margins_p ? 0 : window_left_margin_width (w)) +
4021 (include_margins_p ? 0 : window_right_margin_width (w)));
4023 /* It's the calling function's responsibility to check these values
4024 and make sure they're not out of range.
4026 #### We need to go through the calling functions and actually
4028 return max (0, pixel_width);
4031 /* This returns the usable space which doesn't include space needed by
4032 scrollbars or divider lines. */
4034 window_char_width (struct window *w, int include_margins_p)
4036 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
4040 #define MINSIZE(w) \
4042 ? window_min_width * defwidth \
4043 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4046 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4048 #define CURSIZE(w) \
4049 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4051 #define CURCHARSIZE(w) \
4052 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4054 #define MINCHARSIZE(window) \
4055 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4056 ? 1 : window_min_height)
4059 window_pixheight (Lisp_Object w)
4061 return window_pixel_height (XWINDOW (w));
4064 /* Unlike set_window_pixheight, this function
4065 also changes the heights of the siblings so as to
4066 keep everything consistent. */
4069 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp,
4072 struct window *win = decode_window (window);
4073 int widthflag = !NILP (horizontalp);
4078 int (*sizefun) (Lisp_Object) = (widthflag
4079 ? window_pixel_width
4080 : window_pixheight);
4081 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4082 ? set_window_pixwidth
4083 : set_window_pixheight);
4085 int defheight, defwidth;
4090 check_min_window_sizes ();
4092 XSETWINDOW (window, win);
4093 f = XFRAME (win->frame);
4094 if (EQ (window, FRAME_ROOT_WINDOW (f)))
4095 error ("Won't change only window");
4097 /* #### This is very likely incorrect and instead the char_to_pixel_
4098 functions should be called. */
4099 default_face_height_and_width (window, &defheight, &defwidth);
4103 w = XWINDOW (window);
4108 error ("No other window to side of this one");
4112 ? !NILP (XWINDOW (parent)->hchild)
4113 : !NILP (XWINDOW (parent)->vchild))
4118 sizep = &CURSIZE (w);
4119 dim = CURCHARSIZE (w);
4121 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4122 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4124 if (MINI_WINDOW_P (XWINDOW (window)))
4126 else if (!NILP (parent))
4128 Fdelete_window (window, Qnil);
4134 delta *= (widthflag ? defwidth : defheight);
4139 maxdelta = ((!NILP (parent))
4140 ? (*sizefun) (parent) - *sizep
4141 : ((!NILP (w->next))
4142 ? (*sizefun) (w->next) - MINSIZE (w->next)
4143 : ((!NILP (w->prev))
4144 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4145 /* This is a frame with only one window,
4146 a minibuffer-only or a minibufferless frame. */
4149 if (delta > maxdelta)
4150 /* This case traps trying to make the minibuffer
4151 the full frame, or make the only window aside from the
4152 minibuffer the full frame. */
4159 /* #### Chuck: is this correct? */
4160 if (*sizep + delta < MINSIZE (window))
4162 Fdelete_window (window);
4168 if (!NILP (w->next) &&
4169 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4171 CURBEG (XWINDOW (w->next)) += delta;
4172 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4173 (*setsizefun) (window, *sizep + delta, 0);
4175 else if (!NILP (w->prev) &&
4176 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4178 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4179 CURBEG (w) -= delta;
4180 (*setsizefun) (window, *sizep + delta, 0);
4185 int opht = (*sizefun) (parent);
4187 /* If trying to grow this window to or beyond size of the parent,
4188 make delta1 so big that, on shrinking back down,
4189 all the siblings end up with less than one line and are deleted. */
4190 if (opht <= *sizep + delta)
4191 delta1 = opht * opht * 2;
4192 /* Otherwise, make delta1 just right so that if we add delta1
4193 lines to this window and to the parent, and then shrink
4194 the parent back to its original size, the new proportional
4195 size of this window will increase by delta. */
4197 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4199 /* Add delta1 lines or columns to this window, and to the parent,
4200 keeping things consistent while not affecting siblings. */
4201 CURSIZE (XWINDOW (parent)) = opht + delta1;
4202 (*setsizefun) (window, *sizep + delta1, 0);
4204 /* Squeeze out delta1 lines or columns from our parent,
4205 shrinking this window and siblings proportionately.
4206 This brings parent back to correct size.
4207 Delta1 was calculated so this makes this window the desired size,
4208 taking it all out of the siblings. */
4209 (*setsizefun) (parent, opht, 0);
4212 SET_LAST_MODIFIED (w, 0);
4213 SET_LAST_FACECHANGE (w);
4214 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4215 /* overkill maybe, but better to be correct */
4216 MARK_FRAME_GUTTERS_CHANGED (f);
4226 /* Scroll contents of window WINDOW up COUNT lines.
4227 If COUNT < (top line height / average line height) then we just adjust
4230 window_scroll (Lisp_Object window, Lisp_Object count, int direction,
4231 Error_behavior errb)
4233 struct window *w = XWINDOW (window);
4234 struct buffer *b = XBUFFER (w->buffer);
4235 int selected = EQ (window, Fselected_window (Qnil));
4237 Lisp_Object point, tem;
4238 display_line_dynarr *dla;
4239 int fheight, fwidth, modeline = 0;
4240 struct display_line* dl;
4243 point = make_int (BUF_PT (b));
4246 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4248 if (pos < BUF_BEGV (b))
4250 else if (pos > BUF_ZV (b))
4253 point = make_int (pos);
4256 /* Always set force_start so that redisplay_window will run
4257 the window-scroll-functions. */
4260 /* #### When the fuck does this happen? I'm so glad that history has
4261 completely documented the behavior of the scrolling functions under
4262 all circumstances. */
4263 tem = Fpos_visible_in_window_p (point, window);
4266 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4268 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4269 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4270 WINDOW_TEXT_TOP_CLIP (w) = 0;
4271 MARK_WINDOWS_CHANGED (w);
4276 if (EQ (count, Qminus))
4280 count = Fprefix_numeric_value (count);
4281 value = XINT (count) * direction;
4284 return; /* someone just made a pointless call */
4288 /* If the user didn't specify how far to scroll then we have to figure it
4289 out by ourselves. */
4290 if (NILP (count) || EQ (count, Qminus))
4292 /* Going forwards is easy. If that is what we are doing then just
4293 set value and the section which handles the user specifying a
4294 positive value will work. */
4297 value = window_displayed_height (w) - next_screen_context_lines;
4298 value = (value < 1 ? 1 : value);
4301 /* Going backwards is hard. We can't use the same loop used if the
4302 user specified a negative value because we care about
4303 next_screen_context_lines. In a variable height world you don't
4304 know how many lines above you can actually be displayed and still
4305 have the context lines appear. So we leave value set to 0 and add
4306 a separate section to deal with this. */
4310 if (direction == 1 && !value)
4315 /* Determine parameters to test for partial line scrolling with. */
4316 dla = window_display_lines (w, CURRENT_DISP);
4318 if (INTP (Vwindow_pixel_scroll_increment))
4319 fheight = XINT (Vwindow_pixel_scroll_increment);
4320 else if (!NILP (Vwindow_pixel_scroll_increment))
4321 default_face_height_and_width (window, &fheight, &fwidth);
4323 if (Dynarr_length (dla) >= 1)
4324 modeline = Dynarr_atp (dla, 0)->modeline;
4326 dl = Dynarr_atp (dla, modeline);
4330 /* Go for partial display line scrolling. This just means bumping
4331 the clip by a reasonable amount and redisplaying, everything else
4332 remains unchanged. */
4333 if (!NILP (Vwindow_pixel_scroll_increment)
4335 Dynarr_length (dla) >= (1 + modeline)
4337 (dl->ascent - dl->top_clip) - fheight * value > 0)
4339 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4340 MARK_WINDOWS_CHANGED (w);
4345 Bufpos startp, old_start;
4347 if (WINDOW_TEXT_TOP_CLIP (w))
4349 WINDOW_TEXT_TOP_CLIP (w) = 0;
4350 MARK_WINDOWS_CHANGED (w);
4353 old_start = marker_position (w->start[CURRENT_DISP]);
4354 startp = vmotion (w, old_start, value, &vtarget);
4356 if (vtarget < value &&
4357 (w->window_end_pos[CURRENT_DISP] == -1
4358 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4360 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4365 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4368 w->start_at_line_beg = beginning_of_line_p (b, startp);
4369 MARK_WINDOWS_CHANGED (w);
4371 if (!point_would_be_visible (w, startp, XINT (point)))
4374 BUF_SET_PT (b, startp);
4376 set_marker_restricted (w->pointm[CURRENT_DISP],
4385 /* Go for partial display line scrolling. This just means bumping
4386 the clip by a reasonable amount and redisplaying, everything else
4387 remains unchanged. */
4388 if (!NILP (Vwindow_pixel_scroll_increment)
4390 Dynarr_length (dla) >= (1 + modeline)
4392 (dl->ascent - dl->top_clip) - fheight * value <
4393 (dl->ascent + dl->descent - dl->clip)
4395 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4397 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4398 MARK_WINDOWS_CHANGED (w);
4403 Bufpos startp, old_start;
4405 if (WINDOW_TEXT_TOP_CLIP (w))
4407 WINDOW_TEXT_TOP_CLIP (w) = 0;
4408 MARK_WINDOWS_CHANGED (w);
4411 old_start = marker_position (w->start[CURRENT_DISP]);
4412 startp = vmotion (w, old_start, value, &vtarget);
4415 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4417 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4422 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4425 w->start_at_line_beg = beginning_of_line_p (b, startp);
4426 MARK_WINDOWS_CHANGED (w);
4428 /* #### Scroll back by less than a line. This code was
4429 originally for scrolling over large pixmaps and it
4430 loses when a line being *exposed* at the top of the
4431 window is bigger than the current one. However, for
4432 pixel based scrolling in general we can guess that
4433 the line we are going to display is probably the same
4434 size as the one we are on. In that instance we can
4435 have a reasonable stab at a suitable top clip. Fixing
4436 this properly is hard (and probably slow) as we would
4437 have to call redisplay to figure out the exposed line
4439 if (!NILP (Vwindow_pixel_scroll_increment)
4440 && Dynarr_length (dla) >= (1 + modeline)
4441 && dl->ascent + fheight * value > 0)
4443 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4446 if (!point_would_be_visible (w, startp, XINT (point)))
4450 if (MINI_WINDOW_P (w))
4453 new_point = start_of_last_line (w, startp);
4456 BUF_SET_PT (b, new_point);
4458 set_marker_restricted (w->pointm[CURRENT_DISP],
4459 make_int (new_point),
4465 else /* value == 0 && direction == -1 */
4467 if (WINDOW_TEXT_TOP_CLIP (w))
4469 WINDOW_TEXT_TOP_CLIP (w) = 0;
4470 MARK_WINDOWS_CHANGED (w);
4472 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4474 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4480 int movement = next_screen_context_lines - 1;
4481 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4482 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4484 start_with_point_on_display_line (w, bottom,
4485 -1 - (movement - vtarget));
4487 if (startp >= old_startp)
4488 startp = vmotion (w, old_startp, -1, NULL);
4490 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4493 w->start_at_line_beg = beginning_of_line_p (b, startp);
4494 MARK_WINDOWS_CHANGED (w);
4496 if (!point_would_be_visible (w, startp, XINT (point)))
4498 Bufpos new_point = start_of_last_line (w, startp);
4501 BUF_SET_PT (b, new_point);
4503 set_marker_restricted (w->pointm[CURRENT_DISP],
4504 make_int (new_point),
4511 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4512 Scroll text of current window up COUNT lines; or near full screen if no arg.
4513 A near full screen is `next-screen-context-lines' less than a full screen.
4514 Negative COUNT means scroll downward.
4515 When calling from a program, supply an integer as argument or nil.
4516 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4517 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4522 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME);
4526 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4527 Scroll text of current window down COUNT lines; or near full screen if no arg.
4528 A near full screen is `next-screen-context-lines' less than a full screen.
4529 Negative COUNT means scroll upward.
4530 When calling from a program, supply a number as argument or nil.
4531 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4532 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4537 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME);
4541 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4542 Return the other window for "other window scroll" commands.
4543 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4544 specifies the window.
4545 If `other-window-scroll-buffer' is non-nil, a window
4546 showing that buffer is used.
4551 Lisp_Object selected_window = Fselected_window (Qnil);
4553 if (MINI_WINDOW_P (XWINDOW (selected_window))
4554 && !NILP (Vminibuffer_scroll_window))
4555 window = Vminibuffer_scroll_window;
4556 /* If buffer is specified, scroll that buffer. */
4557 else if (!NILP (Vother_window_scroll_buffer))
4559 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4561 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4565 /* Nothing specified; look for a neighboring window on the same
4567 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4569 if (EQ (window, selected_window))
4570 /* That didn't get us anywhere; look for a window on another
4573 window = Fnext_window (window, Qnil, Qt, Qnil);
4574 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4575 && ! EQ (window, selected_window));
4578 CHECK_LIVE_WINDOW (window);
4580 if (EQ (window, selected_window))
4581 error ("There is no other window");
4586 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4587 Scroll next window upward COUNT lines; or near full frame if no arg.
4588 The next window is the one below the current one; or the one at the top
4589 if the current one is at the bottom. Negative COUNT means scroll downward.
4590 When calling from a program, supply a number as argument or nil.
4592 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4593 specifies the window to scroll.
4594 If `other-window-scroll-buffer' is non-nil, scroll the window
4595 showing that buffer, popping the buffer up if necessary.
4599 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME);
4603 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4604 Scroll selected window display COUNT columns left.
4605 Default for COUNT is window width minus 2.
4609 Lisp_Object window = Fselected_window (Qnil);
4610 struct window *w = XWINDOW (window);
4611 int n = (NILP (count) ?
4612 window_char_width (w, 0) - 2 :
4613 XINT (Fprefix_numeric_value (count)));
4615 return Fset_window_hscroll (window, make_int (w->hscroll + n));
4618 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4619 Scroll selected window display COUNT columns right.
4620 Default for COUNT is window width minus 2.
4624 Lisp_Object window = Fselected_window (Qnil);
4625 struct window *w = XWINDOW (window);
4626 int n = (NILP (count) ?
4627 window_char_width (w, 0) - 2 :
4628 XINT (Fprefix_numeric_value (count)));
4630 return Fset_window_hscroll (window, make_int (w->hscroll - n));
4633 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4634 Center point in WINDOW. With N, put point on line N.
4635 The desired position of point is always relative to the window.
4636 If WINDOW is nil, the selected window is used.
4640 struct window *w = decode_window (window);
4641 struct buffer *b = XBUFFER (w->buffer);
4642 Bufpos opoint = BUF_PT (b);
4646 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4649 n = Fprefix_numeric_value (n);
4651 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4654 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4656 w->start_at_line_beg = beginning_of_line_p (b, startp);
4658 MARK_WINDOWS_CHANGED (w);
4662 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4663 Position point relative to WINDOW.
4664 With no argument, position text at center of window.
4665 An argument specifies window line; zero means top of window,
4666 negative means relative to bottom of window.
4667 If WINDOW is nil, the selected window is used.
4674 Bufpos start, new_point;
4677 /* Don't use decode_window() because we need the new value of
4680 window = Fselected_window (Qnil);
4682 CHECK_LIVE_WINDOW (window);
4683 w = XWINDOW (window);
4684 b = XBUFFER (w->buffer);
4686 height = window_displayed_height (w);
4687 selected = EQ (window, Fselected_window (w->frame));
4693 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4694 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4696 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4699 BUF_SET_PT (b, new_point);
4701 Fset_window_point (window, make_int (new_point));
4703 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4707 start = marker_position (w->start[CURRENT_DISP]);
4708 if (start < BUF_BEGV (b))
4709 start = BUF_BEGV (b);
4710 else if (start > BUF_ZV (b))
4714 new_point = BUF_PT (b);
4716 new_point = marker_position (w->pointm[CURRENT_DISP]);
4718 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4721 BUF_SET_PT (b, new_point);
4723 Fset_window_point (window, make_int (new_point));
4725 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4728 return make_int (retval);
4732 /* #### Is this going to work right when at eob? */
4733 arg = Fprefix_numeric_value (arg);
4735 XSETINT (arg, XINT (arg) + height);
4738 start = marker_position (w->start[CURRENT_DISP]);
4739 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4742 new_point = BUF_PT (b);
4744 new_point = marker_position (w->pointm[CURRENT_DISP]);
4746 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4749 BUF_SET_PT (b, new_point);
4751 Fset_window_point (window, make_int (new_point));
4753 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4755 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4761 BUF_SET_PT (b, start);
4763 Fset_window_point (window, make_int (start));
4767 return Fvertical_motion (arg, window, Qnil);
4771 new_point = vmotion (XWINDOW (window),
4772 marker_position (w->pointm[CURRENT_DISP]),
4774 Fset_window_point (window, make_int (new_point));
4775 return make_int (vpos);
4781 map_windows_1 (Lisp_Object window,
4782 int (*mapfun) (struct window *w, void *closure),
4785 for (; !NILP (window); window = XWINDOW (window)->next)
4788 struct window *w = XWINDOW (window);
4790 if (!NILP (w->vchild))
4791 retval = map_windows_1 (w->vchild, mapfun, closure);
4792 else if (!NILP (w->hchild))
4793 retval = map_windows_1 (w->hchild, mapfun, closure);
4795 retval = (mapfun) (w, closure);
4804 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4805 invocation of MAPFUN. If any invocation of MAPFUN returns
4806 non-zero, the mapping is halted. Otherwise, map_windows() maps
4807 over all windows in F.
4809 If MAPFUN creates or deletes windows, the behavior is undefined. */
4812 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4816 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4819 Lisp_Object frmcons, devcons, concons;
4821 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4823 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4835 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4838 w->shadow_thickness_changed = 1;
4839 MARK_WINDOWS_CHANGED (w);
4843 vertical_divider_changed_in_window (Lisp_Object specifier,
4847 MARK_WINDOWS_CHANGED (w);
4848 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4851 /* also used in scrollbar.c */
4853 some_window_value_changed (Lisp_Object specifier, struct window *w,
4856 MARK_WINDOWS_CHANGED (w);
4859 #ifdef MEMORY_USAGE_STATS
4865 #ifdef HAVE_SCROLLBARS
4869 int other_redisplay;
4874 compute_window_mirror_usage (struct window_mirror *mir,
4875 struct window_stats *stats,
4876 struct overhead_stats *ovstats)
4880 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4882 #ifdef HAVE_SCROLLBARS
4884 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4887 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4890 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4893 #endif /* HAVE_SCROLLBARS */
4894 stats->other_redisplay +=
4895 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4896 stats->other_redisplay +=
4897 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4901 compute_window_usage (struct window *w, struct window_stats *stats,
4902 struct overhead_stats *ovstats)
4905 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4906 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4907 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4908 stats->line_start +=
4909 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4910 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4913 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4914 Return stats about the memory usage of window WINDOW.
4915 The values returned are in the form of an alist of usage types and byte
4916 counts. The byte counts attempt to encompass all the memory used
4917 by the window (separate from the memory logically associated with a
4918 buffer or frame), including internal structures and any malloc()
4919 overhead associated with them. In practice, the byte counts are
4920 underestimated because certain memory usage is very hard to determine
4921 \(e.g. the amount of memory used inside the Xt library or inside the
4922 X server) and because there is other stuff that might logically
4923 be associated with a window, buffer, or frame (e.g. window configurations,
4924 glyphs) but should not obviously be included in the usage counts.
4926 Multiple slices of the total memory usage may be returned, separated
4927 by a nil. Each slice represents a particular view of the memory, a
4928 particular way of partitioning it into groups. Within a slice, there
4929 is no overlap between the groups of memory, and each slice collectively
4930 represents all the memory concerned.
4934 struct window_stats stats;
4935 struct overhead_stats ovstats;
4936 Lisp_Object val = Qnil;
4938 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4940 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4942 val = acons (Qface_cache, make_int (stats.face), val);
4943 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4944 #ifdef HAVE_SCROLLBARS
4945 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4947 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4948 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4949 val = acons (Qother, make_int (stats.other), val);
4950 val = Fcons (Qnil, val);
4951 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4952 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4953 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4955 return Fnreverse (val);
4958 #endif /* MEMORY_USAGE_STATS */
4961 /************************************************************************/
4962 /* Window configurations */
4963 /************************************************************************/
4965 /* #### This window configuration stuff has had serious bugs lurking in it
4966 for years; it would be a -huge- win if this was reimplemented in lisp.
4969 /* If you add anything to this structure make sure saved_window_equal
4973 Lisp_Object window; /* window */
4974 Lisp_Object buffer; /* buffer */
4975 Lisp_Object start; /* copied marker */
4976 Lisp_Object pointm; /* copied marker */
4977 Lisp_Object sb_point; /* copied marker */
4978 Lisp_Object mark; /* copied marker */
4984 Charcount modeline_hscroll;
4985 int parent_index; /* index into saved_windows */
4986 int prev_index; /* index into saved_windows */
4987 char start_at_line_beg; /* boolean */
4989 #define WINDOW_SLOT_DECLARATION
4990 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4991 #include "winslots.h"
4994 /* If you add anything to this structure make sure window_config_equal
4996 struct window_config
4998 struct lcrecord_header header;
4999 /* int frame_width; No longer needed, JV
5000 int frame_height; */
5002 Lisp_Object selected_frame;
5004 Lisp_Object current_window;
5005 Lisp_Object current_buffer;
5006 Lisp_Object minibuffer_scroll_window;
5007 Lisp_Object root_window;
5008 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5009 /* Record the values of window-min-width and window-min-height
5010 so that window sizes remain consistent with them. */
5011 int min_width, min_height;
5012 int saved_windows_count;
5013 /* Zero-sized arrays aren't ANSI C */
5014 struct saved_window saved_windows[1];
5017 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5018 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5019 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5020 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5021 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5024 mark_window_config (Lisp_Object obj)
5026 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5028 mark_object (config->current_window);
5029 mark_object (config->current_buffer);
5030 mark_object (config->minibuffer_scroll_window);
5031 mark_object (config->root_window);
5033 for (i = 0; i < config->saved_windows_count; i++)
5035 struct saved_window *s = SAVED_WINDOW_N (config, i);
5036 mark_object (s->window);
5037 mark_object (s->buffer);
5038 mark_object (s->start);
5039 mark_object (s->pointm);
5040 mark_object (s->sb_point);
5041 mark_object (s->mark);
5043 /* #### This looked like this. I do not see why specifier cached
5044 values should not be marked, as such specifiers as toolbars
5045 might have GC-able instances. Freed configs are not marked,
5046 aren't they? -- kkm */
5047 mark_object (s->dedicated);
5049 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5050 #include "winslots.h"
5057 sizeof_window_config_for_n_windows (int n)
5059 return (sizeof (struct window_config) +
5060 /* n - 1 because zero-sized arrays aren't ANSI C */
5061 (n - 1) *sizeof (struct saved_window));
5065 sizeof_window_config (const void *h)
5067 const struct window_config *c = (const struct window_config *) h;
5068 return sizeof_window_config_for_n_windows (c->saved_windows_count);
5072 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5074 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5077 error ("printing unreadable object #<window-configuration 0x%x>",
5078 config->header.uid);
5079 write_c_string ("#<window-configuration ", printcharfun);
5080 sprintf (buf, "0x%x>", config->header.uid);
5081 write_c_string (buf, printcharfun);
5084 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
5085 window_configuration,
5087 print_window_config,
5088 0, 0, 0, 0, sizeof_window_config,
5089 struct window_config);
5092 /* Returns a boolean indicating whether the two saved windows are
5095 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
5097 #define WINDOW_SLOT(slot, compare) \
5098 if (!compare (win1->slot, win2->slot)) \
5100 #include "winslots.h"
5103 EQ (win1->window, win2->window) &&
5104 EQ (win1->buffer, win2->buffer) &&
5105 internal_equal (win1->start, win2->start, 0) &&
5106 internal_equal (win1->pointm, win2->pointm, 0) &&
5107 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5108 internal_equal (win1->mark, win2->mark, 0) &&
5109 win1->pixel_left == win2->pixel_left &&
5110 win1->pixel_top == win2->pixel_top &&
5111 win1->pixel_width == win2->pixel_width &&
5112 win1->pixel_height == win2->pixel_height &&
5113 win1->hscroll == win2->hscroll &&
5114 win1->modeline_hscroll == win2->modeline_hscroll &&
5115 win1->parent_index == win2->parent_index &&
5116 win1->prev_index == win2->prev_index &&
5117 win1->start_at_line_beg == win2->start_at_line_beg;
5120 /* Returns a boolean indicating whether the two given configurations
5123 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5125 struct window_config *fig1, *fig2;
5128 /* First check if they are truly the same. */
5129 if (EQ (conf1, conf2))
5132 fig1 = XWINDOW_CONFIGURATION (conf1);
5133 fig2 = XWINDOW_CONFIGURATION (conf2);
5135 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5136 EQ (fig1->current_window, fig2->current_window) &&
5137 EQ (fig1->current_buffer, fig2->current_buffer) &&
5138 EQ (fig1->root_window, fig2->root_window) &&
5139 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5141 fig1->frame_width == fig2->frame_width &&
5142 fig1->frame_height == fig2->frame_height)) */
5145 for (i = 0; i < fig1->saved_windows_count; i++)
5147 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5148 SAVED_WINDOW_N (fig2, i)))
5155 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5156 Return t if OBJECT is a window-configuration object.
5160 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5164 mark_windows_in_use_closure (struct window *w, void *closure)
5166 int mark = *(int *)closure;
5167 w->config_mark = mark;
5172 mark_windows_in_use (struct frame *f, int mark)
5174 map_windows (f, mark_windows_in_use_closure, &mark);
5177 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5179 free_window_configuration (Lisp_Object window_config)
5182 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5184 /* Free all the markers. It's not completely necessary that
5185 we do this (window configs sitting in a free list aren't
5186 marked normally so the markers wouldn't be marked anyway)
5187 but it's more efficient. */
5188 for (i = 0; i < config->saved_windows_count; i++)
5190 struct saved_window *p = SAVED_WINDOW_N (config, i);
5192 if (!NILP (p->pointm))
5194 free_marker (XMARKER (p->pointm));
5197 if (!NILP (p->start))
5199 free_marker (XMARKER (p->start));
5202 if (!NILP (p->sb_point))
5204 free_marker (XMARKER (p->sb_point));
5207 if (!NILP (p->mark))
5209 free_marker (XMARKER (p->mark));
5214 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5215 free_managed_lcrecord (Vwindow_configuration_free_list
5216 [config->saved_windows_count - 1],
5222 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5223 Set the configuration of windows and buffers as specified by CONFIGURATION.
5224 CONFIGURATION must be a value previously returned
5225 by `current-window-configuration' (which see).
5230 struct window_config *config;
5231 struct saved_window *p;
5232 Lisp_Object new_current_buffer;
5236 struct gcpro gcpro1;
5237 Lisp_Object old_window_config;
5238 /* int previous_frame_height;
5239 int previous_frame_width;*/
5240 int previous_pixel_top;
5241 int previous_pixel_height;
5242 int previous_pixel_left;
5243 int previous_pixel_width;
5244 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5245 int real_font_height;
5246 int converted_minibuf_height,target_minibuf_height;
5247 int specpdl_count = specpdl_depth ();
5249 GCPRO1 (configuration);
5251 CHECK_WINDOW_CONFIGURATION (configuration);
5252 config = XWINDOW_CONFIGURATION (configuration);
5254 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5257 /* Do not signal an error here if the frame was deleted. There are
5258 reasonable cases where we could get here with a deleted frame and
5259 just want to do close to nothing instead. */
5261 if (FRAME_LIVE_P (f))
5263 /* restore the frame characteristics */
5265 new_current_buffer = config->current_buffer;
5266 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5267 new_current_buffer = Qnil;
5270 * Assumed precondition: w->config_mark = 0 for all w
5271 * This procedure should ensure this is true by the time it exits
5272 * to ensure the precondition for future calls.
5274 * We use w->config_mark to know whether we're modifying a
5275 * window that is currently visible on the frame (#### we
5276 * should just be able to check whether the window is dead
5277 * or not, but this way is safer?). As we process each
5278 * window, we set its config_mark to 0. At the end, we
5279 * go through all the windows that used to be on the frame,
5280 * set each one's config_mark to 0 (to maintain the
5281 * assumed precondition) and delete each one that's no
5284 * #### Using a window-configuration to keep track of
5285 * the current windows is wasteful. All we need is the
5286 * list of windows, so we could just use a dynarr.
5288 old_window_config = Fcurrent_window_configuration (frame);
5290 /* If the new configuration is already equal to the old, then stop
5291 right here. This saves the work below and it also saves
5292 triggering a full redisplay of this window. This is a huge win
5293 when using the mouse since the mode motion code uses
5294 save-window-excursion extensively but will rarely cause the
5295 configuration to actually change. */
5296 if (window_config_equal (configuration, old_window_config))
5298 free_window_configuration (old_window_config);
5303 /* We can't quit or even check for quit because that may cause
5304 investigation of the frame state, which may crash if the frame is
5305 in an inconsistent state. */
5306 begin_dont_check_for_quit ();
5307 record_unwind_protect (free_window_configuration, old_window_config);
5309 mark_windows_in_use (f, 1);
5310 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5311 /* Force subwindows to be remapped. This is overkill but saves
5312 us having to rely on the redisplay code to unmap any extant
5315 #### It does cause some extra flashing though which we could
5316 possibly avoid. So consider trying to get redisplay to work
5319 Removing the instances from the frame cache is wrong because
5320 an instance is only put in the frame cache when it is
5321 instantiated. So if we do this there is a chance that stuff
5322 will never get put back in the frame cache. */
5323 reset_frame_subwindow_instance_cache (f);
5326 /* JV: This is bogus,
5327 First of all, the units are inconsistent. The frame sizes are measured
5328 in characters but the window sizes are stored in pixels. So if a
5329 font size change happened between saving and restoring, the
5330 frame "sizes" maybe equal but the windows still should be
5331 resized. This is tickled a lot by the new "character size
5332 stays constant" policy in 21.0. It leads to very weird
5333 glitches (and possibly crashes when asserts are tickled).
5335 Just changing the units doesn't help because changing the
5336 toolbar configuration can also change the pixel positions.
5337 Luckily there is a much simpler way of doing this, see below.
5339 previous_frame_width = FRAME_WIDTH (f);
5340 previous_frame_height = FRAME_HEIGHT (f);
5341 /* If the frame has been resized since this window configuration was
5342 made, we change the frame to the size specified in the
5343 configuration, restore the configuration, and then resize it
5344 back. We keep track of the prevailing height in these variables. */
5345 if (config->frame_height != FRAME_HEIGHT (f)
5346 || config->frame_width != FRAME_WIDTH (f))
5347 change_frame_size (f, config->frame_height, config->frame_width, 0);
5350 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5351 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5352 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5353 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5355 /* remember some properties of the minibuffer */
5357 default_face_height_and_width (frame, &real_font_height, 0);
5358 assert(real_font_height > 0);
5360 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5362 previous_minibuf_height
5363 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5364 previous_minibuf_top
5365 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5366 previous_minibuf_width
5367 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5371 previous_minibuf_height = 0;
5372 previous_minibuf_top = 0;
5373 previous_minibuf_width = 0;
5375 converted_minibuf_height =
5376 (previous_minibuf_height % real_font_height) == 0 ?
5377 - (previous_minibuf_height / real_font_height ) : /* lines */
5378 previous_minibuf_height; /* pixels */
5380 /* Temporarily avoid any problems with windows that are smaller
5381 than they are supposed to be. */
5382 window_min_height = 1;
5383 window_min_width = 1;
5385 /* OK, now restore all the windows in the window config.
5386 This may involve "undeleting" windows, since the
5387 windows in the window config may be deleted.
5389 for (k = 0; k < config->saved_windows_count; k++)
5391 p = SAVED_WINDOW_N (config, k);
5392 w = XWINDOW (p->window);
5395 /* The window might be dead. In this case, its redisplay
5396 structures were freed, so we need to reallocate them. */
5397 if (!w->face_cachels)
5399 w->face_cachels = Dynarr_new (face_cachel);
5400 reset_face_cachels (w);
5402 if (!w->glyph_cachels)
5403 w->glyph_cachels = Dynarr_new (glyph_cachel);
5404 if (!w->line_start_cache)
5405 w->line_start_cache = Dynarr_new (line_start_cache);
5406 w->gutter_extent_modiff[0] = 0;
5407 w->gutter_extent_modiff[1] = 0;
5408 w->gutter_extent_modiff[2] = 0;
5409 w->gutter_extent_modiff[3] = 0;
5412 if (p->parent_index >= 0)
5413 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5417 if (p->prev_index >= 0)
5419 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5421 /* This is true for a minibuffer-only frame. */
5422 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5425 XWINDOW (w->prev)->next = p->window;
5430 if (!NILP (w->parent))
5432 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5434 XWINDOW (w->parent)->vchild = p->window;
5435 XWINDOW (w->parent)->hchild = Qnil;
5439 XWINDOW (w->parent)->hchild = p->window;
5440 XWINDOW (w->parent)->vchild = Qnil;
5444 if (!w->config_mark)
5446 /* #### This should be equivalent to the window previously
5447 having been dead. If we're brave, we'll put in an
5448 assertion to this effect. */
5449 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5451 else /* if (!EQ (w->buffer, p->buffer)) */
5453 /* With the new redisplay we let it know that a change has
5454 been made and it will take care of the rest. If we don't
5455 tell it something has possibly changed it could lead to
5456 incorrect display. */
5457 MARK_WINDOWS_CHANGED (w);
5460 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5461 WINDOW_TOP (w) = WINDOW_TOP (p);
5462 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5463 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5464 w->hscroll = p->hscroll;
5465 w->modeline_hscroll = p->modeline_hscroll;
5466 w->line_cache_last_updated = Qzero;
5467 /* When we restore a window's configuration, the identity of
5468 the window hasn't actually changed - so there is no
5469 reason why we shouldn't preserve the instance cache for
5470 it - unless it was originally deleted. This will often
5471 buy us something as we will not have to re-instantiate
5472 all the instances. This is because this is an instance
5473 cache - not a display cache. Preserving the display cache
5474 would definitely be wrong.
5476 We specifically want to do this for tabs, since for some
5477 reason finding a file will cause the configuration to be
5479 if (NILP (w->subwindow_instance_cache))
5480 w->subwindow_instance_cache =
5481 make_lisp_hash_table (30,
5482 HASH_TABLE_KEY_VALUE_WEAK,
5484 SET_LAST_MODIFIED (w, 1);
5485 SET_LAST_FACECHANGE (w);
5488 /* #### Consider making the instance cache a winslot. */
5489 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5490 #include "winslots.h"
5492 /* Reinstall the saved buffer and pointers into it. */
5493 if (NILP (p->buffer))
5494 w->buffer = p->buffer;
5497 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5498 /* If saved buffer is alive, install it. */
5500 w->buffer = p->buffer;
5501 w->start_at_line_beg = p->start_at_line_beg;
5502 set_marker_restricted (w->start[CURRENT_DISP],
5503 Fmarker_position (p->start),
5505 set_marker_restricted (w->pointm[CURRENT_DISP],
5506 Fmarker_position (p->pointm),
5508 set_marker_restricted (w->sb_point,
5509 Fmarker_position (p->sb_point),
5511 Fset_marker (XBUFFER (w->buffer)->mark,
5512 Fmarker_position (p->mark), w->buffer);
5514 /* As documented in Fcurrent_window_configuration, don't
5515 save the location of point in the buffer which was current
5516 when the window configuration was recorded. */
5517 if (!EQ (p->buffer, new_current_buffer) &&
5518 XBUFFER (p->buffer) == current_buffer)
5519 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5521 else if (NILP (w->buffer) ||
5522 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5523 /* Else if window's old buffer is dead too, get a live one. */
5525 /* #### The following line makes me nervous... */
5526 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5527 w->buffer = Fget_buffer_create (QSscratch);
5528 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5529 /* This will set the markers to beginning of visible
5531 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5532 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5534 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5535 w->start_at_line_beg = 1;
5538 /* Keeping window's old buffer; make sure the markers
5541 /* Set window markers at start of visible range. */
5542 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5543 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5545 if (XMARKER (w->sb_point)->buffer == 0)
5546 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5547 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5548 set_marker_restricted (w->pointm[CURRENT_DISP],
5550 (BUF_PT (XBUFFER (w->buffer))),
5552 w->start_at_line_beg = 1;
5557 FRAME_ROOT_WINDOW (f) = config->root_window;
5558 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5559 then calls do_switch_frame() below to select the frame that was
5560 recorded in the window config as being selected.
5562 Instead, we don't ever change the selected frame, and either
5563 call Fselect_window() below if the window config's frame is
5564 currently selected, or just set the selected window of the
5565 window config's frame. */
5568 /* Set the frame height to the value it had before this function. */
5569 if (previous_frame_height != FRAME_HEIGHT (f)
5570 || previous_frame_width != FRAME_WIDTH (f))
5571 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5573 /* We just reset the size and position of the minibuffer, to its old
5574 value, which needn't be valid. So we do some magic to see which value
5575 to actually take. Then we set it.
5578 We take the old value if is in the same units but differs from the
5581 #### Now we get more cases correct then ever before, but
5582 are we treating all? For instance what if the frames minibuf window
5583 is no longer the same one?
5585 target_minibuf_height = previous_minibuf_height;
5586 if (converted_minibuf_height &&
5587 (converted_minibuf_height * config->minibuf_height) > 0 &&
5588 (converted_minibuf_height != config->minibuf_height))
5590 target_minibuf_height = config->minibuf_height < 0 ?
5591 - (config->minibuf_height * real_font_height) :
5592 config->minibuf_height;
5593 target_minibuf_height =
5594 max(target_minibuf_height,real_font_height);
5596 if (previous_minibuf_height)
5598 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5599 = previous_minibuf_top -
5600 (target_minibuf_height - previous_minibuf_height);
5601 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5602 target_minibuf_height, 0);
5603 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5604 previous_minibuf_width, 0);
5607 /* This is a better way to deal with frame resizing, etc.
5608 What we _actually_ want is for the old (just restored)
5610 into the place of the new one. So we just do that. Simple! */
5611 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5612 /* Note that this function also updates the subwindow
5614 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5615 previous_pixel_height -
5616 (target_minibuf_height - previous_minibuf_height), 0);
5617 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5618 /* Note that this function also updates the subwindow
5620 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5622 /* If restoring in the current frame make the window current,
5623 otherwise just update the frame selected_window slot to be
5624 the restored current_window. */
5625 if (f == selected_frame ())
5628 /* When using `pop-window-configuration', often the minibuffer
5629 ends up as the selected window even though it's not active ...
5630 I really don't know the cause of this, but it should never
5631 happen. This kludge should fix it.
5633 #### Find out why this is really going wrong. */
5634 if (!minibuf_level &&
5635 MINI_WINDOW_P (XWINDOW (config->current_window)))
5636 window_to_select = Fnext_window (config->current_window,
5639 window_to_select = config->current_window;
5641 /* Do this last so that buffer stacking is calculated
5643 Fselect_window (config->current_window, Qnil);
5645 if (!NILP (new_current_buffer))
5647 Fset_buffer (new_current_buffer);
5648 Frecord_buffer (new_current_buffer);
5652 Fset_buffer (XWINDOW (config->current_window)->buffer);
5653 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5657 set_frame_selected_window (f, config->current_window);
5660 old_window_config = Qnil; /* Warning suppression */
5662 /* Restore the minimum heights recorded in the configuration. */
5663 window_min_height = config->min_height;
5664 window_min_width = config->min_width;
5667 /* see above comment */
5668 /* Fselect_window will have made f the selected frame, so we
5669 reselect the proper frame here. Fhandle_switch_frame will change the
5670 selected window too, but that doesn't make the call to
5671 Fselect_window above totally superfluous; it still sets f's
5673 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5674 do_switch_frame (config->selected_frame, Qnil, 0);
5677 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5679 if (FRAME_LIVE_P (f))
5681 /* Do this before calling recompute_all_cached_specifiers_in_window()
5682 so that things like redisplay_redraw_cursor() won't abort due
5683 to no window mirror present. */
5684 f->mirror_dirty = 1;
5686 config = XWINDOW_CONFIGURATION (old_window_config);
5687 for (k = 0; k < config->saved_windows_count; k++)
5689 p = SAVED_WINDOW_N (config, k);
5690 w = XWINDOW (p->window);
5691 /* Remember, we set w->config_mark on all currently visible
5692 windows, and reset it on all newly visible windows.
5693 Any windows still marked need to be deleted. */
5696 mark_window_as_deleted (w);
5701 /* We just potentially changed the window's buffer and
5702 potentially turned a dead window into a live one,
5703 so we need to recompute the cached specifier values. */
5704 recompute_all_cached_specifiers_in_window (w);
5709 /* Now restore things, when everything else if OK. */
5711 unbind_to (specpdl_count, Qnil);
5718 /* Mark all subwindows of a window as deleted. The argument
5719 W is actually the subwindow tree of the window in question. */
5722 delete_all_subwindows (struct window *w)
5724 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5725 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5726 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5728 mark_window_as_deleted (w);
5733 count_windows (struct window *window)
5736 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5737 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5738 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5742 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5745 for (j = 0; j < lim; j++)
5747 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5751 return 0; /* suppress compiler warning */
5755 save_window_save (Lisp_Object window, struct window_config *config, int i)
5759 for (; !NILP (window); window = w->next)
5761 struct saved_window *p = SAVED_WINDOW_N (config, i);
5763 w = XWINDOW (window);
5766 p->buffer = w->buffer;
5767 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5768 WINDOW_TOP (p) = WINDOW_TOP (w);
5769 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5770 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5771 p->hscroll = w->hscroll;
5772 p->modeline_hscroll = w->modeline_hscroll;
5774 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5775 #include "winslots.h"
5777 if (!NILP (w->buffer))
5779 /* Save w's value of point in the window configuration.
5780 If w is the selected window, then get the value of point
5781 from the buffer; pointm is garbage in the selected window. */
5782 if (EQ (window, Fselected_window (Qnil)))
5784 p->pointm = noseeum_make_marker ();
5785 Fset_marker (p->pointm,
5786 make_int (BUF_PT (XBUFFER (w->buffer))),
5790 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5792 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5793 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5794 p->start_at_line_beg = w->start_at_line_beg;
5796 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5804 p->start_at_line_beg = 0;
5807 if (NILP (w->parent))
5808 p->parent_index = -1;
5810 p->parent_index = saved_window_index (w->parent, config, i);
5814 p->prev_index = saved_window_index (w->prev, config, i);
5815 if (!NILP (w->vchild))
5816 i = save_window_save (w->vchild, config, i);
5817 if (!NILP (w->hchild))
5818 i = save_window_save (w->hchild, config, i);
5825 /* Added to doc string:
5827 This also records the currently selected frame, and FRAME's focus
5828 redirection (see `redirect-frame-focus').
5833 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5834 Return an object representing the current window configuration of FRAME.
5835 If FRAME is nil or omitted, use the selected frame.
5836 This describes the number of windows, their sizes and current buffers,
5837 and for each window on FRAME the displayed buffer, where display
5838 starts, and the positions of point and mark.
5839 An exception is made for point in the current buffer:
5840 its value is -not- saved.
5845 struct frame *f = decode_frame (frame);
5846 struct window_config *config;
5847 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5849 int real_font_height;
5851 if (n_windows <= countof (Vwindow_configuration_free_list))
5852 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5853 (Vwindow_configuration_free_list
5856 /* More than ten windows; just allocate directly */
5857 config = (struct window_config *)
5858 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5859 &lrecord_window_configuration);
5860 XSETWINDOW_CONFIGURATION (result, config);
5862 config->frame_width = FRAME_WIDTH (f);
5863 config->frame_height = FRAME_HEIGHT (f); */
5864 /* When using `push-window-configuration', often the minibuffer ends
5865 up as the selected window because functions run as the result of
5866 user interaction e.g. hyper-apropos. It seems to me the sensible
5867 thing to do is not record the minibuffer here. */
5868 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5869 config->current_window = FRAME_SELECTED_WINDOW (f);
5871 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5872 XSETBUFFER (config->current_buffer, current_buffer);
5873 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5874 config->root_window = FRAME_ROOT_WINDOW (f);
5875 config->min_height = window_min_height;
5876 config->min_width = window_min_width;
5877 config->saved_windows_count = n_windows;
5878 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5880 /* save the minibuffer height using the heuristics from
5881 change_frame_size_1 */
5883 XSETFRAME (frame, f); /* frame could have been nil ! */
5884 default_face_height_and_width (frame, &real_font_height, 0);
5885 assert(real_font_height > 0);
5887 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5888 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5891 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5892 - (minibuf_height / real_font_height ) : /* lines */
5893 minibuf_height; /* pixels */
5899 save_window_excursion_unwind (Lisp_Object window_config)
5901 Lisp_Object val = Fset_window_configuration (window_config);
5902 free_window_configuration (window_config);
5906 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5907 Execute body, preserving window sizes and contents.
5908 Restores which buffer appears in which window, where display starts,
5909 as well as the current buffer.
5910 Does not restore the value of point in current buffer.
5914 /* This function can GC */
5916 int speccount = specpdl_depth ();
5918 record_unwind_protect (save_window_excursion_unwind,
5919 Fcurrent_window_configuration (Qnil));
5920 val = Fprogn (args);
5921 return unbind_to (speccount, val);
5924 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5925 Return the horizontal pixel position of POS in window.
5926 Beginning of line is column 0. This is calculated using the redisplay
5927 display tables. If WINDOW is nil, the current window is assumed.
5928 If POS is nil, point is assumed. Note that POS must be visible for
5929 a non-nil result to be returned.
5933 struct window* w = decode_window (window);
5934 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5936 struct display_line *dl = 0;
5937 struct display_block *db = 0;
5938 struct rune* rb = 0;
5939 int y = w->last_point_y[CURRENT_DISP];
5940 int x = w->last_point_x[CURRENT_DISP];
5942 if (MINI_WINDOW_P (w))
5945 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5951 pos = Fwindow_point (window);
5956 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5961 for (i = first_line; i < Dynarr_length (dla); i++)
5963 dl = Dynarr_atp (dla, i);
5964 /* find the vertical location first */
5965 if (point >= dl->bufpos && point <= dl->end_bufpos)
5967 db = get_display_block_from_line (dl, TEXT);
5968 for (i = 0; i < Dynarr_length (db->runes); i++)
5970 rb = Dynarr_atp (db->runes, i);
5971 if (point <= rb->bufpos)
5983 /* optimized case */
5984 dl = Dynarr_atp (dla, y);
5985 db = get_display_block_from_line (dl, TEXT);
5987 if (x >= Dynarr_length (db->runes))
5990 rb = Dynarr_atp (db->runes, x);
5993 return make_int (rb->xpos - WINDOW_LEFT (w));
5998 /* This is short and simple in elisp, but... it was written to debug
5999 problems purely on the C side. That is where we need to call it so
6002 debug_print_window (Lisp_Object window, int level)
6005 Lisp_Object child = Fwindow_first_vchild (window);
6008 child = Fwindow_first_hchild (window);
6010 for (i = level; i > 0; i--)
6013 stderr_out ("#<window");
6015 Lisp_Object buffer = XWINDOW (window)->buffer;
6016 if (!NILP (buffer) && BUFFERP (buffer))
6017 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
6019 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
6021 while (!NILP (child))
6023 debug_print_window (child, level + 1);
6024 child = Fwindow_next_child (child);
6028 void debug_print_windows (struct frame *f);
6030 debug_print_windows (struct frame *f)
6032 debug_print_window (f->root_window, 0);
6033 putc ('\n', stderr);
6035 #endif /* DEBUG_XEMACS */
6038 /************************************************************************/
6039 /* initialization */
6040 /************************************************************************/
6043 syms_of_window (void)
6045 INIT_LRECORD_IMPLEMENTATION (window);
6046 INIT_LRECORD_IMPLEMENTATION (window_configuration);
6048 defsymbol (&Qwindowp, "windowp");
6049 defsymbol (&Qwindow_live_p, "window-live-p");
6050 defsymbol (&Qwindow_configurationp, "window-configuration-p");
6051 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6052 defsymbol (&Qdisplay_buffer, "display-buffer");
6054 #ifdef MEMORY_USAGE_STATS
6055 defsymbol (&Qface_cache, "face-cache");
6056 defsymbol (&Qglyph_cache, "glyph-cache");
6057 defsymbol (&Qline_start_cache, "line-start-cache");
6058 #ifdef HAVE_SCROLLBARS
6059 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
6061 defsymbol (&Qother_redisplay, "other-redisplay");
6062 /* Qother in general.c */
6065 DEFSUBR (Fselected_window);
6066 DEFSUBR (Flast_nonminibuf_window);
6067 DEFSUBR (Fminibuffer_window);
6068 DEFSUBR (Fwindow_minibuffer_p);
6070 DEFSUBR (Fwindow_live_p);
6071 DEFSUBR (Fwindow_first_hchild);
6072 DEFSUBR (Fwindow_first_vchild);
6073 DEFSUBR (Fwindow_next_child);
6074 DEFSUBR (Fwindow_previous_child);
6075 DEFSUBR (Fwindow_parent);
6076 DEFSUBR (Fwindow_lowest_p);
6077 DEFSUBR (Fwindow_truncated_p);
6078 DEFSUBR (Fwindow_highest_p);
6079 DEFSUBR (Fwindow_leftmost_p);
6080 DEFSUBR (Fwindow_rightmost_p);
6081 DEFSUBR (Fpos_visible_in_window_p);
6082 DEFSUBR (Fwindow_buffer);
6083 DEFSUBR (Fwindow_frame);
6084 DEFSUBR (Fwindow_height);
6085 DEFSUBR (Fwindow_displayed_height);
6086 DEFSUBR (Fwindow_width);
6087 DEFSUBR (Fwindow_full_width);
6088 DEFSUBR (Fwindow_pixel_height);
6089 DEFSUBR (Fwindow_pixel_width);
6090 DEFSUBR (Fwindow_text_area_height);
6091 DEFSUBR (Fwindow_text_area_pixel_height);
6092 DEFSUBR (Fwindow_displayed_text_pixel_height);
6093 DEFSUBR (Fwindow_text_area_pixel_width);
6094 DEFSUBR (Fwindow_hscroll);
6095 DEFSUBR (Fset_window_hscroll);
6096 DEFSUBR (Fmodeline_hscroll);
6097 DEFSUBR (Fset_modeline_hscroll);
6098 #if 0 /* bogus FSF crock */
6099 DEFSUBR (Fwindow_redisplay_end_trigger);
6100 DEFSUBR (Fset_window_redisplay_end_trigger);
6102 DEFSUBR (Fwindow_pixel_edges);
6103 DEFSUBR (Fwindow_text_area_pixel_edges);
6104 DEFSUBR (Fwindow_point);
6105 DEFSUBR (Fwindow_start);
6106 DEFSUBR (Fwindow_end);
6107 DEFSUBR (Fwindow_last_line_visible_height);
6108 DEFSUBR (Fset_window_point);
6109 DEFSUBR (Fset_window_start);
6110 DEFSUBR (Fwindow_dedicated_p);
6111 DEFSUBR (Fset_window_dedicated_p);
6112 DEFSUBR (Fnext_window);
6113 DEFSUBR (Fprevious_window);
6114 DEFSUBR (Fnext_vertical_window);
6115 DEFSUBR (Fother_window);
6116 DEFSUBR (Fget_lru_window);
6117 DEFSUBR (Fget_largest_window);
6118 DEFSUBR (Fget_buffer_window);
6119 DEFSUBR (Fwindow_left_margin_pixel_width);
6120 DEFSUBR (Fwindow_right_margin_pixel_width);
6121 DEFSUBR (Fdelete_other_windows);
6122 DEFSUBR (Fdelete_windows_on);
6123 DEFSUBR (Freplace_buffer_in_windows);
6124 DEFSUBR (Fdelete_window);
6125 DEFSUBR (Fset_window_buffer);
6126 DEFSUBR (Fselect_window);
6127 DEFSUBR (Fsplit_window);
6128 DEFSUBR (Fenlarge_window);
6129 DEFSUBR (Fenlarge_window_pixels);
6130 DEFSUBR (Fshrink_window);
6131 DEFSUBR (Fshrink_window_pixels);
6132 DEFSUBR (Fscroll_up);
6133 DEFSUBR (Fscroll_down);
6134 DEFSUBR (Fscroll_left);
6135 DEFSUBR (Fscroll_right);
6136 DEFSUBR (Fother_window_for_scrolling);
6137 DEFSUBR (Fscroll_other_window);
6138 DEFSUBR (Fcenter_to_window_line);
6139 DEFSUBR (Fmove_to_window_line);
6140 #ifdef MEMORY_USAGE_STATS
6141 DEFSUBR (Fwindow_memory_usage);
6143 DEFSUBR (Fwindow_configuration_p);
6144 DEFSUBR (Fset_window_configuration);
6145 DEFSUBR (Fcurrent_window_configuration);
6146 DEFSUBR (Fsave_window_excursion);
6147 DEFSUBR (Fcurrent_pixel_column);
6151 reinit_vars_of_window (void)
6154 /* Make sure all windows get marked */
6155 minibuf_window = Qnil;
6156 staticpro_nodump (&minibuf_window);
6158 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6160 Vwindow_configuration_free_list[i] =
6161 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6162 &lrecord_window_configuration);
6163 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6168 vars_of_window (void)
6170 reinit_vars_of_window ();
6172 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6173 *Non-nil means to scroll if point lands on a line which is clipped.
6175 scroll_on_clipped_lines = 1;
6177 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6178 See `temp-buffer-show-function'.
6180 Vtemp_buffer_show_hook = Qnil;
6182 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6183 Non-nil means call as function to display a help buffer.
6184 The function is called with one argument, the buffer to be displayed.
6185 Used by `with-output-to-temp-buffer'.
6186 If this function is used, then it must do the entire job of showing
6187 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6188 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6190 Vtemp_buffer_show_function = Qnil;
6192 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6193 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6195 Vminibuffer_scroll_window = Qnil;
6197 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6198 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6200 Vother_window_scroll_buffer = Qnil;
6202 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6203 *Number of pixels to scroll by per requested line.
6204 If nil then normal line scrolling occurs regardless of line height.
6205 If t then scrolling is done in increments equal to the height of the default face.
6207 Vwindow_pixel_scroll_increment = Qt;
6209 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6210 *Number of lines of continuity when scrolling by screenfuls.
6212 next_screen_context_lines = 2;
6214 DEFVAR_INT ("window-min-height", &window_min_height /*
6215 *Delete any window less than this tall (including its modeline).
6217 window_min_height = 4;
6219 DEFVAR_INT ("window-min-width", &window_min_width /*
6220 *Delete any window less than this wide.
6222 window_min_width = 10;
6226 specifier_vars_of_window (void)
6228 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6229 *How thick to draw 3D shadows around modelines.
6230 If this is set to 0, modelines will be the traditional 2D. Sizes above
6231 10 will be accepted but the maximum thickness that will be drawn is 10.
6232 This is a specifier; use `set-specifier' to change it.
6234 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6235 /* The initial value for modeline-shadow-thickness is 2, but if the
6236 user removes all specifications we provide a fallback value of 0,
6237 which is probably what was expected. */
6238 set_specifier_fallback (Vmodeline_shadow_thickness,
6239 list1 (Fcons (Qnil, Qzero)));
6240 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6242 set_specifier_caching (Vmodeline_shadow_thickness,
6243 offsetof (struct window, modeline_shadow_thickness),
6244 modeline_shadow_thickness_changed,
6247 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6248 *Whether the modeline should be displayed.
6249 This is a specifier; use `set-specifier' to change it.
6251 Vhas_modeline_p = Fmake_specifier (Qboolean);
6252 set_specifier_fallback (Vhas_modeline_p,
6253 list1 (Fcons (Qnil, Qt)));
6254 set_specifier_caching (Vhas_modeline_p,
6255 offsetof (struct window, has_modeline_p),
6256 /* #### It's strange that we need a special
6257 flag to indicate that the shadow-thickness
6258 has changed, but not one to indicate that
6259 the modeline has been turned off or on. */
6260 some_window_value_changed,
6263 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6264 &Vvertical_divider_always_visible_p /*
6265 *Should XEmacs always display vertical dividers between windows.
6267 When this is non-nil, vertical dividers are always shown, and are
6268 draggable. When it is nil, vertical dividers are shown only when
6269 there are no scrollbars in between windows, and are not draggable.
6271 This is a specifier; use `set-specifier' to change it.
6273 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6274 set_specifier_fallback (Vvertical_divider_always_visible_p,
6275 list1 (Fcons (Qnil, Qt)));
6276 set_specifier_caching (Vvertical_divider_always_visible_p,
6277 offsetof (struct window,
6278 vertical_divider_always_visible_p),
6279 vertical_divider_changed_in_window,
6282 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6283 *How thick to draw 3D shadows around vertical dividers.
6284 This is a specifier; use `set-specifier' to change it.
6286 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6287 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6288 list1 (Fcons (Qnil, Qzero)));
6289 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6291 set_specifier_caching (Vvertical_divider_shadow_thickness,
6292 offsetof (struct window,
6293 vertical_divider_shadow_thickness),
6294 vertical_divider_changed_in_window,
6296 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6297 *The width of the vertical dividers, not including shadows.
6299 For TTY windows, divider line is always one character wide. When
6300 instance of this specifier is zero in a TTY window, no divider is
6301 drawn at all between windows. When non-zero, a one character wide
6302 divider is displayed.
6304 This is a specifier; use `set-specifier' to change it.
6307 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6309 Lisp_Object fb = Qnil;
6311 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6313 #ifdef HAVE_X_WINDOWS
6314 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6316 #ifdef HAVE_MS_WINDOWS
6317 /* #### This should be made magic and made to obey system settings */
6318 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6320 set_specifier_fallback (Vvertical_divider_line_width, fb);
6322 set_specifier_caching (Vvertical_divider_line_width,
6323 offsetof (struct window,
6324 vertical_divider_line_width),
6325 vertical_divider_changed_in_window,
6328 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6329 *How much space to leave around the vertical dividers.
6331 In TTY windows, spacing is always zero, and the value of this
6332 specifier is ignored.
6334 This is a specifier; use `set-specifier' to change it.
6336 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6338 Lisp_Object fb = Qnil;
6340 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6342 #ifdef HAVE_X_WINDOWS
6343 /* #### 3D dividers look great on MS Windows with spacing = 0.
6344 Should not the same value be the fallback under X? - kkm */
6345 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6347 #ifdef HAVE_MS_WINDOWS
6348 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6350 set_specifier_fallback (Vvertical_divider_spacing, fb);
6352 set_specifier_caching (Vvertical_divider_spacing,
6353 offsetof (struct window, vertical_divider_spacing),
6354 vertical_divider_changed_in_window,