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 Fixnum window_min_height;
115 Fixnum 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 Fixnum 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_image_instance_cache_hash_table ();
286 p->line_cache_last_updated = Qzero;
287 INIT_DISP_VARIABLE (last_point_x, 0);
288 INIT_DISP_VARIABLE (last_point_y, 0);
289 INIT_DISP_VARIABLE (window_end_pos, 0);
290 p->redisplay_end_trigger = Qnil;
292 p->gutter_extent_modiff[0] = 0;
293 p->gutter_extent_modiff[1] = 0;
294 p->gutter_extent_modiff[2] = 0;
295 p->gutter_extent_modiff[3] = 0;
297 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
298 #include "winslots.h"
300 p->windows_changed = 1;
301 p->shadow_thickness_changed = 1;
305 #undef INIT_DISP_VARIABLE
308 * The redisplay structures used to be stored with each window. While
309 * they are logically something associated with frames they can't be
310 * stored there with a redisplay which handles variable height lines.
311 * Lines in horizontally split windows might not line up. So they get
312 * stored with the windows.
314 * The problem with this is window configurations. When restoring a
315 * window configuration it now becomes problematic to do an
316 * incremental redisplay. The solution is to store the redisplay
317 * structures with the frame as they should be but laid out in the
318 * same manner as the window structure. Thus is born the window
321 * It also becomes a convenient place to stick scrollbar instances
322 * since they extrapolate out to having the same problem described for
323 * the display structures.
326 /* Create a new window mirror structure and associated redisplay
328 static struct window_mirror *
329 new_window_mirror (struct frame *f)
331 struct window_mirror *t = xnew_and_zero (struct window_mirror);
335 t->current_display_lines = Dynarr_new (display_line);
336 t->desired_display_lines = Dynarr_new (display_line);
339 #ifdef HAVE_SCROLLBARS
340 t->scrollbar_vertical_instance = NULL;
341 t->scrollbar_horizontal_instance = NULL;
347 /* Synchronize the mirror structure with a given window structure.
348 This is normally called from update_frame_window_mirror with a
349 starting window of f->root_window. */
350 static struct window_mirror *
351 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
357 free_window_mirror (mir);
364 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
366 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
367 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
368 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
371 * If the redisplay structs are not empty and the mirror has
372 * children, then this mirror structure was formerly being used for
373 * display but is no longer. Reset its current display structs so
374 * that redisplay doesn't accidentally think they are accurate if it
375 * is later used for display purposes once again. Also, mark the
376 * scrollbar instance as not active.
378 if (mir->vchild || mir->hchild)
380 /* The redisplay structures are big. Leaving them around in
381 non-leaf windows can add up to a lot of wasted space. So
383 free_display_structs (mir);
384 mir->current_display_lines = Dynarr_new (display_line);
385 mir->desired_display_lines = Dynarr_new (display_line);
387 #ifdef HAVE_SCROLLBARS
388 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
396 /* Given a window mirror, determine which real window it contains the
397 redisplay structures for. */
399 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
400 struct window_mirror *mir)
402 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
406 if (!NILP (XWINDOW (win)->vchild))
409 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
413 if (!NILP (XWINDOW (win)->hchild))
416 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
425 /* Given a real window, find the mirror structure which contains its
426 redisplay structures. */
427 static struct window_mirror *
428 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
431 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
433 if (w == XWINDOW (win))
436 if (!NILP (XWINDOW (win)->vchild))
438 struct window_mirror *retval =
439 find_window_mirror_internal (XWINDOW (win)->vchild,
441 if (retval) return retval;
444 if (!NILP (XWINDOW (win)->hchild))
446 struct window_mirror *retval =
447 find_window_mirror_internal (XWINDOW (win)->hchild,
449 if (retval) return retval;
456 /* Update the mirror structure for the given frame. */
458 update_frame_window_mirror (struct frame *f)
460 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
464 /* Free a given mirror structure along with all of its children as
465 well as their associated display structures. */
467 free_window_mirror (struct window_mirror *mir)
471 struct window_mirror *prev = mir;
472 if (mir->hchild) free_window_mirror (mir->hchild);
473 if (mir->vchild) free_window_mirror (mir->vchild);
474 #ifdef HAVE_SCROLLBARS
475 release_window_mirror_scrollbars (mir);
477 free_display_structs (mir);
483 /* Given a mirror structure, return the window it mirrors. Calls
484 real_window_internal to do most of the work. */
486 real_window (struct window_mirror *mir, int no_abort)
488 Lisp_Object retval = real_window_internal (mir->frame->root_window,
489 mir->frame->root_mirror, mir);
490 if (NILP (retval) && !no_abort)
496 /* Given a real window, return its mirror structure. Calls
497 find_window_mirror_internal to do all of the work. */
498 struct window_mirror *
499 find_window_mirror (struct window *w)
501 struct frame *f = XFRAME (w->frame);
503 update_frame_window_mirror (f);
504 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
507 /*****************************************************************************
508 find_window_by_pixel_pos
510 Given a pixel position relative to a frame, find the window at that
512 ****************************************************************************/
514 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
519 for (; !NILP (win); win = XWINDOW (win)->next)
523 if (!NILP (XWINDOW (win)->vchild))
525 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
528 if (!NILP (XWINDOW (win)->hchild))
530 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
534 if (pix_x >= WINDOW_LEFT (w)
535 && pix_x <= WINDOW_RIGHT (w)
536 && pix_y >= WINDOW_TOP (w)
537 && pix_y <= WINDOW_BOTTOM (w))
543 /* Return a pointer to the display structures for the given window. */
544 display_line_dynarr *
545 window_display_lines (struct window *w, int which)
547 struct window_mirror *t;
549 if (XFRAME (w->frame)->mirror_dirty)
550 update_frame_window_mirror (XFRAME (w->frame));
551 t = find_window_mirror (w);
555 if (which == CURRENT_DISP)
556 return t->current_display_lines;
557 else if (which == DESIRED_DISP)
558 return t->desired_display_lines;
559 else if (which == CMOTION_DISP)
560 /* The CMOTION_DISP display lines are global. */
561 return cmotion_display_lines;
565 return 0; /* shut up compiler */
569 window_display_buffer (struct window *w)
571 struct window_mirror *t;
573 if (XFRAME (w->frame)->mirror_dirty)
574 update_frame_window_mirror (XFRAME (w->frame));
575 t = find_window_mirror (w);
583 set_window_display_buffer (struct window *w, struct buffer *b)
585 struct window_mirror *t;
587 if (XFRAME (w->frame)->mirror_dirty)
588 update_frame_window_mirror (XFRAME (w->frame));
589 t = find_window_mirror (w);
597 /* Determining a window's position based solely on its pixel
598 positioning doesn't work. Instead, we do it the intelligent way,
599 by checking its positioning in the window hierarchy. */
601 window_is_leftmost (struct window *w)
603 Lisp_Object parent, current_ancestor, window;
605 XSETWINDOW (window, w);
607 parent = XWINDOW (window)->parent;
608 current_ancestor = window;
610 while (!NILP (parent))
612 if (!NILP (XWINDOW (parent)->hchild) &&
613 !EQ (XWINDOW (parent)->hchild, current_ancestor))
616 current_ancestor = parent;
617 parent = XWINDOW (parent)->parent;
624 window_is_rightmost (struct window *w)
626 Lisp_Object parent, current_ancestor, window;
628 XSETWINDOW (window, w);
630 parent = XWINDOW (window)->parent;
631 current_ancestor = window;
633 while (!NILP (parent))
635 if (!NILP (XWINDOW (parent)->hchild)
636 && !NILP (XWINDOW (current_ancestor)->next))
639 current_ancestor = parent;
640 parent = XWINDOW (parent)->parent;
647 window_full_width_p (struct window *w)
649 return window_is_leftmost (w) && window_is_rightmost (w);
653 window_is_highest (struct window *w)
655 Lisp_Object parent, current_ancestor, window;
657 XSETWINDOW (window, w);
659 parent = XWINDOW (window)->parent;
660 current_ancestor = window;
662 while (!NILP (parent))
664 if (!NILP (XWINDOW (parent)->vchild) &&
665 !EQ (XWINDOW (parent)->vchild, current_ancestor))
668 current_ancestor = parent;
669 parent = XWINDOW (parent)->parent;
672 /* This is really to catch the minibuffer but we make it generic in
673 case we ever change things around to let the minibuffer be on top. */
674 if (NILP (XWINDOW (current_ancestor)->prev))
681 window_is_lowest (struct window *w)
683 Lisp_Object parent, current_ancestor, window;
685 XSETWINDOW (window, w);
687 parent = XWINDOW (window)->parent;
688 current_ancestor = window;
690 while (!NILP (parent))
692 if (!NILP (XWINDOW (parent)->vchild)
693 && !NILP (XWINDOW (current_ancestor)->next))
696 current_ancestor = parent;
697 parent = XWINDOW (parent)->parent;
703 #if 0 /* not currently used */
706 window_full_height_p (struct window *w)
708 return window_is_highest (w) && window_is_lowest (w);
714 window_truncation_on (struct window *w)
716 /* Minibuffer windows are never truncated.
717 #### is this the right way ? */
718 if (MINI_WINDOW_P (w))
721 /* Horizontally scrolled windows are truncated. */
725 /* If truncate_partial_width_windows is true and the window is not
726 the full width of the frame it is truncated. */
727 if (truncate_partial_width_windows
728 && !(window_is_leftmost (w) && window_is_rightmost (w)))
731 /* If the window's buffer's value of truncate_lines is non-nil, then
732 the window is truncated. */
733 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
739 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
740 Returns non-nil if text in the window is truncated.
744 struct window *w = decode_window (window);
746 return window_truncation_on (w) ? Qt : Qnil;
751 have_undivided_common_edge (struct window *w_right, void *closure)
753 struct window *w_left = (struct window *) closure;
754 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
755 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
756 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
757 #ifdef HAVE_SCROLLBARS
758 && (NILP (w_right->scrollbar_on_left_p)
759 || NILP (w_right->vertical_scrollbar_visible_p)
760 || ZEROP (w_right->scrollbar_width))
766 window_needs_vertical_divider_1 (struct window *w)
768 /* Never if we're on the right */
769 if (window_is_rightmost (w))
772 /* Always if draggable */
773 if (!NILP (w->vertical_divider_always_visible_p))
776 #ifdef HAVE_SCROLLBARS
777 /* Our right scrollbar is enough to separate us at the right */
778 if (NILP (w->scrollbar_on_left_p)
779 && !NILP (w->vertical_scrollbar_visible_p)
780 && !ZEROP (w->scrollbar_width))
784 /* Ok. to determine whether we need a divider on the left, we must
785 check that our right neighbor windows have scrollbars on their
786 left sides. We must check all such windows which have common
787 left edge with our window's right edge. */
788 return map_windows (XFRAME (WINDOW_FRAME (w)),
789 have_undivided_common_edge, (void*)w);
793 window_needs_vertical_divider (struct window *w)
795 if (!w->need_vertical_divider_valid_p)
797 w->need_vertical_divider_p =
798 window_needs_vertical_divider_1 (w);
799 w->need_vertical_divider_valid_p = 1;
801 return w->need_vertical_divider_p;
804 /* Called from invalidate_vertical_divider_cache_in_frame */
806 invalidate_vertical_divider_cache_in_window (struct window *w,
809 w->need_vertical_divider_valid_p = 0;
813 /* Calculate width of vertical divider, including its shadows
814 and spacing. The returned value is effectively the distance
815 between adjacent window edges. This function does not check
816 whether a window needs a vertical divider, so the returned
817 value is a "theoretical" one */
819 window_divider_width (struct window *w)
821 /* the shadow thickness can be negative. This means that the divider
822 will have a depressed look */
824 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
826 XINT (w->vertical_divider_line_width)
827 + 2 * XINT (w->vertical_divider_spacing)
828 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
830 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
834 window_scrollbar_width (struct window *w)
836 #ifdef HAVE_SCROLLBARS
837 if (!WINDOW_WIN_P (w)
840 || NILP (w->vertical_scrollbar_visible_p))
841 /* #### when does NILP (w->buffer) happen? */
844 return XINT (w->scrollbar_width);
847 #endif /* HAVE_SCROLLBARS */
850 /* Horizontal scrollbars are only active on windows with truncation
853 window_scrollbar_height (struct window *w)
855 #ifdef HAVE_SCROLLBARS
856 if (!WINDOW_WIN_P (w)
859 || NILP (w->horizontal_scrollbar_visible_p)
860 || !window_truncation_on (w))
863 return XINT (w->scrollbar_height);
866 #endif /* HAVE_SCROLLBARS */
870 window_modeline_height (struct window *w)
872 struct frame *f = XFRAME (w->frame);
875 if (MINI_WINDOW_P (w) || NILP (w->buffer))
879 else if (!WINDOW_HAS_MODELINE_P (w))
881 if (window_scrollbar_height (w))
885 modeline_height = FRAMEMETH (f, divider_height, ());
887 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
888 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
897 display_line_dynarr *dla;
899 /* We don't force a regeneration of the modeline here.
900 Instead it is now a precondition that any function calling
901 this should make sure that one of these structures is
902 up-to-date. In practice this only affects two internal
903 redisplay functions, regenerate_window and
904 regenerate_window_point_center. */
905 /* We check DESIRED_DISP because if it is valid it is more
906 up-to-date than CURRENT_DISP. For calls to this outside
907 of redisplay it doesn't matter which structure we check
908 since there is a redisplay condition that these
909 structures be identical outside of redisplay. */
910 dla = window_display_lines (w, DESIRED_DISP);
911 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
912 modeline_height = (Dynarr_atp (dla, 0)->ascent +
913 Dynarr_atp (dla, 0)->descent);
916 dla = window_display_lines (w, CURRENT_DISP);
917 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
918 modeline_height = (Dynarr_atp (dla, 0)->ascent +
919 Dynarr_atp (dla, 0)->descent);
921 /* This should be an abort except I'm not yet 100%
922 confident that it won't ever get hit (though I
923 haven't been able to trigger it). It is extremely
924 unlikely to cause any noticeable problem and even if
925 it does it will be a minor display glitch. */
926 /* #### Bullshit alert. It does get hit and it causes
927 noticeable glitches. real_current_modeline_height
928 is a kludge to fix this for 19.14. */
929 modeline_height = real_current_modeline_height (w);
932 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
933 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
937 return modeline_height;
940 /*****************************************************************************
941 margin_width_internal
943 For a given window, return the width in pixels of the specified margin.
944 ****************************************************************************/
946 margin_width_internal (struct window *w, int left_margin)
949 int window_cwidth = window_char_width (w, 1);
954 /* We might be getting called on a non-leaf. */
955 if (NILP (w->buffer))
958 /* The minibuffer never has margins. */
959 if (MINI_WINDOW_P (w))
962 XSETWINDOW (window, w);
963 b = XBUFFER (w->buffer);
964 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
965 XINT (w->right_margin_width));
967 default_face_height_and_width (window, 0, &font_width);
969 /* The left margin takes precedence over the right margin so we
970 subtract its width from the space available for the right
973 window_cwidth -= XINT (w->left_margin_width);
975 /* The margin cannot be wider than the window is. We allow the
976 value to be bigger since it is possible for the user to enlarge
977 the window such that the left margin value would no longer be too
978 big, but we won't return a value that is larger. */
979 if (margin_cwidth > window_cwidth)
980 margin_cwidth = window_cwidth;
982 /* At the user level the margin is always specified in characters.
983 Internally however it is manipulated in terms of pixels. */
984 return margin_cwidth * font_width;
988 window_left_margin_width (struct window *w)
990 return margin_width_internal (w, 1);
994 window_right_margin_width (struct window *w)
996 return margin_width_internal (w, 0);
999 /*****************************************************************************
1002 The gutters of a window are those areas in the boundary defined by
1003 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1004 do not contain text. Items which may be in the gutters include
1005 scrollbars, toolbars and modelines. The margin areas are not
1006 included. This is an exception made because redisplay special cases
1007 the handling of those areas in many places in such a way that
1008 including them in the gutter area would make life difficult.
1010 The size functions refer to height for the bottom and top gutters and
1011 width for the left and right gutters. The starting position
1012 functions refer to the Y coord for bottom and top gutters and the X
1013 coord for left and right gutters. All starting positions are
1014 relative to the frame, not the window.
1015 ****************************************************************************/
1018 window_top_window_gutter_height (struct window *w)
1020 if (!NILP (w->hchild) || !NILP (w->vchild))
1023 #ifdef HAVE_SCROLLBARS
1024 if (!NILP (w->scrollbar_on_top_p))
1025 return window_scrollbar_height (w);
1032 window_top_gutter_height (struct window *w)
1034 return window_top_window_gutter_height (w);
1038 window_bottom_window_gutter_height (struct window *w)
1042 if (!NILP (w->hchild) || !NILP (w->vchild))
1045 gutter = window_modeline_height (w);
1047 #ifdef HAVE_SCROLLBARS
1048 if (NILP (w->scrollbar_on_top_p))
1049 return window_scrollbar_height (w) + gutter;
1056 window_bottom_gutter_height (struct window *w)
1058 return window_bottom_window_gutter_height (w);
1062 window_left_window_gutter_width (struct window *w, int modeline)
1064 if (!NILP (w->hchild) || !NILP (w->vchild))
1067 #ifdef HAVE_SCROLLBARS
1068 if (!modeline && !NILP (w->scrollbar_on_left_p))
1069 return window_scrollbar_width (w);
1076 window_left_gutter_width (struct window *w, int modeline)
1078 return window_left_window_gutter_width (w, modeline);
1082 window_right_window_gutter_width (struct window *w, int modeline)
1086 if (!NILP (w->hchild) || !NILP (w->vchild))
1089 #ifdef HAVE_SCROLLBARS
1090 if (!modeline && NILP (w->scrollbar_on_left_p))
1091 gutter += window_scrollbar_width (w);
1094 if (window_needs_vertical_divider (w))
1095 gutter += window_divider_width (w);
1101 window_right_gutter_width (struct window *w, int modeline)
1103 return window_right_window_gutter_width (w, modeline);
1107 window_pixel_height (struct window* w)
1109 return WINDOW_HEIGHT (w);
1113 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1114 Return t if OBJECT is a window.
1118 return WINDOWP (object) ? Qt : Qnil;
1121 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1122 Return t if OBJECT is a window which is currently visible.
1126 return WINDOWP (object) && WINDOW_LIVE_P (XWINDOW (object))
1130 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1131 Return the window that the cursor now appears in and commands apply to.
1132 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1133 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1134 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1135 is a console, the selected frame on that console's selected device will
1136 be used. Otherwise, the selected frame is used.
1140 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1141 return Qnil; /* happens at startup */
1144 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1145 return FRAME_SELECTED_WINDOW (f);
1149 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1150 Return the last selected window that is not a minibuffer window.
1151 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1152 return the last non-minibuffer window used by that frame. If
1153 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1154 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1155 that console's selected device will be used. Otherwise, the selected
1160 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1161 return Qnil; /* happens at startup */
1164 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1165 return FRAME_LAST_NONMINIBUF_WINDOW (f);
1169 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1170 Return the window used now for minibuffers.
1171 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1172 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1173 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1174 is a console, the selected frame on that console's selected device will
1175 be used. Otherwise, the selected frame is used.
1179 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1182 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1183 Return non-nil if WINDOW is a minibuffer window.
1187 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1190 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1191 Return the first horizontal child of WINDOW, or nil.
1195 return decode_window (window)->hchild;
1198 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1199 Return the first vertical child of WINDOW, or nil.
1203 return decode_window (window)->vchild;
1206 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1207 Return the next window on the same level as WINDOW, or nil.
1211 return decode_window (window)->next;
1214 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1215 Return the previous window on the same level as WINDOW, or nil.
1219 return decode_window (window)->prev;
1222 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1223 Return the parent of WINDOW, or nil.
1227 return decode_window (window)->parent;
1230 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1231 Return non-nil if WINDOW is along the bottom of its frame.
1235 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1238 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1239 Return non-nil if WINDOW is along the top of its frame.
1243 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1246 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1247 Return non-nil if WINDOW is along the left edge of its frame.
1251 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1254 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1255 Return non-nil if WINDOW is along the right edge of its frame.
1259 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1262 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1263 Return t if position POS is currently on the frame in WINDOW.
1264 Returns nil if that position is scrolled vertically out of view.
1265 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1269 struct window *w = decode_window (window);
1270 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1272 struct buffer *buf = XBUFFER (w->buffer);
1275 posint = BUF_PT (buf);
1278 CHECK_INT_COERCE_MARKER (pos);
1279 posint = XINT (pos);
1282 if (posint < top || posint > BUF_ZV (buf))
1285 /* w->start can be out of range. If it is, do something reasonable. */
1286 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1289 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1294 decode_window (Lisp_Object window)
1297 return XWINDOW (Fselected_window (Qnil));
1299 CHECK_LIVE_WINDOW (window);
1300 return XWINDOW (window);
1303 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1304 Return the buffer that WINDOW is displaying.
1308 return decode_window (window)->buffer;
1311 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1312 Return the frame that window WINDOW is on.
1316 return decode_window (window)->frame;
1319 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1320 Return the number of default lines in WINDOW.
1321 This actually works by dividing the window's pixel height (including
1322 the modeline and horizontal scrollbar, if any) by the height of the
1323 default font; therefore, the number of displayed lines will probably
1325 Use `window-height' to get consistent results in geometry calculations.
1326 Use `window-displayed-height' to get the actual number of lines
1327 currently displayed in a window.
1329 The names are somewhat confusing; here's a table to help out:
1332 -------------------------------------------------------------------------
1334 (rows/columns) window-width window-text-area-height
1335 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1338 (rows/columns) window-full-width window-height
1339 (pixels) window-pixel-width window-pixel-height
1342 (rows/columns) ---- window-displayed-height
1343 (pixels) ---- window-displayed-text-pixel-height
1347 return make_int (window_char_height (decode_window (window), 1));
1350 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1351 Return the number of lines currently displayed in WINDOW.
1352 This counts the actual number of lines displayed in WINDOW
1353 \(as opposed to `window-height'). The modeline and horizontal
1354 scrollbar do not count as lines. If there is some blank space
1355 between the end of the buffer and the end of the window, this
1356 function pretends that there are lines of text in the default
1361 return make_int (window_displayed_height (decode_window (window)));
1364 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1365 Return the height of WINDOW in pixels. Defaults to current window.
1366 This includes the window's modeline and horizontal scrollbar (if any).
1370 return make_int (window_pixel_height (decode_window (window)));
1373 DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1374 Return the number of default lines in the text area of WINDOW.
1375 This actually works by dividing the window's text area pixel height (i.e.
1376 excluding the modeline and horizontal scrollbar, if any) by the height of the
1377 default font; therefore, the number of displayed lines will probably
1379 See also `window-height' and `window-displayed-height'.
1383 return make_int (window_char_height (decode_window (window), 0));
1386 DEFUN ("window-text-area-pixel-height",
1387 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1388 Return the height in pixels of the text-displaying portion of WINDOW.
1389 Unlike `window-pixel-height', the space occupied by the modeline and
1390 horizontal scrollbar, if any, is not counted.
1394 struct window *w = decode_window (window);
1396 return make_int (WINDOW_TEXT_HEIGHT (w));
1399 DEFUN ("window-displayed-text-pixel-height",
1400 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1401 Return the height in pixels of the text displayed in WINDOW.
1402 Unlike `window-text-area-pixel-height', any blank space below the
1403 end of the buffer is not included. If optional argument NOCLIPPED
1404 is non-nil, do not include space occupied by clipped lines.
1406 (window, noclipped))
1409 Bufpos start, eobuf;
1411 int hlimit, height, prev_height = -1;
1415 line_start_cache_dynarr *cache;
1418 window = Fselected_window (Qnil);
1420 CHECK_LIVE_WINDOW (window);
1421 w = XWINDOW (window);
1423 start = marker_position (w->start[CURRENT_DISP]);
1424 hlimit = WINDOW_TEXT_HEIGHT (w);
1425 eobuf = BUF_ZV (XBUFFER (w->buffer));
1427 default_face_height_and_width (window, &defheight, NULL);
1429 /* guess lines needed in line start cache + a few extra */
1430 needed = (hlimit + defheight-1) / defheight + 3;
1433 elt = point_in_line_start_cache (w, start, needed);
1434 assert (elt >= 0); /* in the cache */
1436 cache = w->line_start_cache;
1437 nelt = Dynarr_length (cache);
1440 for (i = elt; i < nelt; i++) {
1441 line = Dynarr_atp (cache, i)->height;
1443 if (height + line > hlimit)
1444 return make_int (!NILP (noclipped) ? height : hlimit);
1448 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1449 return make_int (height);
1452 /* get here => need more cache lines. try again. */
1453 assert(height > prev_height); /* progress? */
1454 prev_height = height;
1456 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1459 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1462 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1463 Return the number of display columns in WINDOW.
1464 This is the width that is usable columns available for text in WINDOW,
1465 and does not include vertical scrollbars, dividers, or the like. See also
1466 `window-full-width' and `window-height'.
1470 return make_int (window_char_width (decode_window (window), 0));
1473 DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1474 Return the total number of columns in WINDOW.
1475 This is like `window-width' but includes vertical scrollbars, dividers,
1480 return make_int (window_char_width (decode_window (window), 1));
1483 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1484 Return the width of WINDOW in pixels. Defaults to current window.
1488 return make_int (decode_window (window)->pixel_width);
1491 DEFUN ("window-text-area-pixel-width",
1492 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1493 Return the width in pixels of the text-displaying portion of WINDOW.
1494 Unlike `window-pixel-width', the space occupied by the vertical
1495 scrollbar or divider, if any, is not counted.
1499 struct window *w = decode_window (window);
1501 return make_int (WINDOW_TEXT_WIDTH (w));
1504 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1505 Return the number of columns by which WINDOW is scrolled from left margin.
1509 return make_int (decode_window (window)->hscroll);
1512 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1513 Return the horizontal scrolling amount of WINDOW's modeline.
1514 If the window has no modeline, return nil.
1518 struct window *w = decode_window (window);
1520 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
1524 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1525 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1526 If NCOL is negative, it will silently be forced to 0.
1527 If the window has no modeline, return nil. Otherwise, return the actual
1532 struct window *w = decode_window (window);
1534 if (WINDOW_HAS_MODELINE_P (w))
1539 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
1540 if (ncols != w->modeline_hscroll)
1542 MARK_MODELINE_CHANGED;
1543 w->modeline_hscroll = ncols;
1545 return make_int ((int) ncols);
1551 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1552 Set number of columns WINDOW is scrolled from left margin to NCOL.
1553 NCOL should be zero or positive.
1561 ncols = XINT (ncol);
1562 if (ncols < 0) ncols = 0;
1563 w = decode_window (window);
1564 if (w->hscroll != ncols)
1565 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1570 #if 0 /* bogus FSF crock */
1572 xxDEFUN ("window-redisplay-end-trigger",
1573 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1574 Return WINDOW's redisplay end trigger value.
1575 See `set-window-redisplay-end-trigger' for more information.
1579 return decode_window (window)->redisplay_end_trigger;
1582 xxDEFUN ("set-window-redisplay-end-trigger",
1583 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1584 Set WINDOW's redisplay end trigger value to VALUE.
1585 VALUE should be a buffer position (typically a marker) or nil.
1586 If it is a buffer position, then if redisplay in WINDOW reaches a position
1587 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1588 with two arguments: WINDOW, and the end trigger value.
1589 Afterwards the end-trigger value is reset to nil.
1593 return (decode_window (window)->redisplay_end_trigger = value);
1598 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1599 Return a list of the pixel edge coordinates of WINDOW.
1600 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1601 all relative to 0, 0 at the top left corner of WINDOW's frame.
1602 The frame toolbars, menubars and gutters are considered to be outside
1603 of this area, while the scrollbars are considered to be inside.
1607 struct window *w = decode_window (window);
1608 struct frame *f = XFRAME (w->frame);
1611 w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
1613 w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
1615 return list4 (make_int (left),
1617 make_int (left + w->pixel_width),
1618 make_int (top + w->pixel_height));
1621 DEFUN ("window-text-area-pixel-edges",
1622 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1623 Return a list of the pixel edge coordinates of the text area of WINDOW.
1624 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1625 all relative to 0, 0 at the top left corner of the total area allocated
1626 to the window, which includes the scrollbars.
1630 struct window *w = decode_window (window);
1632 int left = window_left_gutter_width (w, /* modeline = */ 0);
1633 int top = window_top_gutter_height (w);
1634 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1635 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1637 return list4 (make_int (left),
1643 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1644 Return current value of point in WINDOW.
1645 For a non-selected window, this is the value point would have
1646 if that window were selected.
1648 Note that, when WINDOW is the selected window and its buffer
1649 is also currently selected, the value returned is the same as (point).
1650 It would be more strictly correct to return the `top-level' value
1651 of point, outside of any save-excursion forms.
1652 But that value is hard to find.
1656 struct window *w = decode_window (window);
1658 /* The special check for current buffer is necessary for this
1659 function to work as defined when called within an excursion. */
1660 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1661 && current_buffer == XBUFFER (w->buffer))
1662 return Fpoint (Qnil);
1663 return Fmarker_position (w->pointm[CURRENT_DISP]);
1666 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1667 Return position at which display currently starts in WINDOW.
1668 This is updated by redisplay or by calling `set-window-start'.
1672 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1675 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1676 Return position at which display currently ends in WINDOW.
1677 This is updated by redisplay, when it runs to completion.
1678 Simply changing the buffer text or setting `window-start' does not
1679 update this value. WINDOW defaults to the selected window.
1681 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1682 to be the same value as this function would return at the end of the
1683 next full redisplay assuming nothing else changes in the meantime.
1684 This function is potentially much slower with this flag set.
1686 (window, guarantee))
1688 struct window *w = decode_window (window);
1690 if (NILP (guarantee))
1695 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1699 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1700 return make_int (end_of_last_line (w, startp));
1704 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1705 Return pixel height of visible part of last window line if it is clipped.
1706 If the last line is not clipped, return nil.
1710 struct window *w = decode_window (window);
1711 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1712 int num_lines = Dynarr_length (dla);
1713 struct display_line *dl;
1715 /* No lines - no clipped lines */
1716 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
1719 dl = Dynarr_atp (dla, num_lines - 1);
1723 return make_int (dl->ascent + dl->descent - dl->clip);
1726 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1727 Make point value in WINDOW be at position POS in WINDOW's buffer.
1731 struct window *w = decode_window (window);
1733 CHECK_INT_COERCE_MARKER (pos);
1734 if (w == XWINDOW (Fselected_window (Qnil)))
1735 Fgoto_char (pos, Qnil);
1737 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1743 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1744 Make display in WINDOW start at position POS in WINDOW's buffer.
1745 Optional third arg NOFORCE non-nil inhibits next redisplay
1746 from overriding motion of point in order to display at this exact start.
1748 (window, pos, noforce))
1750 struct window *w = decode_window (window);
1752 CHECK_INT_COERCE_MARKER (pos);
1753 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1754 /* this is not right, but much easier than doing what is right. */
1755 /* w->start_at_line_beg = 0; */
1756 /* WTF is the above supposed to mean? GE */
1757 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1758 marker_position (w->start[CURRENT_DISP]));
1761 w->redo_modeline = 1;
1762 SET_LAST_MODIFIED (w, 0);
1763 SET_LAST_FACECHANGE (w);
1765 MARK_WINDOWS_CHANGED (w);
1770 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1771 Return WINDOW's dedicated object, usually t or nil.
1772 See also `set-window-dedicated-p'.
1776 return decode_window (window)->dedicated;
1779 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1780 Control whether WINDOW is dedicated to the buffer it displays.
1781 If it is dedicated, Emacs will not automatically change
1782 which buffer appears in it.
1783 The second argument is the new value for the dedication flag;
1788 struct window *w = decode_window (window);
1790 w->dedicated = NILP (arg) ? Qnil : Qt;
1792 return w->dedicated;
1795 /* FSFmacs has window-display-table here. We have display table as a
1799 /* Record info on buffer window w is displaying
1800 when it is about to cease to display that buffer. */
1802 unshow_buffer (struct window *w)
1804 Lisp_Object buf = w->buffer;
1806 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1809 /* FSF disables this check, so I'll do it too. I hope it won't
1810 break things. --ben */
1812 if (w == XWINDOW (Fselected_window (Qnil))
1813 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1814 /* Do this except when the selected window's buffer
1815 is being removed from some other window. */
1817 /* last_window_start records the start position that this buffer
1818 had in the last window to be disconnected from it.
1819 Now that this statement is unconditional,
1820 it is possible for the buffer to be displayed in the
1821 selected window, while last_window_start reflects another
1822 window which was recently showing the same buffer.
1823 Some people might say that might be a good thing. Let's see. */
1824 XBUFFER (buf)->last_window_start =
1825 marker_position (w->start[CURRENT_DISP]);
1827 /* Point in the selected window's buffer
1828 is actually stored in that buffer, and the window's pointm isn't used.
1829 So don't clobber point in that buffer. */
1830 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1832 struct buffer *b= XBUFFER (buf);
1833 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1834 marker_position (w->pointm[CURRENT_DISP]),
1839 /* Put REPLACEMENT into the window structure in place of OLD. */
1841 replace_window (Lisp_Object old, Lisp_Object replacement)
1844 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1846 /* If OLD is its frame's root_window, then replacement is the new
1847 root_window for that frame. */
1849 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1850 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1852 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1853 WINDOW_TOP (p) = WINDOW_TOP (o);
1854 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1855 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1857 p->next = tem = o->next;
1859 XWINDOW (tem)->prev = replacement;
1861 p->prev = tem = o->prev;
1863 XWINDOW (tem)->next = replacement;
1865 p->parent = tem = o->parent;
1868 if (EQ (XWINDOW (tem)->vchild, old))
1869 XWINDOW (tem)->vchild = replacement;
1870 if (EQ (XWINDOW (tem)->hchild, old))
1871 XWINDOW (tem)->hchild = replacement;
1874 /* #### Here, if replacement is a vertical combination
1875 and so is its new parent, we should make replacement's
1876 children be children of that parent instead. */
1878 ERROR_CHECK_SUBWINDOW_CACHE (p);
1882 window_unmap_subwindows (struct window* w)
1884 assert (!NILP (w->subwindow_instance_cache));
1885 elisp_maphash (unmap_subwindow_instance_cache_mapper,
1886 w->subwindow_instance_cache, (void*)1);
1889 /* we're deleting W; set the structure of W to indicate this. */
1892 mark_window_as_deleted (struct window *w)
1894 /* The window instance cache is going away now, so need to get the
1895 cachels reset by redisplay. */
1896 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
1898 /* The cache is going away. If we leave unmapping to
1899 reset_subwindow_cachels then we get in a situation where the
1900 domain (the window) has been deleted but we still need access to
1901 its attributes in order to unmap windows properly. Since the
1902 subwindows are going to get GC'd anyway as a result of the domain
1903 going away, it is safer to just unmap them all while we know the
1904 domain is still valid. */
1905 ERROR_CHECK_SUBWINDOW_CACHE (w);
1906 window_unmap_subwindows (w);
1909 (while t (split-window) (delete-window))
1910 we end up with a tree of deleted windows which are all connected
1911 through the `next' slot. This might not seem so bad, as they're
1912 deleted, and will presumably be GCed - but if even *one* of those
1913 windows is still being pointed to, by the user, or by a window
1914 configuration, then *all* of those windows stick around.
1916 Since the window-configuration code doesn't need any of the
1917 pointers to other windows (they are all recreated from the
1918 window-config data), we set them all to nil so that we
1919 are able to collect more actual garbage. */
1925 w->subwindow_instance_cache = Qnil;
1929 /* Free the extra data structures attached to windows immediately so
1930 they don't sit around consuming excess space. They will be
1931 reinitialized by the window-configuration code as necessary. */
1932 finalize_window ((void *) w, 0);
1935 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1936 Remove WINDOW from the display. Default is selected window.
1937 If window is the only one on its frame, the frame is deleted as well.
1938 Normally, you cannot delete the last non-minibuffer-only frame (you must
1939 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1940 second argument FORCE is non-nil, you can delete the last frame. (This
1941 will automatically call `save-buffers-kill-emacs'.)
1945 /* This function can GC if this is the only window in the frame */
1953 /* Note: this function is called by other C code on non-leaf
1956 /* Do the equivalent of decode_window() but don't error out on
1957 deleted window; it's OK to delete an already-deleted window. */
1959 window = Fselected_window (Qnil);
1961 CHECK_WINDOW (window);
1963 w = XWINDOW (window);
1965 /* It's okay to delete an already-deleted window. */
1966 if (! WINDOW_LIVE_P (w))
1969 frame = WINDOW_FRAME (w);
1971 d = XDEVICE (FRAME_DEVICE (f));
1973 if (TOP_LEVEL_WINDOW_P (w))
1975 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1976 /* this frame isn't fully initialized yet; don't blow up. */
1979 if (MINI_WINDOW_P (XWINDOW (window)))
1980 error ("Attempt to delete the minibuffer window");
1982 /* It has been suggested that it's a good thing for C-x 0 to have this
1983 behavior, but not such a good idea for #'delete-window to have it.
1984 Maybe C-x 0 should be bound to something else, or maybe frame
1985 deletion should only happen when this is called interactively.
1987 delete_frame_internal (f, !NILP (force), 0, 0);
1991 /* At this point, we know the window has a parent. */
1993 par = XWINDOW (parent);
1995 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1996 /* It's quite likely that deleting a window will result in
1997 subwindows needing to be deleted also (since they are cached
1998 per-window). So we mark them as changed, so that the cachels will
1999 get reset by redisplay and thus deleted subwindows can get
2001 MARK_FRAME_SUBWINDOWS_CHANGED (f);
2003 /* Are we trying to delete any frame's selected window?
2004 Note that we could be dealing with a non-leaf window
2005 where the selected window is one of our children.
2006 So, we check by scanning all the ancestors of the
2007 frame's selected window and comparing each one with
2010 Lisp_Object pwindow;
2012 pwindow = FRAME_SELECTED_WINDOW (f);
2014 while (!NILP (pwindow))
2016 if (EQ (window, pwindow))
2018 pwindow = XWINDOW (pwindow)->parent;
2021 if (EQ (window, pwindow))
2023 /* OK, we found it. */
2024 Lisp_Object alternative;
2025 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
2027 /* If we're about to delete the selected window on the
2028 selected frame, then we should use Fselect_window to select
2029 the new window. On the other hand, if we're about to
2030 delete the selected window on any other frame, we shouldn't do
2031 anything but set the frame's selected_window slot. */
2032 if (EQ (frame, Fselected_frame (Qnil)))
2033 Fselect_window (alternative, Qnil);
2035 set_frame_selected_window (f, alternative);
2039 /* w->buffer is nil in a non-leaf window; in this case,
2040 get rid of the markers we maintain that point into that buffer. */
2041 if (!NILP (w->buffer))
2044 unchain_marker (w->pointm[CURRENT_DISP]);
2045 unchain_marker (w->pointm[DESIRED_DISP]);
2046 unchain_marker (w->pointm[CMOTION_DISP]);
2047 unchain_marker (w->start[CURRENT_DISP]);
2048 unchain_marker (w->start[DESIRED_DISP]);
2049 unchain_marker (w->start[CMOTION_DISP]);
2050 unchain_marker (w->sb_point);
2051 /* This breaks set-window-configuration if windows in the saved
2052 configuration get deleted and multiple frames are in use. */
2053 /* w->buffer = Qnil; */
2056 /* close up the hole in the sibling list */
2057 if (!NILP (w->next))
2058 XWINDOW (w->next)->prev = w->prev;
2059 if (!NILP (w->prev))
2060 XWINDOW (w->prev)->next = w->next;
2061 if (EQ (window, par->hchild))
2062 par->hchild = w->next;
2063 if (EQ (window, par->vchild))
2064 par->vchild = w->next;
2066 /* Find one of our siblings to give our space to. */
2068 Lisp_Object sib = w->prev;
2071 /* If w gives its space to its next sibling, that sibling needs
2072 to have its top/left side pulled back to where w's is.
2073 set_window_{height,width} will re-position the sibling's
2076 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
2077 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
2080 /* Stretch that sibling. */
2081 if (!NILP (par->vchild))
2082 set_window_pixheight
2083 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
2084 if (!NILP (par->hchild))
2086 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
2089 /* If parent now has only one child,
2090 put the child into the parent's place. */
2092 Lisp_Object parchild = par->hchild;
2093 if (NILP (parchild))
2094 parchild = par->vchild;
2095 if (NILP (XWINDOW (parchild)->next))
2097 replace_window (parent, parchild);
2098 mark_window_as_deleted (XWINDOW (parent));
2102 /* Since we may be deleting combination windows, we must make sure that
2103 not only W but all its children have been marked as deleted. */
2104 if (!NILP (w->hchild))
2105 delete_all_subwindows (XWINDOW (w->hchild));
2106 else if (!NILP (w->vchild))
2107 delete_all_subwindows (XWINDOW (w->vchild));
2109 mark_window_as_deleted (w);
2111 f->mirror_dirty = 1;
2116 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2117 Return the next window after WINDOW in the canonical ordering of windows.
2118 If omitted, WINDOW defaults to the selected window.
2120 Optional second arg MINIBUF t means count the minibuffer window even
2121 if not active. MINIBUF nil or omitted means count the minibuffer iff
2122 it is active. MINIBUF neither t nor nil means not to count the
2123 minibuffer even if it is active.
2125 Several frames may share a single minibuffer; if the minibuffer
2126 counts, all windows on all frames that share that minibuffer count
2127 too. Therefore, `next-window' can be used to iterate through the
2128 set of windows even when the minibuffer is on another frame. If the
2129 minibuffer does not count, only windows from WINDOW's frame count.
2131 By default, only the windows in the selected frame are considered.
2132 The optional argument WHICH-FRAMES changes this behavior:
2133 WHICH-FRAMES = `visible' means search windows on all visible frames.
2134 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2135 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2136 WHICH-FRAMES = a frame means search only windows on that frame.
2137 Anything else means restrict to the selected frame.
2139 The optional fourth argument WHICH-DEVICES further clarifies on which
2140 devices to search for frames as specified by WHICH-FRAMES. This value
2141 is only meaningful if WHICH-FRAMES is non-nil.
2142 If nil or omitted, search all devices on the selected console.
2143 If a device, only search that device.
2144 If a console, search all devices on that console.
2145 If a device type, search all devices of that type.
2146 If `window-system', search all window-system devices.
2147 Any other non-nil value means search all devices.
2149 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2150 you can use `next-window' to iterate through the entire cycle of
2151 acceptable windows, eventually ending up back at the window you started with.
2152 `previous-window' traverses the same cycle, in the reverse order.
2154 (window, minibuf, which_frames, which_devices))
2157 Lisp_Object start_window;
2160 window = Fselected_window (Qnil);
2162 CHECK_LIVE_WINDOW (window);
2164 start_window = window;
2166 /* minibuf == nil may or may not include minibuffers.
2167 Decide if it does. */
2169 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2170 else if (! EQ (minibuf, Qt))
2172 /* Now `minibuf' is one of:
2173 t => count all minibuffer windows
2174 lambda => count none of them
2175 or a specific minibuffer window (the active one) to count. */
2177 /* which_frames == nil doesn't specify which frames to include. */
2178 if (NILP (which_frames))
2179 which_frames = (! EQ (minibuf, Qlambda)
2180 ? (FRAME_MINIBUF_WINDOW
2183 (XWINDOW (window)))))
2185 else if (EQ (which_frames, Qvisible))
2187 else if (ZEROP (which_frames))
2189 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2190 /* If which_frames is a frame and window arg isn't on that frame, just
2191 return the first window on the frame. */
2192 return frame_first_window (XFRAME (which_frames));
2193 else if (! EQ (which_frames, Qt))
2194 which_frames = Qnil;
2195 /* Now `which_frames' is one of:
2196 t => search all frames
2197 nil => search just the current frame
2198 visible => search just visible frames
2199 0 => search visible and iconified frames
2200 a window => search the frame that window belongs to. */
2202 /* Do this loop at least once, to get the next window, and perhaps
2203 again, if we hit the minibuffer and that is not acceptable. */
2206 /* Find a window that actually has a next one. This loop
2207 climbs up the tree. */
2208 while (tem = XWINDOW (window)->next, NILP (tem))
2209 if (tem = XWINDOW (window)->parent, !NILP (tem))
2211 else /* window must be minibuffer window now */
2213 /* We've reached the end of this frame.
2214 Which other frames are acceptable? */
2215 tem = WINDOW_FRAME (XWINDOW (window));
2217 if (! NILP (which_frames))
2219 Lisp_Object tem1 = tem;
2220 tem = next_frame (tem, which_frames, which_devices);
2222 /* In the case where the minibuffer is active,
2223 and we include its frame as well as the selected one,
2224 next_frame may get stuck in that frame.
2225 If that happens, go back to the selected frame
2226 so we can complete the cycle. */
2228 XSETFRAME (tem, selected_frame ());
2231 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2237 /* If we're in a combination window, find its first child and
2238 recurse on that. Otherwise, we've found the window we want. */
2241 if (!NILP (XWINDOW (window)->hchild))
2242 window = XWINDOW (window)->hchild;
2243 else if (!NILP (XWINDOW (window)->vchild))
2244 window = XWINDOW (window)->vchild;
2248 /* Which windows are acceptable?
2249 Exit the loop and accept this window if
2250 this isn't a minibuffer window,
2251 or we're accepting all minibuffer windows,
2252 or this is the active minibuffer and we are accepting that one, or
2253 we've come all the way around and we're back at the original window. */
2254 while (MINI_WINDOW_P (XWINDOW (window))
2255 && ! EQ (minibuf, Qt)
2256 && ! EQ (minibuf, window)
2257 && ! EQ (window, start_window));
2262 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2263 Return the window preceding WINDOW in the canonical ordering of windows.
2264 If omitted, WINDOW defaults to the selected window.
2266 Optional second arg MINIBUF t means count the minibuffer window even
2267 if not active. MINIBUF nil or omitted means count the minibuffer iff
2268 it is active. MINIBUF neither t nor nil means not to count the
2269 minibuffer even if it is active.
2271 Several frames may share a single minibuffer; if the minibuffer
2272 counts, all windows on all frames that share that minibuffer count
2273 too. Therefore, `previous-window' can be used to iterate through
2274 the set of windows even when the minibuffer is on another frame. If
2275 the minibuffer does not count, only windows from WINDOW's frame count.
2277 By default, only the windows in the selected frame are considered.
2278 The optional argument WHICH-FRAMES changes this behavior:
2279 WHICH-FRAMES = `visible' means search windows on all visible frames.
2280 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2281 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2282 WHICH-FRAMES = a frame means search only windows on that frame.
2283 Anything else means restrict to the selected frame.
2285 The optional fourth argument WHICH-DEVICES further clarifies on which
2286 devices to search for frames as specified by WHICH-FRAMES. This value
2287 is only meaningful if WHICH-FRAMES is non-nil.
2288 If nil or omitted, search all devices on the selected console.
2289 If a device, only search that device.
2290 If a console, search all devices on that console.
2291 If a device type, search all devices of that type.
2292 If `window-system', search all window-system devices.
2293 Any other non-nil value means search all devices.
2295 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2296 you can use `previous-window' to iterate through the entire cycle of
2297 acceptable windows, eventually ending up back at the window you started with.
2298 `next-window' traverses the same cycle, in the reverse order.
2300 (window, minibuf, which_frames, devices))
2303 Lisp_Object start_window;
2306 window = Fselected_window (Qnil);
2308 CHECK_LIVE_WINDOW (window);
2310 start_window = window;
2312 /* minibuf == nil may or may not include minibuffers.
2313 Decide if it does. */
2315 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2316 else if (! EQ (minibuf, Qt))
2318 /* Now `minibuf' is one of:
2319 t => count all minibuffer windows
2320 lambda => count none of them
2321 or a specific minibuffer window (the active one) to count. */
2323 /* which_frames == nil doesn't specify which frames to include.
2324 Decide which frames it includes. */
2325 if (NILP (which_frames))
2326 which_frames = (! EQ (minibuf, Qlambda)
2327 ? (FRAME_MINIBUF_WINDOW
2330 (XWINDOW (window)))))
2332 else if (EQ (which_frames, Qvisible))
2334 else if (ZEROP (which_frames))
2336 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2337 /* If which_frames is a frame and window arg isn't on that frame, just
2338 return the first window on the frame. */
2339 return frame_first_window (XFRAME (which_frames));
2340 else if (! EQ (which_frames, Qt))
2341 which_frames = Qnil;
2342 /* Now `which_frames' is one of:
2343 t => search all frames
2344 nil => search just the current frame
2345 visible => search just visible frames
2346 0 => search visible and iconified frames
2347 a window => search the frame that window belongs to. */
2349 /* Do this loop at least once, to get the next window, and perhaps
2350 again, if we hit the minibuffer and that is not acceptable. */
2353 /* Find a window that actually has a next one. This loop
2354 climbs up the tree. */
2355 while (tem = XWINDOW (window)->prev, NILP (tem))
2356 if (tem = XWINDOW (window)->parent, !NILP (tem))
2358 else /* window must be minibuffer window now */
2360 /* We have found the top window on the frame.
2361 Which frames are acceptable? */
2362 tem = WINDOW_FRAME (XWINDOW (window));
2364 if (! NILP (which_frames))
2365 /* It's actually important that we use previous_frame here,
2366 rather than next_frame. All the windows acceptable
2367 according to the given parameters should form a ring;
2368 Fnext_window and Fprevious_window should go back and
2369 forth around the ring. If we use next_frame here,
2370 then Fnext_window and Fprevious_window take different
2371 paths through the set of acceptable windows.
2372 window_loop assumes that these `ring' requirement are
2375 Lisp_Object tem1 = tem;
2376 tem = previous_frame (tem, which_frames, devices);
2377 /* In the case where the minibuffer is active,
2378 and we include its frame as well as the selected one,
2379 next_frame may get stuck in that frame.
2380 If that happens, go back to the selected frame
2381 so we can complete the cycle. */
2383 XSETFRAME (tem, selected_frame ());
2386 /* If this frame has a minibuffer, find that window first,
2387 because it is conceptually the last window in that frame. */
2388 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2389 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2391 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2398 /* If we're in a combination window, find its first child and
2399 recurse on that. Otherwise, we've found the window we want. */
2402 if (!NILP (XWINDOW (window)->hchild))
2403 window = XWINDOW (window)->hchild;
2404 else if (!NILP (XWINDOW (window)->vchild))
2405 window = XWINDOW (window)->vchild;
2407 while (tem = XWINDOW (window)->next, !NILP (tem))
2411 /* Which windows are acceptable?
2412 Exit the loop and accept this window if
2413 this isn't a minibuffer window,
2414 or we're accepting all minibuffer windows,
2415 or this is the active minibuffer and we are accepting that one, or
2416 we've come all the way around and we're back at the original window. */
2417 while (MINI_WINDOW_P (XWINDOW (window))
2418 && ! EQ (minibuf, Qt)
2419 && ! EQ (minibuf, window)
2420 && ! EQ (window, start_window));
2425 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2426 Return the next window which is vertically after WINDOW.
2431 struct window *w = decode_window (window);
2432 XSETWINDOW (window, w);
2434 if (MINI_WINDOW_P (XWINDOW (window)))
2437 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2439 if (EQ (window, root))
2442 if (!NILP (XWINDOW (window)->hchild))
2443 window = XWINDOW (window)->hchild;
2444 else if (!NILP (XWINDOW (window)->vchild))
2445 window = XWINDOW (window)->vchild;
2452 if (!NILP (XWINDOW (window)->parent) &&
2453 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2455 if (!NILP (XWINDOW (window)->next))
2456 return XWINDOW (window)->next;
2458 window = XWINDOW (window)->parent;
2461 window = XWINDOW (window)->parent;
2463 while (!EQ (window, root));
2466 if (!NILP (XWINDOW (window)->hchild))
2467 window = XWINDOW (window)->hchild;
2468 else if (!NILP (XWINDOW (window)->vchild))
2469 window = XWINDOW (window)->vchild;
2474 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2475 Select the COUNT'th different window on this frame.
2476 All windows on current frame are arranged in a cyclic order.
2477 This command selects the window COUNT steps away in that order.
2478 A negative COUNT moves in the opposite order.
2480 By default, only the windows in the selected frame are considered.
2481 The optional argument WHICH-FRAMES changes this behavior:
2482 WHICH-FRAMES = `visible' means search windows on all visible frames.
2483 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2484 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2485 WHICH-FRAMES = a frame means search only windows on that frame.
2486 Anything else means restrict to the selected frame.
2488 The optional argument WHICH-DEVICES further clarifies on which devices
2489 to search for frames as specified by WHICH-FRAMES. This value is only
2490 meaningful if WHICH-FRAMES is non-nil.
2491 If nil or omitted, search all devices on the selected console.
2492 If a device, only search that device.
2493 If a console, search all devices on that console.
2494 If a device type, search all devices of that type.
2495 If `window-system', search all window-system devices.
2496 Any other non-nil value means search all devices.
2498 (count, which_frames, which_devices))
2504 w = Fselected_window (Qnil);
2509 w = Fnext_window (w, Qnil, which_frames, which_devices);
2514 w = Fprevious_window (w, Qnil, which_frames, which_devices);
2517 Fselect_window (w, Qnil);
2522 /* Look at all windows, performing an operation specified by TYPE
2525 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2526 frame. If FRAMES is a frame, just look at windows on that frame.
2527 If MINI is non-zero, perform the operation on minibuffer windows too.
2533 GET_BUFFER_WINDOW, /* Arg is buffer */
2534 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2535 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2536 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2537 UNDEDICATE_BUFFER, /* 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 UNDEDICATE_BUFFER:
2692 if ((XBUFFER (p->buffer) == XBUFFER (obj)) && (p->dedicated))
2693 p->dedicated = Qnil;
2697 case DELETE_OTHER_WINDOWS:
2699 /* Don't delete the last window on a frame; this can
2700 happen when the minibuffer is selected, and would
2701 cause the frame to be deleted. */
2702 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2703 Fdelete_window (w, Qnil);
2707 case DELETE_BUFFER_WINDOWS:
2709 if (EQ (p->buffer, obj))
2711 struct frame *f = XFRAME (WINDOW_FRAME (p));
2713 /* If this window is dedicated, and in a frame
2714 of its own, kill the frame. */
2715 if (EQ (w, FRAME_ROOT_WINDOW (f))
2716 && !NILP (p->dedicated)
2717 && other_visible_frames (f))
2719 /* Skip the other windows on this frame.
2720 There might be one, the minibuffer! */
2721 if (! EQ (w, last_window))
2722 while (f == XFRAME (WINDOW_FRAME
2723 (XWINDOW (next_window))))
2725 /* As we go, check for the end of the
2726 loop. We mustn't start going
2727 around a second time. */
2728 if (EQ (next_window, last_window))
2733 next_window = Fnext_window (next_window,
2737 /* Now we can safely delete the frame. */
2738 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2741 /* If we're deleting the buffer displayed in
2742 the only window on the frame, find a new
2743 buffer to display there. */
2744 if (NILP (p->parent))
2746 Lisp_Object new_buffer;
2747 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2748 if (NILP (new_buffer))
2749 new_buffer = Fget_buffer_create (QSscratch);
2750 Fset_window_buffer (w, new_buffer, Qnil);
2751 if (EQ (w, Fselected_window (Qnil)))
2752 Fset_buffer (p->buffer);
2755 Fdelete_window (w, Qnil);
2760 case GET_LARGEST_WINDOW:
2762 /* Ignore dedicated windows and minibuffers. */
2763 if (MINI_WINDOW_P (p)
2764 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2767 /* write the check as follows to avoid tripping
2768 error_check_window() --ben */
2769 struct window *b = NILP (best_window) ? 0 :
2770 XWINDOW (best_window);
2771 if (NILP (best_window)
2772 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2773 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2783 if (EQ (w, last_window))
2790 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2793 #if 0 /* not currently used */
2796 buffer_window_count (struct buffer *b, struct frame *f)
2798 Lisp_Object buffer, frame;
2800 XSETFRAME (frame, f);
2801 XSETBUFFER (buffer, b);
2803 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2808 buffer_window_mru (struct window *w)
2810 Lisp_Object window =
2811 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2815 else if (XWINDOW (window) == w)
2824 undedicate_windows (Lisp_Object buffer, Lisp_Object frame)
2826 window_loop (UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2830 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2831 Return the window least recently selected or used for display.
2833 By default, only the windows in the selected frame are considered.
2834 The optional argument WHICH-FRAMES changes this behavior:
2835 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2836 If WHICH-FRAMES is 0, search all visible and iconified frames.
2837 If WHICH-FRAMES is t, search all frames.
2838 If WHICH-FRAMES is nil, search only the selected frame.
2839 If WHICH-FRAMES is a frame, search only that frame.
2841 The optional argument WHICH-DEVICES further clarifies on which devices
2842 to search for frames as specified by WHICH-FRAMES. This value is only
2843 meaningful if WHICH-FRAMES is non-nil.
2844 If nil or omitted, search all devices on the selected console.
2845 If a device, only search that device.
2846 If a console, search all devices on that console.
2847 If a device type, search all devices of that type.
2848 If `window-system', search all devices on window-system consoles.
2849 Any other non-nil value means search all devices.
2851 (which_frames, which_devices))
2854 /* First try for a non-dedicated window that is full-width */
2855 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2856 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2859 /* Then try for any non-dedicated window */
2860 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices);
2861 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2865 /* FSFmacs never returns a dedicated window here. If we do,
2866 it makes `display-buffer' not work right. #### All of this
2867 shit is so disgusting and awful that it needs to be rethought
2869 /* then try for a dedicated window that is full-width */
2870 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2871 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2874 /* If none of them, then all windows, dedicated or not. */
2875 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
2877 /* At this point we damn well better have found something. */
2878 if (NILP (w)) abort ();
2884 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2885 Return the window largest in area.
2887 By default, only the windows in the selected frame are considered.
2888 The optional argument WHICH-FRAMES changes this behavior:
2889 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2890 If WHICH-FRAMES is 0, search all visible and iconified frames.
2891 If WHICH-FRAMES is t, search all frames.
2892 If WHICH-FRAMES is nil, search only the selected frame.
2893 If WHICH-FRAMES is a frame, search only that frame.
2895 The optional argument WHICH-DEVICES further clarifies on which devices
2896 to search for frames as specified by WHICH-FRAMES. This value is only
2897 meaningful if WHICH-FRAMES is non-nil.
2898 If nil or omitted, search all devices on the selected console.
2899 If a device, only search that device.
2900 If a console, search all devices on that console.
2901 If a device type, search all devices of that type.
2902 If `window-system', search all devices on window-system consoles.
2903 Any other non-nil value means search all devices.
2905 (which_frames, which_devices))
2907 /* Don't search dedicated windows because FSFmacs doesn't.
2908 This stuff is all black magic so don't try to apply common
2910 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2911 which_frames, 0, which_devices);
2914 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2915 Return a window currently displaying BUFFER, or nil if none.
2917 By default, only the windows in the selected frame are considered.
2918 The optional argument WHICH-FRAMES changes this behavior:
2919 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2920 If WHICH-FRAMES is 0, search all visible and iconified frames.
2921 If WHICH-FRAMES is t, search all frames.
2922 If WHICH-FRAMES is nil, search only the selected frame.
2923 If WHICH-FRAMES is a frame, search only that frame.
2925 The optional argument WHICH-DEVICES further clarifies on which devices
2926 to search for frames as specified by WHICH-FRAMES. This value is only
2927 meaningful if WHICH-FRAMES is non-nil.
2928 If nil or omitted, search all devices on the selected console.
2929 If a device, only search that device.
2930 If a console, search all devices on that console.
2931 If a device type, search all devices of that type.
2932 If `window-system', search all devices on window-system consoles.
2933 Any other non-nil value means search all devices.
2935 (buffer, which_frames, which_devices))
2937 buffer = Fget_buffer (buffer);
2938 if (BUFFERP (buffer))
2939 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2940 return window_loop (GET_BUFFER_WINDOW, buffer, 1,
2941 which_frames, 1, which_devices);
2946 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2947 but there is no sensible way to implement those functions, since
2948 you can't in general derive a window from a buffer. */
2950 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2952 Return the width in pixels of the left outside margin of window WINDOW.
2953 If WINDOW is nil, the selected window is assumed.
2957 return make_int (window_left_margin_width (decode_window (window)));
2960 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2962 Return the width in pixels of the right outside margin of window WINDOW.
2963 If WINDOW is nil, the selected window is assumed.
2967 return make_int (window_right_margin_width (decode_window (window)));
2970 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2971 Make WINDOW (or the selected window) fill its frame.
2972 Only the frame WINDOW is on is affected.
2973 This function tries to reduce display jumps
2974 by keeping the text previously visible in WINDOW
2975 in the same place on the frame. Doing this depends on
2976 the value of (window-start WINDOW), so if calling this function
2977 in a program gives strange scrolling, make sure the window-start
2978 value is reasonable when this function is called.
2982 struct window *w = decode_window (window);
2983 struct buffer *b = XBUFFER (w->buffer);
2985 int old_top = WINDOW_TOP (w);
2987 XSETWINDOW (window, w);
2989 if (MINI_WINDOW_P (w) && old_top > 0)
2990 error ("Can't expand minibuffer to full frame");
2992 /* Ignore dedicated windows. */
2993 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2995 start_pos = marker_position (w->start[CURRENT_DISP]);
2997 /* Try to minimize scrolling, by setting the window start to the
2998 point which will cause the text at the old window start to be at
2999 the same place on the frame. But don't try to do this if the
3000 window start is outside the visible portion (as might happen when
3001 the display is not current, due to typeahead). */
3002 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
3003 && !MINI_WINDOW_P (w))
3005 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
3007 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
3009 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
3011 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3013 /* We need to do this, so that the window-scroll-functions
3021 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3022 "bDelete windows on (buffer): ", /*
3023 Delete all windows showing BUFFER.
3025 Optional second argument WHICH-FRAMES controls which frames are affected.
3026 If nil or omitted, delete all windows showing BUFFER in any frame.
3027 If t, delete only windows showing BUFFER in the selected frame.
3028 If `visible', delete all windows showing BUFFER in any visible frame.
3029 If a frame, delete only windows showing BUFFER in that frame.
3030 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3031 except that the meanings of nil and t are reversed.
3033 The optional third argument WHICH-DEVICES further clarifies on which
3034 devices to search for frames as specified by WHICH-FRAMES. This value
3035 is only meaningful if WHICH-FRAMES is not t.
3036 If nil or omitted, search only the selected console.
3037 If a device, only search that device.
3038 If a console, search all devices on that console.
3039 If a device type, search all devices of that type.
3040 If `window-system', search all devices on a window system.
3041 Any other non-nil value means search all devices.
3043 (buffer, which_frames, which_devices))
3045 /* This function can GC */
3046 buffer = Fget_buffer (buffer);
3047 CHECK_BUFFER (buffer);
3049 /* WHICH-FRAMES values t and nil mean the opposite of what
3050 window_loop expects. */
3051 if (EQ (which_frames, Qnil))
3053 else if (EQ (which_frames, Qt))
3054 which_frames = Qnil;
3056 /* Ignore dedicated windows. */
3057 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0,
3058 which_frames, 0, which_devices);
3063 list_windows (struct window *w, Lisp_Object value)
3067 if (!NILP (w->hchild))
3068 value = list_windows (XWINDOW (w->hchild), value);
3069 else if (!NILP (w->vchild))
3070 value = list_windows (XWINDOW (w->vchild), value);
3074 XSETWINDOW (window, w);
3075 value = Fcons (window, value);
3079 w = XWINDOW (w->next);
3085 list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec)
3087 Lisp_Object devcons, concons;
3088 Lisp_Object retval = Qnil;
3090 DEVICE_LOOP_NO_BREAK (devcons, concons)
3092 Lisp_Object frame_list, the_window;
3093 Lisp_Object device, tail;
3095 device = XCAR (devcons);
3096 frame_list = DEVICE_FRAME_LIST (XDEVICE (device));
3098 LIST_LOOP (tail, frame_list)
3100 if ((NILP (frame_spec)
3101 && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device))))
3102 || (EQ (frame_spec, Qvisible)
3103 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail))))
3104 || (FRAMEP (frame_spec)
3105 && !EQ (frame_spec, XCAR (tail)))
3106 || (!NILP (frame_spec)
3107 && !device_matches_device_spec (device,
3108 NILP (device_spec) ?
3112 the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail)));
3113 retval = list_windows (XWINDOW (the_window), retval);
3116 return Fnreverse (retval);
3119 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3,
3120 "bReplace buffer in windows: ", /*
3121 Replace BUFFER with some other buffer in all windows showing it.
3123 Optional second argument WHICH-FRAMES controls which frames are affected.
3124 If nil or omitted, all frames are affected.
3125 If t, only the selected frame is affected.
3126 If `visible', all visible frames are affected.
3127 If a frame, only that frame is affected.
3128 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3129 except that the meanings of nil and t are reversed.
3131 The optional third argument WHICH-DEVICES further clarifies on which
3132 devices to search for frames as specified by WHICH-FRAMES. This value
3133 is only meaningful if WHICH-FRAMES is not t.
3134 If nil or omitted, search only the selected console.
3135 If a device, only search that device.
3136 If a console, search all devices on that console.
3137 If a device type, search all devices of that type.
3138 If `window-system', search all devices on a window system.
3139 Any other non-nil value means search all devices.
3141 (buffer, which_frames, which_devices))
3143 /* This function can GC */
3144 Lisp_Object window_list;
3146 struct gcpro gcpro1, gcpro2;
3148 if (EQ (which_frames, Qnil))
3150 else if (EQ (which_frames, Qt))
3151 which_frames = Qnil;
3152 window_list = list_all_windows (which_frames, which_devices);
3154 buffer = Fget_buffer (buffer);
3155 CHECK_BUFFER (buffer);
3157 GCPRO2 (window_list, buffer);
3158 LIST_LOOP (tail, window_list)
3160 Lisp_Object window = XCAR (tail);
3161 if (!MINI_WINDOW_P (XWINDOW (window))
3162 && EQ (XWINDOW (window)->buffer, buffer))
3164 Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil);
3165 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
3166 if (NILP (another_buffer))
3167 another_buffer = Fget_buffer_create (QSscratch);
3168 if (!NILP (XWINDOW (window)->dedicated)
3170 FRAME_ROOT_WINDOW (XFRAME (frame)))
3171 && other_visible_frames (XFRAME (frame)))
3173 delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */
3177 Fset_window_buffer (window, another_buffer, Qnil);
3178 if (EQ (window, Fselected_window (Qnil)))
3179 Fset_buffer (XWINDOW (window)->buffer);
3187 /* The smallest acceptable dimensions for a window. Anything smaller
3188 might crash Emacs. */
3189 #define MIN_SAFE_WINDOW_WIDTH (2)
3190 #define MIN_SAFE_WINDOW_HEIGHT (2)
3192 /* Make sure that window_min_height and window_min_width are
3193 not too small; if they are, set them to safe minima. */
3196 check_min_window_sizes (void)
3198 /* Smaller values might permit a crash. */
3199 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3200 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3201 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3202 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3206 frame_min_height (struct frame *frame)
3208 /* For height, we have to see whether the frame has a minibuffer, and
3209 whether it wants a modeline. */
3210 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3211 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3212 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3215 /* Return non-zero if both frame sizes are less than or equal to
3216 minimal allowed values. ROWS and COLS are in characters */
3218 frame_size_valid_p (struct frame *frame, int rows, int cols)
3220 return (rows >= frame_min_height (frame)
3221 && cols >= MIN_SAFE_WINDOW_WIDTH);
3224 /* Return non-zero if both frame sizes are less than or equal to
3225 minimal allowed values. WIDTH and HEIGHT are in pixels */
3227 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3230 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3231 return frame_size_valid_p (frame, rows, cols);
3234 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3235 minimum allowable size. */
3237 check_frame_size (struct frame *frame, int *rows, int *cols)
3239 int min_height = frame_min_height (frame);
3241 if (*rows < min_height)
3243 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3244 *cols = MIN_SAFE_WINDOW_WIDTH;
3247 /* Normally the window is deleted if it gets too small.
3248 nodelete nonzero means do not do this.
3249 (The caller should check later and do so if appropriate) */
3251 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3254 struct window *w = XWINDOW (window);
3255 struct frame *f = XFRAME (w->frame);
3257 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3258 Lisp_Object child, minor_kid, major_kid;
3261 int defheight, defwidth;
3263 /* #### This is very likely incorrect and instead the char_to_pixel_
3264 functions should be called. */
3265 default_face_height_and_width (window, &defheight, &defwidth);
3266 line_size = (set_height ? defheight : defwidth);
3268 check_min_window_sizes ();
3270 minsize = (set_height ? window_min_height : window_min_width);
3271 minsize *= line_size;
3274 && !TOP_LEVEL_WINDOW_P (w)
3275 && new_pixsize < minsize)
3277 Fdelete_window (window, Qnil);
3281 SET_LAST_MODIFIED (w, 0);
3282 SET_LAST_FACECHANGE (w);
3283 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3286 WINDOW_HEIGHT (w) = new_pixsize;
3287 major_kid = w->vchild;
3288 minor_kid = w->hchild;
3292 WINDOW_WIDTH (w) = new_pixsize;
3293 major_kid = w->hchild;
3294 minor_kid = w->vchild;
3297 if (!NILP (minor_kid))
3299 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3302 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3304 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3306 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3309 else if (!NILP (major_kid))
3311 int last_pos, last_old_pos, pos, old_pos, first;
3312 int pixel_adj_left = new_pixsize - old_pixsize;
3313 int div_val = old_pixsize << 1;
3316 * Previously we bailed out here if there was no size change.
3317 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3318 * toolbar appears or disappears, windows may not change size,
3319 * but their top and left coordinates need to be updated.
3321 * So we don't bail until after the loop below.
3324 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3327 for (child = major_kid; !NILP (child); child = c->next)
3329 c = XWINDOW (child);
3333 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3334 WINDOW_TOP (c) = last_pos;
3338 old_pos = last_old_pos + WINDOW_WIDTH (c);
3339 WINDOW_LEFT (c) = last_pos;
3342 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3343 /* All but the last window should have a height which is
3344 a multiple of the default line height. */
3345 if (!NILP (c->next))
3346 pos = (pos / line_size) * line_size;
3348 /* Avoid confusion: don't delete child if it becomes too small */
3349 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3351 last_pos = pos + first;
3352 last_old_pos = old_pos;
3355 /* Sometimes we may get called with our old size. In that case
3356 we don't need to do anything else. */
3357 if (!pixel_adj_left)
3360 /* Now delete any children that became too small. */
3362 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3365 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3367 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3372 /* Set the height of WINDOW and all its inferiors. */
3374 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3376 set_window_pixsize (window, new_pixheight, nodelete, 1);
3379 /* Recursively set width of WINDOW and its inferiors. */
3381 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3383 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3387 static int window_select_count;
3389 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3390 Make WINDOW display BUFFER as its contents.
3391 BUFFER can be a buffer or buffer name.
3393 With non-nil optional argument NORECORD, do not modify the
3394 global or per-frame buffer ordering.
3396 (window, buffer, norecord))
3399 struct window *w = decode_window (window);
3400 int old_buffer_local_face_property = 0;
3402 buffer = Fget_buffer (buffer);
3403 CHECK_BUFFER (buffer);
3405 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3406 error ("Attempt to display deleted buffer");
3410 error ("Window is deleted");
3412 /* While this seems like a logical thing to do, it causes problems
3413 because of saved window configurations. It is possible for a
3414 buffer to get restored into a window in which it is already being
3415 displayed, but start and point are actually at completely
3416 different locations. So we let this function complete fully and
3417 it will then make sure redisplay correctly updates things.
3419 #### This is a kludge. The correct approach is not to do this
3420 but to fix set-window-configuration. */
3422 else if (EQ (tem, buffer))
3425 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3426 is first being set up. */
3428 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3429 error ("Window is dedicated to buffer %s",
3430 XSTRING_DATA (XBUFFER (tem)->name));
3432 old_buffer_local_face_property =
3433 XBUFFER (w->buffer)->buffer_local_face_property;
3438 w->window_end_pos[CURRENT_DISP] = 0;
3440 w->modeline_hscroll = 0;
3441 Fset_marker (w->pointm[CURRENT_DISP],
3442 make_int (BUF_PT (XBUFFER (buffer))),
3444 set_marker_restricted (w->start[CURRENT_DISP],
3445 make_int (XBUFFER (buffer)->last_window_start),
3447 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3448 /* set start_at_line_beg correctly. GE */
3449 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3450 marker_position (w->start[CURRENT_DISP]));
3451 w->force_start = 0; /* Lucid fix */
3452 SET_LAST_MODIFIED (w, 1);
3453 SET_LAST_FACECHANGE (w);
3454 MARK_WINDOWS_CHANGED (w);
3456 int new_buffer_local_face_property =
3457 XBUFFER (w->buffer)->buffer_local_face_property;
3459 if (new_buffer_local_face_property
3460 || new_buffer_local_face_property != old_buffer_local_face_property)
3461 MARK_WINDOW_FACES_CHANGED (w);
3463 recompute_all_cached_specifiers_in_window (w);
3464 if (EQ (window, Fselected_window (Qnil)))
3466 if (NILP (norecord))
3467 Frecord_buffer (buffer);
3469 Fset_buffer (buffer);
3474 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3475 Select WINDOW. Most editing will apply to WINDOW's buffer.
3476 The main editor command loop selects the buffer of the selected window
3477 before each command.
3479 With non-nil optional argument NORECORD, do not modify the
3480 global or per-frame buffer ordering.
3485 Lisp_Object old_selected_window = Fselected_window (Qnil);
3487 CHECK_LIVE_WINDOW (window);
3488 w = XWINDOW (window);
3490 /* we have already caught dead-window errors */
3491 if (!NILP (w->hchild) || !NILP (w->vchild))
3492 error ("Trying to select non-leaf window");
3494 w->use_time = make_int (++window_select_count);
3496 if (EQ (window, old_selected_window))
3499 /* deselect the old window, if it exists (it might not exist if
3500 the selected device has no frames, which occurs at startup) */
3501 if (!NILP (old_selected_window))
3503 struct window *ow = XWINDOW (old_selected_window);
3505 Fset_marker (ow->pointm[CURRENT_DISP],
3506 make_int (BUF_PT (XBUFFER (ow->buffer))),
3509 MARK_WINDOWS_CHANGED (ow);
3512 /* now select the window's frame */
3513 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3515 select_frame_1 (WINDOW_FRAME (w));
3517 /* also select the window's buffer */
3518 if (NILP (norecord))
3519 Frecord_buffer (w->buffer);
3520 Fset_buffer (w->buffer);
3522 /* Go to the point recorded in the window.
3523 This is important when the buffer is in more
3524 than one window. It also matters when
3525 redisplay_window has altered point after scrolling,
3526 because it makes the change only in the window. */
3528 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3529 if (new_point < BUF_BEGV (current_buffer))
3530 new_point = BUF_BEGV (current_buffer);
3531 else if (new_point > BUF_ZV (current_buffer))
3532 new_point = BUF_ZV (current_buffer);
3534 BUF_SET_PT (current_buffer, new_point);
3537 MARK_WINDOWS_CHANGED (w);
3543 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3544 Lisp_Object override_frame)
3546 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3550 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3552 /* This function can GC */
3555 struct buffer *b = XBUFFER (buf);
3557 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3558 widen_buffer (b, 0);
3559 BUF_SET_PT (b, BUF_BEG (b));
3561 if (!NILP (Vtemp_buffer_show_function))
3562 call1 (Vtemp_buffer_show_function, buf);
3565 window = display_buffer (buf, Qnil, same_frame);
3567 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3568 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3570 Vminibuffer_scroll_window = window;
3571 w = XWINDOW (window);
3573 w->modeline_hscroll = 0;
3574 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3575 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3576 set_marker_restricted (w->sb_point, make_int (1), buf);
3578 /* Run temp-buffer-show-hook, with the chosen window selected. */
3579 if (!preparing_for_armageddon)
3582 tem = Fboundp (Qtemp_buffer_show_hook);
3585 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3588 int count = specpdl_depth ();
3590 /* Select the window that was chosen, for running
3592 record_unwind_protect (save_window_excursion_unwind,
3593 Fcurrent_window_configuration (Qnil));
3595 Fselect_window (window, Qnil);
3596 run_hook (Qtemp_buffer_show_hook);
3597 unbind_to (count, Qnil);
3605 make_dummy_parent (Lisp_Object window)
3608 struct window *o = XWINDOW (window);
3609 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3611 XSETWINDOW (new, p);
3612 copy_lcrecord (p, o);
3614 /* Don't copy the pointers to the line start cache or the face
3616 p->line_start_cache = Dynarr_new (line_start_cache);
3617 p->face_cachels = Dynarr_new (face_cachel);
3618 p->glyph_cachels = Dynarr_new (glyph_cachel);
3619 p->subwindow_instance_cache =
3620 make_image_instance_cache_hash_table ();
3622 /* Put new into window structure in place of window */
3623 replace_window (window, new);
3631 p->start[CURRENT_DISP] = Qnil;
3632 p->start[DESIRED_DISP] = Qnil;
3633 p->start[CMOTION_DISP] = Qnil;
3634 p->pointm[CURRENT_DISP] = Qnil;
3635 p->pointm[DESIRED_DISP] = Qnil;
3636 p->pointm[CMOTION_DISP] = Qnil;
3641 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3642 Split WINDOW, putting SIZE lines in the first of the pair.
3643 WINDOW defaults to the selected one and SIZE to half its size.
3644 If optional third arg HORFLAG is non-nil, split side by side
3645 and put SIZE columns in the first of the pair.
3647 (window, size, horflag))
3650 struct window *o, *p;
3656 window = Fselected_window (Qnil);
3658 CHECK_LIVE_WINDOW (window);
3660 o = XWINDOW (window);
3661 f = XFRAME (WINDOW_FRAME (o));
3665 if (!NILP (horflag))
3666 /* In the new scheme, we are symmetric with respect to separators
3667 so there is no need to do weird things here. */
3669 psize = WINDOW_WIDTH (o) >> 1;
3670 csize = window_pixel_width_to_char_width (o, psize, 0);
3674 psize = WINDOW_HEIGHT (o) >> 1;
3675 csize = window_pixel_height_to_char_height (o, psize, 1);
3681 csize = XINT (size);
3682 if (!NILP (horflag))
3683 psize = window_char_width_to_pixel_width (o, csize, 0);
3685 psize = window_char_height_to_pixel_height (o, csize, 1);
3688 if (MINI_WINDOW_P (o))
3689 error ("Attempt to split minibuffer window");
3690 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3691 error ("Attempt to split unsplittable frame");
3693 check_min_window_sizes ();
3697 if (csize < window_min_height)
3698 error ("Window height %d too small (after splitting)", csize);
3699 if (csize + window_min_height > window_char_height (o, 1))
3700 error ("Window height %d too small (after splitting)",
3701 window_char_height (o, 1) - csize);
3702 if (NILP (o->parent)
3703 || NILP (XWINDOW (o->parent)->vchild))
3705 make_dummy_parent (window);
3707 /* #### I can't understand why you have to reset face
3708 cachels here. This can cause crash so let's disable it
3709 and see the difference. See redisplay-tests.el --yh */
3710 reset_face_cachels (XWINDOW (window));
3713 XWINDOW (new)->vchild = window;
3714 XFRAME (o->frame)->mirror_dirty = 1;
3719 if (csize < window_min_width)
3720 error ("Window width %d too small (after splitting)", csize);
3721 if (csize + window_min_width > window_char_width (o, 0))
3722 error ("Window width %d too small (after splitting)",
3723 window_char_width (o, 0) - csize);
3724 if (NILP (o->parent)
3725 || NILP (XWINDOW (o->parent)->hchild))
3727 make_dummy_parent (window);
3729 /* #### See above. */
3730 reset_face_cachels (XWINDOW (window));
3733 XWINDOW (new)->hchild = window;
3734 XFRAME (o->frame)->mirror_dirty = 1;
3738 /* Now we know that window's parent is a vertical combination
3739 if we are dividing vertically, or a horizontal combination
3740 if we are making side-by-side windows */
3742 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3743 new = allocate_window ();
3746 p->frame = o->frame;
3748 if (!NILP (p->next))
3749 XWINDOW (p->next)->prev = new;
3752 p->parent = o->parent;
3755 reset_face_cachels (p);
3756 reset_glyph_cachels (p);
3759 /* Apportion the available frame space among the two new windows */
3761 if (!NILP (horflag))
3763 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3764 WINDOW_TOP (p) = WINDOW_TOP (o);
3765 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3766 WINDOW_WIDTH (o) = psize;
3767 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3771 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3772 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3773 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3774 WINDOW_HEIGHT (o) = psize;
3775 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3778 XFRAME (p->frame)->mirror_dirty = 1;
3779 /* do this last (after the window is completely initialized and
3780 the mirror-dirty flag is set) so that specifier recomputation
3781 caused as a result of this will work properly and not abort. */
3782 Fset_window_buffer (new, o->buffer, Qt);
3787 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3788 Make the selected window COUNT lines taller.
3789 From program, optional second arg HORIZONTALP non-nil means grow
3790 sideways COUNT columns, and optional third arg WINDOW specifies the
3791 window to change instead of the selected window.
3793 (count, horizontalp, window))
3796 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0);
3800 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3801 Make the selected window COUNT pixels taller.
3802 From program, optional second arg HORIZONTALP non-nil means grow
3803 sideways COUNT pixels, and optional third arg WINDOW specifies the
3804 window to change instead of the selected window.
3806 (count, horizontalp, window))
3809 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1);
3813 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3814 Make the selected window COUNT lines shorter.
3815 From program, optional second arg HORIZONTALP non-nil means shrink
3816 sideways COUNT columns, and optional third arg WINDOW specifies the
3817 window to change instead of the selected window.
3819 (count, horizontalp, window))
3822 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0);
3826 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3827 Make the selected window COUNT pixels smaller.
3828 From program, optional second arg HORIZONTALP non-nil means shrink
3829 sideways COUNT pixels, and optional third arg WINDOW specifies the
3830 window to change instead of the selected window.
3832 (count, horizontalp, window))
3835 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1);
3840 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3841 int include_gutters_p)
3844 int defheight, defwidth;
3848 XSETWINDOW (window, w);
3850 avail_height = (pixel_height -
3851 (include_gutters_p ? 0 :
3852 window_top_window_gutter_height (w) +
3853 window_bottom_window_gutter_height (w)));
3855 default_face_height_and_width (window, &defheight, &defwidth);
3857 char_height = avail_height / defheight;
3859 /* It's the calling function's responsibility to check these values
3860 and make sure they're not out of range.
3862 #### We need to go through the calling functions and actually
3864 return max (0, char_height);
3868 window_char_height_to_pixel_height (struct window *w, int char_height,
3869 int include_gutters_p)
3872 int defheight, defwidth;
3877 XSETWINDOW (window, w);
3879 default_face_height_and_width (window, &defheight, &defwidth);
3881 avail_height = char_height * defheight;
3882 pixel_height = (avail_height +
3883 (include_gutters_p ? 0 :
3884 window_top_window_gutter_height (w) +
3885 window_bottom_window_gutter_height (w)));
3887 /* It's the calling function's responsibility to check these values
3888 and make sure they're not out of range.
3890 #### We need to go through the calling functions and actually
3892 return max (0, pixel_height);
3895 /* Return number of default lines of text can fit in the window W.
3896 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3897 horizontal scrollbar) in the space that is used for the calculation.
3898 This doesn't include space used by the frame gutters.
3901 window_char_height (struct window *w, int include_gutters_p)
3903 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3908 * Return number of lines currently displayed in window w. If
3909 * end-of-buffer is displayed then the area below end-of-buffer is assume
3910 * to be blank lines of default height.
3911 * Does not include the modeline.
3914 window_displayed_height (struct window *w)
3916 struct buffer *b = XBUFFER (w->buffer);
3917 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3919 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3921 : w->window_end_pos[CURRENT_DISP]);
3923 if (!Dynarr_length (dla))
3924 return window_char_height (w, 0);
3926 num_lines = Dynarr_length (dla);
3928 /* #### Document and assert somewhere that w->window_end_pos == -1
3929 indicates that end-of-buffer is being displayed. */
3932 struct display_line *dl = Dynarr_atp (dla, 0);
3933 int ypos1 = dl->ypos + dl->descent;
3934 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3936 int defheight, defwidth;
3938 XSETWINDOW (window, w);
3944 if (Dynarr_length (dla) == 1)
3945 ypos1 = WINDOW_TEXT_TOP (w);
3948 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3949 /* If this line is clipped then we know that there is no
3950 blank room between eob and the modeline. If we are
3951 scrolling on clipped lines just know off the clipped
3953 if (scroll_on_clipped_lines && dl->clip)
3954 return num_lines - 1;
3955 ypos1 = dl->ypos + dl->descent - dl->clip;
3959 default_face_height_and_width (window, &defheight, &defwidth);
3960 /* #### This probably needs to know about the clipping area once a
3961 final definition is decided on. */
3962 num_lines += ((ypos2 - ypos1) / defheight);
3966 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3969 if (scroll_on_clipped_lines
3970 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3978 window_pixel_width (Lisp_Object window)
3980 return WINDOW_WIDTH (XWINDOW (window));
3983 /* Calculate the pixel of a window, optionally including margin space
3984 but no vertical gutters. */
3986 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3987 int include_margins_p)
3991 int defheight, defwidth;
3994 XSETWINDOW (window, w);
3996 avail_width = (pixel_width -
3997 window_left_gutter_width (w, 0) -
3998 window_right_gutter_width (w, 0) -
3999 (include_margins_p ? 0 : window_left_margin_width (w)) -
4000 (include_margins_p ? 0 : window_right_margin_width (w)));
4002 default_face_height_and_width (window, &defheight, &defwidth);
4004 char_width = (avail_width / defwidth);
4006 /* It's the calling function's responsibility to check these values
4007 and make sure they're not out of range.
4009 #### We need to go through the calling functions and actually
4011 return max (0, char_width);
4015 window_char_width_to_pixel_width (struct window *w, int char_width,
4016 int include_margins_p)
4020 int defheight, defwidth;
4023 XSETWINDOW (window, w);
4025 default_face_height_and_width (window, &defheight, &defwidth);
4027 avail_width = char_width * defwidth;
4028 pixel_width = (avail_width +
4029 window_left_window_gutter_width (w, 0) +
4030 window_right_window_gutter_width (w, 0) +
4031 (include_margins_p ? 0 : window_left_margin_width (w)) +
4032 (include_margins_p ? 0 : window_right_margin_width (w)));
4034 /* It's the calling function's responsibility to check these values
4035 and make sure they're not out of range.
4037 #### We need to go through the calling functions and actually
4039 return max (0, pixel_width);
4042 /* This returns the usable space which doesn't include space needed by
4043 scrollbars or divider lines. */
4045 window_char_width (struct window *w, int include_margins_p)
4047 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
4051 #define MINSIZE(w) \
4053 ? window_min_width * defwidth \
4054 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4057 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4059 #define CURSIZE(w) \
4060 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4062 #define CURCHARSIZE(w) \
4063 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4065 #define MINCHARSIZE(window) \
4066 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4067 ? 1 : window_min_height)
4070 window_pixheight (Lisp_Object w)
4072 return window_pixel_height (XWINDOW (w));
4075 /* Unlike set_window_pixheight, this function
4076 also changes the heights of the siblings so as to
4077 keep everything consistent. */
4080 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp,
4083 struct window *win = decode_window (window);
4084 int widthflag = !NILP (horizontalp);
4089 int (*sizefun) (Lisp_Object) = (widthflag
4090 ? window_pixel_width
4091 : window_pixheight);
4092 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4093 ? set_window_pixwidth
4094 : set_window_pixheight);
4096 int defheight, defwidth;
4101 check_min_window_sizes ();
4103 XSETWINDOW (window, win);
4104 f = XFRAME (win->frame);
4105 if (EQ (window, FRAME_ROOT_WINDOW (f)))
4106 error ("Won't change only window");
4108 /* #### This is very likely incorrect and instead the char_to_pixel_
4109 functions should be called. */
4110 default_face_height_and_width (window, &defheight, &defwidth);
4114 w = XWINDOW (window);
4119 error ("No other window to side of this one");
4123 ? !NILP (XWINDOW (parent)->hchild)
4124 : !NILP (XWINDOW (parent)->vchild))
4129 sizep = &CURSIZE (w);
4130 dim = CURCHARSIZE (w);
4132 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4133 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4135 if (MINI_WINDOW_P (XWINDOW (window)))
4137 else if (!NILP (parent))
4139 Fdelete_window (window, Qnil);
4145 delta *= (widthflag ? defwidth : defheight);
4150 maxdelta = ((!NILP (parent))
4151 ? (*sizefun) (parent) - *sizep
4152 : ((!NILP (w->next))
4153 ? (*sizefun) (w->next) - MINSIZE (w->next)
4154 : ((!NILP (w->prev))
4155 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4156 /* This is a frame with only one window,
4157 a minibuffer-only or a minibufferless frame. */
4160 if (delta > maxdelta)
4161 /* This case traps trying to make the minibuffer
4162 the full frame, or make the only window aside from the
4163 minibuffer the full frame. */
4170 /* #### Chuck: is this correct? */
4171 if (*sizep + delta < MINSIZE (window))
4173 Fdelete_window (window);
4179 if (!NILP (w->next) &&
4180 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4182 CURBEG (XWINDOW (w->next)) += delta;
4183 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4184 (*setsizefun) (window, *sizep + delta, 0);
4186 else if (!NILP (w->prev) &&
4187 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4189 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4190 CURBEG (w) -= delta;
4191 (*setsizefun) (window, *sizep + delta, 0);
4196 int opht = (*sizefun) (parent);
4198 /* If trying to grow this window to or beyond size of the parent,
4199 make delta1 so big that, on shrinking back down,
4200 all the siblings end up with less than one line and are deleted. */
4201 if (opht <= *sizep + delta)
4202 delta1 = opht * opht * 2;
4203 /* Otherwise, make delta1 just right so that if we add delta1
4204 lines to this window and to the parent, and then shrink
4205 the parent back to its original size, the new proportional
4206 size of this window will increase by delta. */
4208 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4210 /* Add delta1 lines or columns to this window, and to the parent,
4211 keeping things consistent while not affecting siblings. */
4212 CURSIZE (XWINDOW (parent)) = opht + delta1;
4213 (*setsizefun) (window, *sizep + delta1, 0);
4215 /* Squeeze out delta1 lines or columns from our parent,
4216 shrinking this window and siblings proportionately.
4217 This brings parent back to correct size.
4218 Delta1 was calculated so this makes this window the desired size,
4219 taking it all out of the siblings. */
4220 (*setsizefun) (parent, opht, 0);
4223 SET_LAST_MODIFIED (w, 0);
4224 SET_LAST_FACECHANGE (w);
4225 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4226 /* overkill maybe, but better to be correct */
4227 MARK_FRAME_GUTTERS_CHANGED (f);
4237 /* Scroll contents of window WINDOW up COUNT lines.
4238 If COUNT < (top line height / average line height) then we just adjust
4241 window_scroll (Lisp_Object window, Lisp_Object count, int direction,
4242 Error_behavior errb)
4244 struct window *w = XWINDOW (window);
4245 struct buffer *b = XBUFFER (w->buffer);
4246 int selected = EQ (window, Fselected_window (Qnil));
4248 Lisp_Object point, tem;
4249 display_line_dynarr *dla;
4250 int fheight, fwidth, modeline = 0;
4251 struct display_line* dl;
4254 point = make_int (BUF_PT (b));
4257 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4259 if (pos < BUF_BEGV (b))
4261 else if (pos > BUF_ZV (b))
4264 point = make_int (pos);
4267 /* Always set force_start so that redisplay_window will run
4268 the window-scroll-functions. */
4271 /* #### When the fuck does this happen? I'm so glad that history has
4272 completely documented the behavior of the scrolling functions under
4273 all circumstances. */
4274 tem = Fpos_visible_in_window_p (point, window);
4277 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4279 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4280 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4281 WINDOW_TEXT_TOP_CLIP (w) = 0;
4282 MARK_WINDOWS_CHANGED (w);
4287 if (EQ (count, Qminus))
4291 count = Fprefix_numeric_value (count);
4292 value = XINT (count) * direction;
4295 return; /* someone just made a pointless call */
4299 /* If the user didn't specify how far to scroll then we have to figure it
4300 out by ourselves. */
4301 if (NILP (count) || EQ (count, Qminus))
4303 /* Going forwards is easy. If that is what we are doing then just
4304 set value and the section which handles the user specifying a
4305 positive value will work. */
4308 value = window_displayed_height (w) - next_screen_context_lines;
4309 value = (value < 1 ? 1 : value);
4312 /* Going backwards is hard. We can't use the same loop used if the
4313 user specified a negative value because we care about
4314 next_screen_context_lines. In a variable height world you don't
4315 know how many lines above you can actually be displayed and still
4316 have the context lines appear. So we leave value set to 0 and add
4317 a separate section to deal with this. */
4321 if (direction == 1 && !value)
4326 /* Determine parameters to test for partial line scrolling with. */
4327 dla = window_display_lines (w, CURRENT_DISP);
4329 if (INTP (Vwindow_pixel_scroll_increment))
4330 fheight = XINT (Vwindow_pixel_scroll_increment);
4331 else if (!NILP (Vwindow_pixel_scroll_increment))
4332 default_face_height_and_width (window, &fheight, &fwidth);
4334 if (Dynarr_length (dla) >= 1)
4335 modeline = Dynarr_atp (dla, 0)->modeline;
4337 dl = Dynarr_atp (dla, modeline);
4341 /* Go for partial display line scrolling. This just means bumping
4342 the clip by a reasonable amount and redisplaying, everything else
4343 remains unchanged. */
4344 if (!NILP (Vwindow_pixel_scroll_increment)
4346 Dynarr_length (dla) >= (1 + modeline)
4348 (dl->ascent - dl->top_clip) > fheight * value)
4350 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4351 MARK_WINDOWS_CHANGED (w);
4356 Bufpos startp, old_start;
4358 if (WINDOW_TEXT_TOP_CLIP (w))
4360 WINDOW_TEXT_TOP_CLIP (w) = 0;
4361 MARK_WINDOWS_CHANGED (w);
4364 old_start = marker_position (w->start[CURRENT_DISP]);
4365 startp = vmotion (w, old_start, value, &vtarget);
4367 if (vtarget < value &&
4368 (w->window_end_pos[CURRENT_DISP] == -1
4369 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4371 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4376 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4379 w->start_at_line_beg = beginning_of_line_p (b, startp);
4380 MARK_WINDOWS_CHANGED (w);
4382 if (!point_would_be_visible (w, startp, XINT (point)))
4385 BUF_SET_PT (b, startp);
4387 set_marker_restricted (w->pointm[CURRENT_DISP],
4396 /* Go for partial display line scrolling. This just means bumping
4397 the clip by a reasonable amount and redisplaying, everything else
4398 remains unchanged. */
4399 if (!NILP (Vwindow_pixel_scroll_increment)
4401 Dynarr_length (dla) >= (1 + modeline)
4403 (dl->ascent - dl->top_clip) - fheight * value <
4404 (dl->ascent + dl->descent - dl->clip)
4406 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4408 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4409 MARK_WINDOWS_CHANGED (w);
4414 Bufpos startp, old_start;
4416 if (WINDOW_TEXT_TOP_CLIP (w))
4418 WINDOW_TEXT_TOP_CLIP (w) = 0;
4419 MARK_WINDOWS_CHANGED (w);
4422 old_start = marker_position (w->start[CURRENT_DISP]);
4423 startp = vmotion (w, old_start, value, &vtarget);
4426 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4428 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4433 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4436 w->start_at_line_beg = beginning_of_line_p (b, startp);
4437 MARK_WINDOWS_CHANGED (w);
4439 /* #### Scroll back by less than a line. This code was
4440 originally for scrolling over large pixmaps and it
4441 loses when a line being *exposed* at the top of the
4442 window is bigger than the current one. However, for
4443 pixel based scrolling in general we can guess that
4444 the line we are going to display is probably the same
4445 size as the one we are on. In that instance we can
4446 have a reasonable stab at a suitable top clip. Fixing
4447 this properly is hard (and probably slow) as we would
4448 have to call redisplay to figure out the exposed line
4450 if (!NILP (Vwindow_pixel_scroll_increment)
4451 && Dynarr_length (dla) >= (1 + modeline)
4452 && dl->ascent + fheight * value > 0)
4454 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4457 if (!point_would_be_visible (w, startp, XINT (point)))
4461 if (MINI_WINDOW_P (w))
4464 new_point = start_of_last_line (w, startp);
4467 BUF_SET_PT (b, new_point);
4469 set_marker_restricted (w->pointm[CURRENT_DISP],
4470 make_int (new_point),
4476 else /* value == 0 && direction == -1 */
4478 if (WINDOW_TEXT_TOP_CLIP (w))
4480 WINDOW_TEXT_TOP_CLIP (w) = 0;
4481 MARK_WINDOWS_CHANGED (w);
4483 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4485 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4491 int movement = next_screen_context_lines - 1;
4492 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4493 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4495 start_with_point_on_display_line (w, bottom,
4496 -1 - (movement - vtarget));
4498 if (startp >= old_startp)
4499 startp = vmotion (w, old_startp, -1, NULL);
4501 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4504 w->start_at_line_beg = beginning_of_line_p (b, startp);
4505 MARK_WINDOWS_CHANGED (w);
4507 if (!point_would_be_visible (w, startp, XINT (point)))
4509 Bufpos new_point = start_of_last_line (w, startp);
4512 BUF_SET_PT (b, new_point);
4514 set_marker_restricted (w->pointm[CURRENT_DISP],
4515 make_int (new_point),
4522 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4523 Scroll text of current window up COUNT lines; or near full screen if no arg.
4524 A near full screen is `next-screen-context-lines' less than a full screen.
4525 Negative COUNT means scroll downward.
4526 When calling from a program, supply an integer as argument or nil.
4527 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4528 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4531 The characters that are moved over may be added to the current selection
4532 \(i.e. active region) if the Shift key is held down, a motion key is used
4533 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4534 the documentation for this variable for more details.
4538 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME);
4542 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4543 Scroll text of current window down COUNT lines; or near full screen if no arg.
4544 A near full screen is `next-screen-context-lines' less than a full screen.
4545 Negative COUNT means scroll upward.
4546 When calling from a program, supply a number as argument or nil.
4547 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4548 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4551 The characters that are moved over may be added to the current selection
4552 \(i.e. active region) if the Shift key is held down, a motion key is used
4553 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4554 the documentation for this variable for more details.
4558 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME);
4562 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4563 Return the other window for "other window scroll" commands.
4564 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4565 specifies the window.
4566 If `other-window-scroll-buffer' is non-nil, a window
4567 showing that buffer is used.
4572 Lisp_Object selected_window = Fselected_window (Qnil);
4574 if (MINI_WINDOW_P (XWINDOW (selected_window))
4575 && !NILP (Vminibuffer_scroll_window))
4576 window = Vminibuffer_scroll_window;
4577 /* If buffer is specified, scroll that buffer. */
4578 else if (!NILP (Vother_window_scroll_buffer))
4580 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4582 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4586 /* Nothing specified; look for a neighboring window on the same
4588 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4590 if (EQ (window, selected_window))
4591 /* That didn't get us anywhere; look for a window on another
4594 window = Fnext_window (window, Qnil, Qt, Qnil);
4595 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4596 && ! EQ (window, selected_window));
4599 CHECK_LIVE_WINDOW (window);
4601 if (EQ (window, selected_window))
4602 error ("There is no other window");
4607 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4608 Scroll next window upward COUNT lines; or near full frame if no arg.
4609 The next window is the one below the current one; or the one at the top
4610 if the current one is at the bottom. Negative COUNT means scroll downward.
4611 When calling from a program, supply a number as argument or nil.
4613 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4614 specifies the window to scroll.
4615 If `other-window-scroll-buffer' is non-nil, scroll the window
4616 showing that buffer, popping the buffer up if necessary.
4620 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME);
4624 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4625 Scroll selected window display COUNT columns left.
4626 Default for COUNT is window width minus 2.
4628 The characters that are moved over may be added to the current selection
4629 \(i.e. active region) if the Shift key is held down, a motion key is used
4630 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4631 the documentation for this variable for more details.
4635 Lisp_Object window = Fselected_window (Qnil);
4636 struct window *w = XWINDOW (window);
4637 int n = (NILP (count) ?
4638 window_char_width (w, 0) - 2 :
4639 XINT (Fprefix_numeric_value (count)));
4641 return Fset_window_hscroll (window, make_int (w->hscroll + n));
4644 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4645 Scroll selected window display COUNT columns right.
4646 Default for COUNT is window width minus 2.
4648 The characters that are moved over may be added to the current selection
4649 \(i.e. active region) if the Shift key is held down, a motion key is used
4650 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4651 the documentation for this variable for more details.
4655 Lisp_Object window = Fselected_window (Qnil);
4656 struct window *w = XWINDOW (window);
4657 int n = (NILP (count) ?
4658 window_char_width (w, 0) - 2 :
4659 XINT (Fprefix_numeric_value (count)));
4661 return Fset_window_hscroll (window, make_int (w->hscroll - n));
4664 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4665 Center point in WINDOW. With N, put point on line N.
4666 The desired position of point is always relative to the window.
4667 If WINDOW is nil, the selected window is used.
4671 struct window *w = decode_window (window);
4672 struct buffer *b = XBUFFER (w->buffer);
4673 Bufpos opoint = BUF_PT (b);
4677 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4680 n = Fprefix_numeric_value (n);
4682 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4685 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4687 w->start_at_line_beg = beginning_of_line_p (b, startp);
4689 MARK_WINDOWS_CHANGED (w);
4693 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4694 Position point relative to WINDOW.
4695 With no argument, position text at center of window.
4696 An argument specifies window line; zero means top of window,
4697 negative means relative to bottom of window.
4698 If WINDOW is nil, the selected window is used.
4705 Bufpos start, new_point;
4708 /* Don't use decode_window() because we need the new value of
4711 window = Fselected_window (Qnil);
4713 CHECK_LIVE_WINDOW (window);
4714 w = XWINDOW (window);
4715 b = XBUFFER (w->buffer);
4717 height = window_displayed_height (w);
4718 selected = EQ (window, Fselected_window (w->frame));
4724 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4725 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4727 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4730 BUF_SET_PT (b, new_point);
4732 Fset_window_point (window, make_int (new_point));
4734 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4738 start = marker_position (w->start[CURRENT_DISP]);
4739 if (start < BUF_BEGV (b))
4740 start = BUF_BEGV (b);
4741 else if (start > BUF_ZV (b))
4745 new_point = BUF_PT (b);
4747 new_point = marker_position (w->pointm[CURRENT_DISP]);
4749 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4752 BUF_SET_PT (b, new_point);
4754 Fset_window_point (window, make_int (new_point));
4756 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4759 return make_int (retval);
4763 /* #### Is this going to work right when at eob? */
4764 arg = Fprefix_numeric_value (arg);
4766 XSETINT (arg, XINT (arg) + height);
4769 start = marker_position (w->start[CURRENT_DISP]);
4770 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4773 new_point = BUF_PT (b);
4775 new_point = marker_position (w->pointm[CURRENT_DISP]);
4777 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4780 BUF_SET_PT (b, new_point);
4782 Fset_window_point (window, make_int (new_point));
4784 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4786 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4792 BUF_SET_PT (b, start);
4794 Fset_window_point (window, make_int (start));
4798 return Fvertical_motion (arg, window, Qnil);
4802 new_point = vmotion (XWINDOW (window),
4803 marker_position (w->pointm[CURRENT_DISP]),
4805 Fset_window_point (window, make_int (new_point));
4806 return make_int (vpos);
4812 map_windows_1 (Lisp_Object window,
4813 int (*mapfun) (struct window *w, void *closure),
4816 for (; !NILP (window); window = XWINDOW (window)->next)
4819 struct window *w = XWINDOW (window);
4821 if (!NILP (w->vchild))
4822 retval = map_windows_1 (w->vchild, mapfun, closure);
4823 else if (!NILP (w->hchild))
4824 retval = map_windows_1 (w->hchild, mapfun, closure);
4826 retval = (mapfun) (w, closure);
4835 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4836 invocation of MAPFUN. If any invocation of MAPFUN returns
4837 non-zero, the mapping is halted. Otherwise, map_windows() maps
4838 over all windows in F.
4840 If MAPFUN creates or deletes windows, the behavior is undefined. */
4843 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4847 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4850 Lisp_Object frmcons, devcons, concons;
4852 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4854 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4866 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4869 w->shadow_thickness_changed = 1;
4870 MARK_WINDOWS_CHANGED (w);
4874 vertical_divider_changed_in_window (Lisp_Object specifier,
4878 MARK_WINDOWS_CHANGED (w);
4879 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4882 /* also used in scrollbar.c */
4884 some_window_value_changed (Lisp_Object specifier, struct window *w,
4887 MARK_WINDOWS_CHANGED (w);
4890 #ifdef MEMORY_USAGE_STATS
4896 #ifdef HAVE_SCROLLBARS
4900 int other_redisplay;
4905 compute_window_mirror_usage (struct window_mirror *mir,
4906 struct window_stats *stats,
4907 struct overhead_stats *ovstats)
4911 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4913 #ifdef HAVE_SCROLLBARS
4915 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4918 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4921 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4924 #endif /* HAVE_SCROLLBARS */
4925 stats->other_redisplay +=
4926 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4927 stats->other_redisplay +=
4928 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4932 compute_window_usage (struct window *w, struct window_stats *stats,
4933 struct overhead_stats *ovstats)
4936 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4937 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4938 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4939 stats->line_start +=
4940 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4941 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4944 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4945 Return stats about the memory usage of window WINDOW.
4946 The values returned are in the form of an alist of usage types and byte
4947 counts. The byte counts attempt to encompass all the memory used
4948 by the window (separate from the memory logically associated with a
4949 buffer or frame), including internal structures and any malloc()
4950 overhead associated with them. In practice, the byte counts are
4951 underestimated because certain memory usage is very hard to determine
4952 \(e.g. the amount of memory used inside the Xt library or inside the
4953 X server) and because there is other stuff that might logically
4954 be associated with a window, buffer, or frame (e.g. window configurations,
4955 glyphs) but should not obviously be included in the usage counts.
4957 Multiple slices of the total memory usage may be returned, separated
4958 by a nil. Each slice represents a particular view of the memory, a
4959 particular way of partitioning it into groups. Within a slice, there
4960 is no overlap between the groups of memory, and each slice collectively
4961 represents all the memory concerned.
4965 struct window_stats stats;
4966 struct overhead_stats ovstats;
4967 Lisp_Object val = Qnil;
4969 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4971 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4973 val = acons (Qface_cache, make_int (stats.face), val);
4974 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4975 #ifdef HAVE_SCROLLBARS
4976 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4978 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4979 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4980 val = acons (Qother, make_int (stats.other), val);
4981 val = Fcons (Qnil, val);
4982 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4983 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4984 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4986 return Fnreverse (val);
4989 #endif /* MEMORY_USAGE_STATS */
4992 /************************************************************************/
4993 /* Window configurations */
4994 /************************************************************************/
4996 /* #### This window configuration stuff has had serious bugs lurking in it
4997 for years; it would be a -huge- win if this was reimplemented in lisp.
5000 /* If you add anything to this structure make sure saved_window_equal
5004 Lisp_Object window; /* window */
5005 Lisp_Object buffer; /* buffer */
5006 Lisp_Object start; /* copied marker */
5007 Lisp_Object pointm; /* copied marker */
5008 Lisp_Object sb_point; /* copied marker */
5009 Lisp_Object mark; /* copied marker */
5015 Charcount modeline_hscroll;
5016 int parent_index; /* index into saved_windows */
5017 int prev_index; /* index into saved_windows */
5018 char start_at_line_beg; /* boolean */
5020 #define WINDOW_SLOT_DECLARATION
5021 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5022 #include "winslots.h"
5025 /* If you add anything to this structure make sure window_config_equal
5027 struct window_config
5029 struct lcrecord_header header;
5030 /* int frame_width; No longer needed, JV
5031 int frame_height; */
5033 Lisp_Object selected_frame;
5035 Lisp_Object current_window;
5036 Lisp_Object current_buffer;
5037 Lisp_Object minibuffer_scroll_window;
5038 Lisp_Object root_window;
5039 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5040 /* Record the values of window-min-width and window-min-height
5041 so that window sizes remain consistent with them. */
5042 int min_width, min_height;
5043 unsigned int saved_windows_count;
5044 /* Zero-sized arrays aren't ANSI C */
5045 struct saved_window saved_windows[1];
5048 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5049 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5050 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5051 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5052 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5055 mark_window_config (Lisp_Object obj)
5057 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5059 mark_object (config->current_window);
5060 mark_object (config->current_buffer);
5061 mark_object (config->minibuffer_scroll_window);
5062 mark_object (config->root_window);
5064 for (i = 0; i < config->saved_windows_count; i++)
5066 struct saved_window *s = SAVED_WINDOW_N (config, i);
5067 mark_object (s->window);
5068 mark_object (s->buffer);
5069 mark_object (s->start);
5070 mark_object (s->pointm);
5071 mark_object (s->sb_point);
5072 mark_object (s->mark);
5074 /* #### This looked like this. I do not see why specifier cached
5075 values should not be marked, as such specifiers as toolbars
5076 might have GC-able instances. Freed configs are not marked,
5077 aren't they? -- kkm */
5078 mark_object (s->dedicated);
5080 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5081 #include "winslots.h"
5087 inline static size_t
5088 sizeof_window_config_for_n_windows (unsigned int n)
5090 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (struct window_config,
5091 struct saved_window, saved_windows, n);
5095 sizeof_window_config (const void *h)
5097 const struct window_config *c = (const struct window_config *) h;
5098 return sizeof_window_config_for_n_windows (c->saved_windows_count);
5102 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5104 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5107 error ("printing unreadable object #<window-configuration 0x%x>",
5108 config->header.uid);
5109 write_c_string ("#<window-configuration ", printcharfun);
5110 sprintf (buf, "0x%x>", config->header.uid);
5111 write_c_string (buf, printcharfun);
5114 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
5115 window_configuration,
5117 print_window_config,
5118 0, 0, 0, 0, sizeof_window_config,
5119 struct window_config);
5122 /* Returns a boolean indicating whether the two saved windows are
5125 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
5127 #define WINDOW_SLOT(slot, compare) \
5128 if (!compare (win1->slot, win2->slot)) \
5130 #include "winslots.h"
5133 EQ (win1->window, win2->window) &&
5134 EQ (win1->buffer, win2->buffer) &&
5135 internal_equal (win1->start, win2->start, 0) &&
5136 internal_equal (win1->pointm, win2->pointm, 0) &&
5137 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5138 internal_equal (win1->mark, win2->mark, 0) &&
5139 win1->pixel_left == win2->pixel_left &&
5140 win1->pixel_top == win2->pixel_top &&
5141 win1->pixel_width == win2->pixel_width &&
5142 win1->pixel_height == win2->pixel_height &&
5143 win1->hscroll == win2->hscroll &&
5144 win1->modeline_hscroll == win2->modeline_hscroll &&
5145 win1->parent_index == win2->parent_index &&
5146 win1->prev_index == win2->prev_index &&
5147 win1->start_at_line_beg == win2->start_at_line_beg;
5150 /* Returns a boolean indicating whether the two given configurations
5153 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5155 struct window_config *fig1, *fig2;
5158 /* First check if they are truly the same. */
5159 if (EQ (conf1, conf2))
5162 fig1 = XWINDOW_CONFIGURATION (conf1);
5163 fig2 = XWINDOW_CONFIGURATION (conf2);
5165 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5166 EQ (fig1->current_window, fig2->current_window) &&
5167 EQ (fig1->current_buffer, fig2->current_buffer) &&
5168 EQ (fig1->root_window, fig2->root_window) &&
5169 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5171 fig1->frame_width == fig2->frame_width &&
5172 fig1->frame_height == fig2->frame_height)) */
5175 for (i = 0; i < fig1->saved_windows_count; i++)
5177 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5178 SAVED_WINDOW_N (fig2, i)))
5185 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5186 Return t if OBJECT is a window-configuration object.
5190 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5194 mark_windows_in_use_closure (struct window *w, void *closure)
5196 int mark = *(int *)closure;
5197 w->config_mark = mark;
5202 mark_windows_in_use (struct frame *f, int mark)
5204 map_windows (f, mark_windows_in_use_closure, &mark);
5207 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5209 free_window_configuration (Lisp_Object window_config)
5212 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5214 /* Free all the markers. It's not completely necessary that
5215 we do this (window configs sitting in a free list aren't
5216 marked normally so the markers wouldn't be marked anyway)
5217 but it's more efficient. */
5218 for (i = 0; i < config->saved_windows_count; i++)
5220 struct saved_window *p = SAVED_WINDOW_N (config, i);
5222 if (!NILP (p->pointm))
5224 free_marker (XMARKER (p->pointm));
5227 if (!NILP (p->start))
5229 free_marker (XMARKER (p->start));
5232 if (!NILP (p->sb_point))
5234 free_marker (XMARKER (p->sb_point));
5237 if (!NILP (p->mark))
5239 free_marker (XMARKER (p->mark));
5244 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5245 free_managed_lcrecord (Vwindow_configuration_free_list
5246 [config->saved_windows_count - 1],
5252 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5253 Set the configuration of windows and buffers as specified by CONFIGURATION.
5254 CONFIGURATION must be a value previously returned
5255 by `current-window-configuration' (which see).
5260 struct window_config *config;
5261 struct saved_window *p;
5262 Lisp_Object new_current_buffer;
5266 struct gcpro gcpro1;
5267 Lisp_Object old_window_config;
5268 /* int previous_frame_height;
5269 int previous_frame_width;*/
5270 int previous_pixel_top;
5271 int previous_pixel_height;
5272 int previous_pixel_left;
5273 int previous_pixel_width;
5274 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5275 int real_font_height;
5276 int converted_minibuf_height,target_minibuf_height;
5277 int specpdl_count = specpdl_depth ();
5279 GCPRO1 (configuration);
5281 CHECK_WINDOW_CONFIGURATION (configuration);
5282 config = XWINDOW_CONFIGURATION (configuration);
5284 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5287 /* Do not signal an error here if the frame was deleted. There are
5288 reasonable cases where we could get here with a deleted frame and
5289 just want to do close to nothing instead. */
5291 if (FRAME_LIVE_P (f))
5293 /* restore the frame characteristics */
5295 new_current_buffer = config->current_buffer;
5296 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5297 new_current_buffer = Qnil;
5300 * Assumed precondition: w->config_mark = 0 for all w
5301 * This procedure should ensure this is true by the time it exits
5302 * to ensure the precondition for future calls.
5304 * We use w->config_mark to know whether we're modifying a
5305 * window that is currently visible on the frame (#### we
5306 * should just be able to check whether the window is dead
5307 * or not, but this way is safer?). As we process each
5308 * window, we set its config_mark to 0. At the end, we
5309 * go through all the windows that used to be on the frame,
5310 * set each one's config_mark to 0 (to maintain the
5311 * assumed precondition) and delete each one that's no
5314 * #### Using a window-configuration to keep track of
5315 * the current windows is wasteful. All we need is the
5316 * list of windows, so we could just use a dynarr.
5318 old_window_config = Fcurrent_window_configuration (frame);
5320 /* If the new configuration is already equal to the old, then stop
5321 right here. This saves the work below and it also saves
5322 triggering a full redisplay of this window. This is a huge win
5323 when using the mouse since the mode motion code uses
5324 save-window-excursion extensively but will rarely cause the
5325 configuration to actually change. */
5326 if (window_config_equal (configuration, old_window_config))
5328 free_window_configuration (old_window_config);
5333 /* We can't quit or even check for quit because that may cause
5334 investigation of the frame state, which may crash if the frame is
5335 in an inconsistent state. */
5336 begin_dont_check_for_quit ();
5337 record_unwind_protect (free_window_configuration, old_window_config);
5339 mark_windows_in_use (f, 1);
5340 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5341 /* Force subwindows to be remapped. This is overkill but saves
5342 us having to rely on the redisplay code to unmap any extant
5345 #### It does cause some extra flashing though which we could
5346 possibly avoid. So consider trying to get redisplay to work
5349 Removing the instances from the frame cache is wrong because
5350 an instance is only put in the frame cache when it is
5351 instantiated. So if we do this there is a chance that stuff
5352 will never get put back in the frame cache. */
5353 reset_frame_subwindow_instance_cache (f);
5356 /* JV: This is bogus,
5357 First of all, the units are inconsistent. The frame sizes are measured
5358 in characters but the window sizes are stored in pixels. So if a
5359 font size change happened between saving and restoring, the
5360 frame "sizes" maybe equal but the windows still should be
5361 resized. This is tickled a lot by the new "character size
5362 stays constant" policy in 21.0. It leads to very weird
5363 glitches (and possibly crashes when asserts are tickled).
5365 Just changing the units doesn't help because changing the
5366 toolbar configuration can also change the pixel positions.
5367 Luckily there is a much simpler way of doing this, see below.
5369 previous_frame_width = FRAME_WIDTH (f);
5370 previous_frame_height = FRAME_HEIGHT (f);
5371 /* If the frame has been resized since this window configuration was
5372 made, we change the frame to the size specified in the
5373 configuration, restore the configuration, and then resize it
5374 back. We keep track of the prevailing height in these variables. */
5375 if (config->frame_height != FRAME_HEIGHT (f)
5376 || config->frame_width != FRAME_WIDTH (f))
5377 change_frame_size (f, config->frame_height, config->frame_width, 0);
5380 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5381 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5382 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5383 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5385 /* remember some properties of the minibuffer */
5387 default_face_height_and_width (frame, &real_font_height, 0);
5388 assert(real_font_height > 0);
5390 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5392 previous_minibuf_height
5393 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5394 previous_minibuf_top
5395 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5396 previous_minibuf_width
5397 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5401 previous_minibuf_height = 0;
5402 previous_minibuf_top = 0;
5403 previous_minibuf_width = 0;
5405 converted_minibuf_height =
5406 (previous_minibuf_height % real_font_height) == 0 ?
5407 - (previous_minibuf_height / real_font_height ) : /* lines */
5408 previous_minibuf_height; /* pixels */
5410 /* Temporarily avoid any problems with windows that are smaller
5411 than they are supposed to be. */
5412 window_min_height = 1;
5413 window_min_width = 1;
5415 /* OK, now restore all the windows in the window config.
5416 This may involve "undeleting" windows, since the
5417 windows in the window config may be deleted.
5419 for (k = 0; k < config->saved_windows_count; k++)
5421 p = SAVED_WINDOW_N (config, k);
5422 w = XWINDOW (p->window);
5425 /* The window might be dead. In this case, its redisplay
5426 structures were freed, so we need to reallocate them. */
5427 if (!w->face_cachels)
5429 w->face_cachels = Dynarr_new (face_cachel);
5430 reset_face_cachels (w);
5432 if (!w->glyph_cachels)
5433 w->glyph_cachels = Dynarr_new (glyph_cachel);
5434 if (!w->line_start_cache)
5435 w->line_start_cache = Dynarr_new (line_start_cache);
5436 w->gutter_extent_modiff[0] = 0;
5437 w->gutter_extent_modiff[1] = 0;
5438 w->gutter_extent_modiff[2] = 0;
5439 w->gutter_extent_modiff[3] = 0;
5442 if (p->parent_index >= 0)
5443 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5447 if (p->prev_index >= 0)
5449 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5451 /* This is true for a minibuffer-only frame. */
5452 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5455 XWINDOW (w->prev)->next = p->window;
5460 if (!NILP (w->parent))
5462 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5464 XWINDOW (w->parent)->vchild = p->window;
5465 XWINDOW (w->parent)->hchild = Qnil;
5469 XWINDOW (w->parent)->hchild = p->window;
5470 XWINDOW (w->parent)->vchild = Qnil;
5474 if (!w->config_mark)
5476 /* #### This should be equivalent to the window previously
5477 having been dead. If we're brave, we'll put in an
5478 assertion to this effect. */
5479 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5481 else /* if (!EQ (w->buffer, p->buffer)) */
5483 /* With the new redisplay we let it know that a change has
5484 been made and it will take care of the rest. If we don't
5485 tell it something has possibly changed it could lead to
5486 incorrect display. */
5487 MARK_WINDOWS_CHANGED (w);
5490 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5491 WINDOW_TOP (w) = WINDOW_TOP (p);
5492 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5493 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5494 w->hscroll = p->hscroll;
5495 w->modeline_hscroll = p->modeline_hscroll;
5496 w->line_cache_last_updated = Qzero;
5497 /* When we restore a window's configuration, the identity of
5498 the window hasn't actually changed - so there is no
5499 reason why we shouldn't preserve the instance cache for
5500 it - unless it was originally deleted. This will often
5501 buy us something as we will not have to re-instantiate
5502 all the instances. This is because this is an instance
5503 cache - not a display cache. Preserving the display cache
5504 would definitely be wrong.
5506 We specifically want to do this for tabs, since for some
5507 reason finding a file will cause the configuration to be
5509 if (NILP (w->subwindow_instance_cache))
5510 w->subwindow_instance_cache =
5511 make_image_instance_cache_hash_table ();
5513 SET_LAST_MODIFIED (w, 1);
5514 SET_LAST_FACECHANGE (w);
5517 /* #### Consider making the instance cache a winslot. */
5518 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5519 #include "winslots.h"
5521 /* Reinstall the saved buffer and pointers into it. */
5522 if (NILP (p->buffer))
5523 w->buffer = p->buffer;
5526 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5527 /* If saved buffer is alive, install it. */
5529 w->buffer = p->buffer;
5530 w->start_at_line_beg = p->start_at_line_beg;
5531 set_marker_restricted (w->start[CURRENT_DISP],
5532 Fmarker_position (p->start),
5534 set_marker_restricted (w->pointm[CURRENT_DISP],
5535 Fmarker_position (p->pointm),
5537 set_marker_restricted (w->sb_point,
5538 Fmarker_position (p->sb_point),
5540 Fset_marker (XBUFFER (w->buffer)->mark,
5541 Fmarker_position (p->mark), w->buffer);
5543 /* As documented in Fcurrent_window_configuration, don't
5544 save the location of point in the buffer which was current
5545 when the window configuration was recorded. */
5546 if (!EQ (p->buffer, new_current_buffer) &&
5547 XBUFFER (p->buffer) == current_buffer)
5548 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5550 else if (NILP (w->buffer) ||
5551 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5552 /* Else if window's old buffer is dead too, get a live one. */
5554 /* #### The following line makes me nervous... */
5555 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5556 w->buffer = Fget_buffer_create (QSscratch);
5557 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5558 /* This will set the markers to beginning of visible
5560 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5561 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5563 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5564 w->start_at_line_beg = 1;
5567 /* Keeping window's old buffer; make sure the markers
5570 /* Set window markers at start of visible range. */
5571 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5572 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5574 if (XMARKER (w->sb_point)->buffer == 0)
5575 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5576 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5577 set_marker_restricted (w->pointm[CURRENT_DISP],
5579 (BUF_PT (XBUFFER (w->buffer))),
5581 w->start_at_line_beg = 1;
5586 FRAME_ROOT_WINDOW (f) = config->root_window;
5587 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5588 then calls do_switch_frame() below to select the frame that was
5589 recorded in the window config as being selected.
5591 Instead, we don't ever change the selected frame, and either
5592 call Fselect_window() below if the window config's frame is
5593 currently selected, or just set the selected window of the
5594 window config's frame. */
5597 /* Set the frame height to the value it had before this function. */
5598 if (previous_frame_height != FRAME_HEIGHT (f)
5599 || previous_frame_width != FRAME_WIDTH (f))
5600 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5602 /* We just reset the size and position of the minibuffer, to its old
5603 value, which needn't be valid. So we do some magic to see which value
5604 to actually take. Then we set it.
5607 We take the old value if is in the same units but differs from the
5610 #### Now we get more cases correct then ever before, but
5611 are we treating all? For instance what if the frames minibuf window
5612 is no longer the same one?
5614 target_minibuf_height = previous_minibuf_height;
5615 if (converted_minibuf_height &&
5616 (converted_minibuf_height * config->minibuf_height) > 0 &&
5617 (converted_minibuf_height != config->minibuf_height))
5619 target_minibuf_height = config->minibuf_height < 0 ?
5620 - (config->minibuf_height * real_font_height) :
5621 config->minibuf_height;
5622 target_minibuf_height =
5623 max(target_minibuf_height,real_font_height);
5625 if (previous_minibuf_height)
5627 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5628 = previous_minibuf_top -
5629 (target_minibuf_height - previous_minibuf_height);
5630 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5631 target_minibuf_height, 0);
5632 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5633 previous_minibuf_width, 0);
5636 /* This is a better way to deal with frame resizing, etc.
5637 What we _actually_ want is for the old (just restored)
5639 into the place of the new one. So we just do that. Simple! */
5640 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5641 /* Note that this function also updates the subwindow
5643 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5644 previous_pixel_height -
5645 (target_minibuf_height - previous_minibuf_height), 0);
5646 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5647 /* Note that this function also updates the subwindow
5649 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5651 /* If restoring in the current frame make the window current,
5652 otherwise just update the frame selected_window slot to be
5653 the restored current_window. */
5654 if (f == selected_frame ())
5657 /* When using `pop-window-configuration', often the minibuffer
5658 ends up as the selected window even though it's not active ...
5659 I really don't know the cause of this, but it should never
5660 happen. This kludge should fix it.
5662 #### Find out why this is really going wrong. */
5663 if (!minibuf_level &&
5664 MINI_WINDOW_P (XWINDOW (config->current_window)))
5665 window_to_select = Fnext_window (config->current_window,
5668 window_to_select = config->current_window;
5670 /* Do this last so that buffer stacking is calculated
5672 Fselect_window (config->current_window, Qnil);
5674 if (!NILP (new_current_buffer))
5676 Fset_buffer (new_current_buffer);
5677 Frecord_buffer (new_current_buffer);
5681 Fset_buffer (XWINDOW (config->current_window)->buffer);
5682 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5686 set_frame_selected_window (f, config->current_window);
5689 old_window_config = Qnil; /* Warning suppression */
5691 /* Restore the minimum heights recorded in the configuration. */
5692 window_min_height = config->min_height;
5693 window_min_width = config->min_width;
5696 /* see above comment */
5697 /* Fselect_window will have made f the selected frame, so we
5698 reselect the proper frame here. Fhandle_switch_frame will change the
5699 selected window too, but that doesn't make the call to
5700 Fselect_window above totally superfluous; it still sets f's
5702 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5703 do_switch_frame (config->selected_frame, Qnil, 0);
5706 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5708 if (FRAME_LIVE_P (f))
5710 /* Do this before calling recompute_all_cached_specifiers_in_window()
5711 so that things like redisplay_redraw_cursor() won't abort due
5712 to no window mirror present. */
5713 f->mirror_dirty = 1;
5715 config = XWINDOW_CONFIGURATION (old_window_config);
5716 for (k = 0; k < config->saved_windows_count; k++)
5718 p = SAVED_WINDOW_N (config, k);
5719 w = XWINDOW (p->window);
5720 /* Remember, we set w->config_mark on all currently visible
5721 windows, and reset it on all newly visible windows.
5722 Any windows still marked need to be deleted. */
5725 mark_window_as_deleted (w);
5730 /* We just potentially changed the window's buffer and
5731 potentially turned a dead window into a live one,
5732 so we need to recompute the cached specifier values. */
5733 recompute_all_cached_specifiers_in_window (w);
5738 /* Now restore things, when everything else if OK. */
5740 unbind_to (specpdl_count, Qnil);
5747 /* Mark all subwindows of a window as deleted. The argument
5748 W is actually the subwindow tree of the window in question. */
5751 delete_all_subwindows (struct window *w)
5753 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5754 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5755 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5757 mark_window_as_deleted (w);
5762 count_windows (struct window *window)
5765 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5766 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5767 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5771 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5774 for (j = 0; j < lim; j++)
5776 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5780 return 0; /* suppress compiler warning */
5784 save_window_save (Lisp_Object window, struct window_config *config, int i)
5788 for (; !NILP (window); window = w->next)
5790 struct saved_window *p = SAVED_WINDOW_N (config, i);
5792 w = XWINDOW (window);
5795 p->buffer = w->buffer;
5796 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5797 WINDOW_TOP (p) = WINDOW_TOP (w);
5798 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5799 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5800 p->hscroll = w->hscroll;
5801 p->modeline_hscroll = w->modeline_hscroll;
5803 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5804 #include "winslots.h"
5806 if (!NILP (w->buffer))
5808 /* Save w's value of point in the window configuration.
5809 If w is the selected window, then get the value of point
5810 from the buffer; pointm is garbage in the selected window. */
5811 if (EQ (window, Fselected_window (Qnil)))
5813 p->pointm = noseeum_make_marker ();
5814 Fset_marker (p->pointm,
5815 make_int (BUF_PT (XBUFFER (w->buffer))),
5819 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5821 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5822 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5823 p->start_at_line_beg = w->start_at_line_beg;
5825 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5833 p->start_at_line_beg = 0;
5836 if (NILP (w->parent))
5837 p->parent_index = -1;
5839 p->parent_index = saved_window_index (w->parent, config, i);
5843 p->prev_index = saved_window_index (w->prev, config, i);
5844 if (!NILP (w->vchild))
5845 i = save_window_save (w->vchild, config, i);
5846 if (!NILP (w->hchild))
5847 i = save_window_save (w->hchild, config, i);
5854 /* Added to doc string:
5856 This also records the currently selected frame, and FRAME's focus
5857 redirection (see `redirect-frame-focus').
5862 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5863 Return an object representing the current window configuration of FRAME.
5864 If FRAME is nil or omitted, use the selected frame.
5865 This describes the number of windows, their sizes and current buffers,
5866 and for each window on FRAME the displayed buffer, where display
5867 starts, and the positions of point and mark.
5868 An exception is made for point in the current buffer:
5869 its value is -not- saved.
5874 struct frame *f = decode_frame (frame);
5875 struct window_config *config;
5876 unsigned int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5878 int real_font_height;
5880 if (n_windows <= countof (Vwindow_configuration_free_list))
5881 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5882 (Vwindow_configuration_free_list
5885 /* More than ten windows; just allocate directly */
5886 config = (struct window_config *)
5887 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5888 &lrecord_window_configuration);
5889 XSETWINDOW_CONFIGURATION (result, config);
5891 config->frame_width = FRAME_WIDTH (f);
5892 config->frame_height = FRAME_HEIGHT (f); */
5893 /* #### When using `push-window-configuration', often the minibuffer ends
5894 up as the selected window because functions run as the result of
5895 user interaction e.g. hyper-apropos. It seems to me the sensible
5896 thing to do is not record the minibuffer here.
5898 #### Unfortunately this is a change to previous behaviour, however logical
5899 it may be, so revert for the moment. */
5901 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5902 config->current_window = FRAME_SELECTED_WINDOW (f);
5904 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5906 config->current_window = FRAME_SELECTED_WINDOW (f);
5907 XSETBUFFER (config->current_buffer, current_buffer);
5908 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5909 config->root_window = FRAME_ROOT_WINDOW (f);
5910 config->min_height = window_min_height;
5911 config->min_width = window_min_width;
5912 config->saved_windows_count = n_windows;
5913 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5915 /* save the minibuffer height using the heuristics from
5916 change_frame_size_1 */
5918 XSETFRAME (frame, f); /* frame could have been nil ! */
5919 default_face_height_and_width (frame, &real_font_height, 0);
5920 assert(real_font_height > 0);
5922 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5923 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5926 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5927 - (minibuf_height / real_font_height ) : /* lines */
5928 minibuf_height; /* pixels */
5934 save_window_excursion_unwind (Lisp_Object window_config)
5936 Lisp_Object val = Fset_window_configuration (window_config);
5937 free_window_configuration (window_config);
5941 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5942 Execute body, preserving window sizes and contents.
5943 Restores which buffer appears in which window, where display starts,
5944 as well as the current buffer.
5945 Does not restore the value of point in current buffer.
5949 /* This function can GC */
5951 int speccount = specpdl_depth ();
5953 record_unwind_protect (save_window_excursion_unwind,
5954 Fcurrent_window_configuration (Qnil));
5955 val = Fprogn (args);
5956 return unbind_to (speccount, val);
5959 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5960 Return the horizontal pixel position of POS in window.
5961 Beginning of line is column 0. This is calculated using the redisplay
5962 display tables. If WINDOW is nil, the current window is assumed.
5963 If POS is nil, point is assumed. Note that POS must be visible for
5964 a non-nil result to be returned.
5968 struct window* w = decode_window (window);
5969 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5971 struct display_line *dl = 0;
5972 struct display_block *db = 0;
5973 struct rune* rb = 0;
5974 int y = w->last_point_y[CURRENT_DISP];
5975 int x = w->last_point_x[CURRENT_DISP];
5977 if (MINI_WINDOW_P (w))
5980 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5986 pos = Fwindow_point (window);
5991 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5996 for (i = first_line; i < Dynarr_length (dla); i++)
5998 dl = Dynarr_atp (dla, i);
5999 /* find the vertical location first */
6000 if (point >= dl->bufpos && point <= dl->end_bufpos)
6002 db = get_display_block_from_line (dl, TEXT);
6003 for (i = 0; i < Dynarr_length (db->runes); i++)
6005 rb = Dynarr_atp (db->runes, i);
6006 if (point <= rb->bufpos)
6018 /* optimized case */
6019 dl = Dynarr_atp (dla, y);
6020 db = get_display_block_from_line (dl, TEXT);
6022 if (x >= Dynarr_length (db->runes))
6025 rb = Dynarr_atp (db->runes, x);
6028 return make_int (rb->xpos - WINDOW_LEFT (w));
6033 /* This is short and simple in elisp, but... it was written to debug
6034 problems purely on the C side. That is where we need to call it so
6037 debug_print_window (Lisp_Object window, int level)
6040 Lisp_Object child = Fwindow_first_vchild (window);
6043 child = Fwindow_first_hchild (window);
6045 for (i = level; i > 0; i--)
6048 stderr_out ("#<window");
6050 Lisp_Object buffer = XWINDOW (window)->buffer;
6051 if (!NILP (buffer) && BUFFERP (buffer))
6052 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
6054 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
6056 while (!NILP (child))
6058 debug_print_window (child, level + 1);
6059 child = Fwindow_next_child (child);
6063 void debug_print_windows (struct frame *f);
6065 debug_print_windows (struct frame *f)
6067 debug_print_window (f->root_window, 0);
6068 putc ('\n', stderr);
6070 #endif /* DEBUG_XEMACS */
6073 /************************************************************************/
6074 /* initialization */
6075 /************************************************************************/
6078 syms_of_window (void)
6080 INIT_LRECORD_IMPLEMENTATION (window);
6081 INIT_LRECORD_IMPLEMENTATION (window_configuration);
6083 defsymbol (&Qwindowp, "windowp");
6084 defsymbol (&Qwindow_live_p, "window-live-p");
6085 defsymbol (&Qwindow_configurationp, "window-configuration-p");
6086 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6087 defsymbol (&Qdisplay_buffer, "display-buffer");
6089 #ifdef MEMORY_USAGE_STATS
6090 defsymbol (&Qface_cache, "face-cache");
6091 defsymbol (&Qglyph_cache, "glyph-cache");
6092 defsymbol (&Qline_start_cache, "line-start-cache");
6093 #ifdef HAVE_SCROLLBARS
6094 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
6096 defsymbol (&Qother_redisplay, "other-redisplay");
6097 /* Qother in general.c */
6100 DEFSUBR (Fselected_window);
6101 DEFSUBR (Flast_nonminibuf_window);
6102 DEFSUBR (Fminibuffer_window);
6103 DEFSUBR (Fwindow_minibuffer_p);
6105 DEFSUBR (Fwindow_live_p);
6106 DEFSUBR (Fwindow_first_hchild);
6107 DEFSUBR (Fwindow_first_vchild);
6108 DEFSUBR (Fwindow_next_child);
6109 DEFSUBR (Fwindow_previous_child);
6110 DEFSUBR (Fwindow_parent);
6111 DEFSUBR (Fwindow_lowest_p);
6112 DEFSUBR (Fwindow_truncated_p);
6113 DEFSUBR (Fwindow_highest_p);
6114 DEFSUBR (Fwindow_leftmost_p);
6115 DEFSUBR (Fwindow_rightmost_p);
6116 DEFSUBR (Fpos_visible_in_window_p);
6117 DEFSUBR (Fwindow_buffer);
6118 DEFSUBR (Fwindow_frame);
6119 DEFSUBR (Fwindow_height);
6120 DEFSUBR (Fwindow_displayed_height);
6121 DEFSUBR (Fwindow_width);
6122 DEFSUBR (Fwindow_full_width);
6123 DEFSUBR (Fwindow_pixel_height);
6124 DEFSUBR (Fwindow_pixel_width);
6125 DEFSUBR (Fwindow_text_area_height);
6126 DEFSUBR (Fwindow_text_area_pixel_height);
6127 DEFSUBR (Fwindow_displayed_text_pixel_height);
6128 DEFSUBR (Fwindow_text_area_pixel_width);
6129 DEFSUBR (Fwindow_hscroll);
6130 DEFSUBR (Fset_window_hscroll);
6131 DEFSUBR (Fmodeline_hscroll);
6132 DEFSUBR (Fset_modeline_hscroll);
6133 #if 0 /* bogus FSF crock */
6134 DEFSUBR (Fwindow_redisplay_end_trigger);
6135 DEFSUBR (Fset_window_redisplay_end_trigger);
6137 DEFSUBR (Fwindow_pixel_edges);
6138 DEFSUBR (Fwindow_text_area_pixel_edges);
6139 DEFSUBR (Fwindow_point);
6140 DEFSUBR (Fwindow_start);
6141 DEFSUBR (Fwindow_end);
6142 DEFSUBR (Fwindow_last_line_visible_height);
6143 DEFSUBR (Fset_window_point);
6144 DEFSUBR (Fset_window_start);
6145 DEFSUBR (Fwindow_dedicated_p);
6146 DEFSUBR (Fset_window_dedicated_p);
6147 DEFSUBR (Fnext_window);
6148 DEFSUBR (Fprevious_window);
6149 DEFSUBR (Fnext_vertical_window);
6150 DEFSUBR (Fother_window);
6151 DEFSUBR (Fget_lru_window);
6152 DEFSUBR (Fget_largest_window);
6153 DEFSUBR (Fget_buffer_window);
6154 DEFSUBR (Fwindow_left_margin_pixel_width);
6155 DEFSUBR (Fwindow_right_margin_pixel_width);
6156 DEFSUBR (Fdelete_other_windows);
6157 DEFSUBR (Fdelete_windows_on);
6158 DEFSUBR (Freplace_buffer_in_windows);
6159 DEFSUBR (Fdelete_window);
6160 DEFSUBR (Fset_window_buffer);
6161 DEFSUBR (Fselect_window);
6162 DEFSUBR (Fsplit_window);
6163 DEFSUBR (Fenlarge_window);
6164 DEFSUBR (Fenlarge_window_pixels);
6165 DEFSUBR (Fshrink_window);
6166 DEFSUBR (Fshrink_window_pixels);
6167 DEFSUBR (Fscroll_up);
6168 DEFSUBR (Fscroll_down);
6169 DEFSUBR (Fscroll_left);
6170 DEFSUBR (Fscroll_right);
6171 DEFSUBR (Fother_window_for_scrolling);
6172 DEFSUBR (Fscroll_other_window);
6173 DEFSUBR (Fcenter_to_window_line);
6174 DEFSUBR (Fmove_to_window_line);
6175 #ifdef MEMORY_USAGE_STATS
6176 DEFSUBR (Fwindow_memory_usage);
6178 DEFSUBR (Fwindow_configuration_p);
6179 DEFSUBR (Fset_window_configuration);
6180 DEFSUBR (Fcurrent_window_configuration);
6181 DEFSUBR (Fsave_window_excursion);
6182 DEFSUBR (Fcurrent_pixel_column);
6186 reinit_vars_of_window (void)
6189 /* Make sure all windows get marked */
6190 minibuf_window = Qnil;
6191 staticpro_nodump (&minibuf_window);
6193 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6195 Vwindow_configuration_free_list[i] =
6196 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6197 &lrecord_window_configuration);
6198 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6203 vars_of_window (void)
6205 reinit_vars_of_window ();
6207 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6208 *Non-nil means to scroll if point lands on a line which is clipped.
6210 scroll_on_clipped_lines = 1;
6212 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6213 See `temp-buffer-show-function'.
6215 Vtemp_buffer_show_hook = Qnil;
6217 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6218 Non-nil means call as function to display a help buffer.
6219 The function is called with one argument, the buffer to be displayed.
6220 Used by `with-output-to-temp-buffer'.
6221 If this function is used, then it must do the entire job of showing
6222 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6223 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6225 Vtemp_buffer_show_function = Qnil;
6227 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6228 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6230 Vminibuffer_scroll_window = Qnil;
6232 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6233 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6235 Vother_window_scroll_buffer = Qnil;
6237 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6238 *Number of pixels to scroll by per requested line.
6239 If nil then normal line scrolling occurs regardless of line height.
6240 If t then scrolling is done in increments equal to the height of the default face.
6242 Vwindow_pixel_scroll_increment = Qt;
6244 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6245 *Number of lines of continuity when scrolling by screenfuls.
6247 next_screen_context_lines = 2;
6249 DEFVAR_INT ("window-min-height", &window_min_height /*
6250 *Delete any window less than this tall (including its modeline).
6252 window_min_height = 4;
6254 DEFVAR_INT ("window-min-width", &window_min_width /*
6255 *Delete any window less than this wide.
6257 window_min_width = 10;
6261 specifier_vars_of_window (void)
6263 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6264 *How thick to draw 3D shadows around modelines.
6265 If this is set to 0, modelines will be the traditional 2D. Sizes above
6266 10 will be accepted but the maximum thickness that will be drawn is 10.
6267 This is a specifier; use `set-specifier' to change it.
6269 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6270 /* The initial value for modeline-shadow-thickness is 2, but if the
6271 user removes all specifications we provide a fallback value of 0,
6272 which is probably what was expected. */
6273 set_specifier_fallback (Vmodeline_shadow_thickness,
6274 list1 (Fcons (Qnil, Qzero)));
6275 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6277 set_specifier_caching (Vmodeline_shadow_thickness,
6278 offsetof (struct window, modeline_shadow_thickness),
6279 modeline_shadow_thickness_changed,
6282 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6283 *Whether the modeline should be displayed.
6284 This is a specifier; use `set-specifier' to change it.
6286 Vhas_modeline_p = Fmake_specifier (Qboolean);
6287 set_specifier_fallback (Vhas_modeline_p,
6288 list1 (Fcons (Qnil, Qt)));
6289 set_specifier_caching (Vhas_modeline_p,
6290 offsetof (struct window, has_modeline_p),
6291 /* #### It's strange that we need a special
6292 flag to indicate that the shadow-thickness
6293 has changed, but not one to indicate that
6294 the modeline has been turned off or on. */
6295 some_window_value_changed,
6298 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6299 &Vvertical_divider_always_visible_p /*
6300 *Should XEmacs always display vertical dividers between windows.
6302 When this is non-nil, vertical dividers are always shown, and are
6303 draggable. When it is nil, vertical dividers are shown only when
6304 there are no scrollbars in between windows, and are not draggable.
6306 This is a specifier; use `set-specifier' to change it.
6308 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6309 set_specifier_fallback (Vvertical_divider_always_visible_p,
6310 list1 (Fcons (Qnil, Qt)));
6311 set_specifier_caching (Vvertical_divider_always_visible_p,
6312 offsetof (struct window,
6313 vertical_divider_always_visible_p),
6314 vertical_divider_changed_in_window,
6317 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6318 *How thick to draw 3D shadows around vertical dividers.
6319 This is a specifier; use `set-specifier' to change it.
6321 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6322 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6323 list1 (Fcons (Qnil, Qzero)));
6324 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6326 set_specifier_caching (Vvertical_divider_shadow_thickness,
6327 offsetof (struct window,
6328 vertical_divider_shadow_thickness),
6329 vertical_divider_changed_in_window,
6331 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6332 *The width of the vertical dividers, not including shadows.
6334 For TTY windows, divider line is always one character wide. When
6335 instance of this specifier is zero in a TTY window, no divider is
6336 drawn at all between windows. When non-zero, a one character wide
6337 divider is displayed.
6339 This is a specifier; use `set-specifier' to change it.
6342 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6344 Lisp_Object fb = Qnil;
6346 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6349 fb = Fcons (Fcons (list1 (Qgtk), make_int (3)), fb);
6351 #ifdef HAVE_X_WINDOWS
6352 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6354 #ifdef HAVE_MS_WINDOWS
6355 /* #### This should be made magic and made to obey system settings */
6356 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6358 set_specifier_fallback (Vvertical_divider_line_width, fb);
6360 set_specifier_caching (Vvertical_divider_line_width,
6361 offsetof (struct window,
6362 vertical_divider_line_width),
6363 vertical_divider_changed_in_window,
6366 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6367 *How much space to leave around the vertical dividers.
6369 In TTY windows, spacing is always zero, and the value of this
6370 specifier is ignored.
6372 This is a specifier; use `set-specifier' to change it.
6374 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6376 Lisp_Object fb = Qnil;
6378 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6380 #ifdef HAVE_X_WINDOWS
6381 /* #### 3D dividers look great on MS Windows with spacing = 0.
6382 Should not the same value be the fallback under X? - kkm */
6383 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6386 fb = Fcons (Fcons (list1 (Qgtk), Qzero), fb);
6388 #ifdef HAVE_MS_WINDOWS
6389 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6391 set_specifier_fallback (Vvertical_divider_spacing, fb);
6393 set_specifier_caching (Vvertical_divider_spacing,
6394 offsetof (struct window, vertical_divider_spacing),
6395 vertical_divider_changed_in_window,