1 /* Window creation, deletion and examination for SXEmacs.
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.
6 Copyright (C) 2004 Johann "Myrkraverk" Oskarsson.
8 This file is part of SXEmacs
10 SXEmacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 SXEmacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 /* Synched up with: FSF 19.30. */
25 /* Beginning to diverge significantly. */
27 /* window-configuraion-hook, by Johann "Myrkraverk" Oskarsson, Jun 2004. */
29 /* This file has been Mule-ized. */
39 #include "redisplay.h"
45 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
46 Lisp_Object Qdisplay_buffer;
48 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
49 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
50 #ifdef HAVE_SCROLLBARS
51 Lisp_Object Qscrollbar_instances;
55 extern int allow_deletion_of_last_visible_frame;
57 EXFUN(Fnext_window, 4);
59 static int window_pixel_width_to_char_width(struct window *w,
61 int include_margins_p);
62 static int window_char_width_to_pixel_width(struct window *w,
64 int include_margins_p);
65 static int window_pixel_height_to_char_height(struct window *w,
67 int include_gutters_p);
68 static int window_char_height_to_pixel_height(struct window *w,
70 int include_gutters_p);
71 static void change_window_height(Lisp_Object window, int delta,
72 Lisp_Object horizontalp, int inpixels);
74 /* Thickness of shadow border around 3d modelines. */
75 Lisp_Object Vmodeline_shadow_thickness;
77 /* Whether vertical dividers are draggable and displayed */
78 Lisp_Object Vvertical_divider_always_visible_p;
80 /* Whether a modeline should be displayed. */
81 Lisp_Object Vhas_modeline_p;
83 /* Thickness of shadow border around vertical dividers. */
84 Lisp_Object Vvertical_divider_shadow_thickness;
86 /* Divider surface width (not counting 3-d borders) */
87 Lisp_Object Vvertical_divider_line_width;
89 /* Spacing between outer edge of divider border and window edge */
90 Lisp_Object Vvertical_divider_spacing;
92 /* How much to scroll by per-line. */
93 Lisp_Object Vwindow_pixel_scroll_increment;
95 /* Scroll if point lands on the bottom line and that line is partially
97 int scroll_on_clipped_lines;
99 /* The minibuffer window of the selected frame.
100 Note that you cannot test for minibufferness of an arbitrary window
101 by comparing against this; but you can test for minibufferness of
102 the selected window. */
103 Lisp_Object minibuf_window;
105 /* Non-nil means it is the window for C-M-v to scroll
106 when the minibuffer is selected. */
107 Lisp_Object Vminibuffer_scroll_window;
109 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
110 Lisp_Object Vother_window_scroll_buffer;
112 /* Non-nil means it's the function to call to display temp buffers. */
113 Lisp_Object Vtemp_buffer_show_function;
115 Lisp_Object Vtemp_buffer_show_hook;
117 /* If a window gets smaller than either of these, it is removed. */
118 Fixnum window_min_height;
119 Fixnum window_min_width;
121 /* Hook run at end of temp_output_buffer_show. */
122 Lisp_Object Qtemp_buffer_show_hook;
124 /* Number of lines of continuity in scrolling by screenfuls. */
125 Fixnum next_screen_context_lines;
127 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
128 /* List of freed window configurations with 1 - 10 windows. */
129 static Lisp_Object Vwindow_configuration_free_list[10];
132 Lisp_Object Qtruncate_partial_width_windows;
134 Lisp_Object Qwindow_configuration_hook, Vwindow_configuration_hook;
136 #define SET_LAST_MODIFIED(w, cache_too) \
138 (w)->last_modified[CURRENT_DISP] = Qzero; \
139 (w)->last_modified[DESIRED_DISP] = Qzero; \
140 (w)->last_modified[CMOTION_DISP] = Qzero; \
142 (w)->line_cache_last_updated = Qzero; \
145 #define SET_LAST_FACECHANGE(w) \
147 (w)->last_facechange[CURRENT_DISP] = Qzero; \
148 (w)->last_facechange[DESIRED_DISP] = Qzero; \
149 (w)->last_facechange[CMOTION_DISP] = Qzero; \
152 #define MARK_DISP_VARIABLE(field) \
153 mark_object (window->field[CURRENT_DISP]); \
154 mark_object (window->field[DESIRED_DISP]); \
155 mark_object (window->field[CMOTION_DISP]);
157 static Lisp_Object mark_window(Lisp_Object obj)
159 struct window *window = XWINDOW(obj);
160 mark_object(window->frame);
161 mark_object(window->mini_p);
162 mark_object(window->next);
163 mark_object(window->prev);
164 mark_object(window->hchild);
165 mark_object(window->vchild);
166 mark_object(window->parent);
167 mark_object(window->buffer);
168 MARK_DISP_VARIABLE(start);
169 MARK_DISP_VARIABLE(pointm);
170 mark_object(window->sb_point); /* #### move to scrollbar.c? */
171 mark_object(window->use_time);
172 MARK_DISP_VARIABLE(last_modified);
173 MARK_DISP_VARIABLE(last_point);
174 MARK_DISP_VARIABLE(last_start);
175 MARK_DISP_VARIABLE(last_facechange);
176 mark_object(window->line_cache_last_updated);
177 mark_object(window->redisplay_end_trigger);
178 mark_object(window->subwindow_instance_cache);
180 mark_face_cachels(window->face_cachels);
181 mark_glyph_cachels(window->glyph_cachels);
183 #define WINDOW_SLOT(slot, compare) mark_object (window->slot)
184 #include "winslots.h"
190 run_window_configuration_hook ( Lisp_Object win )
197 win = Fselected_window(Qnil);
202 frame = WINDOW_FRAME (w);
205 if ( ! f->window_configuration_hook ) {
206 f->window_configuration_hook = 1;
207 va_run_hook_with_args(Qwindow_configuration_hook, 1, win);
208 f->window_configuration_hook = 0;
213 print_window(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
218 error("printing unreadable object #<window 0x%x>",
219 XWINDOW(obj)->header.uid);
221 write_c_string("#<window", printcharfun);
222 if (!NILP(XWINDOW(obj)->buffer)) {
223 Lisp_Object name = XBUFFER(XWINDOW(obj)->buffer)->name;
224 write_c_string(" on ", printcharfun);
225 print_internal(name, printcharfun, 1);
227 sprintf(buf, " 0x%x>", XWINDOW(obj)->header.uid);
228 write_c_string(buf, printcharfun);
231 static void finalize_window(void *header, int for_disksave)
233 struct window *w = (struct window *)header;
235 if (w->line_start_cache) {
236 Dynarr_free(w->line_start_cache);
237 w->line_start_cache = 0;
240 if (w->face_cachels) {
243 for (i = 0; i < Dynarr_length(w->face_cachels); i++) {
244 struct face_cachel *cachel =
245 Dynarr_atp(w->face_cachels, i);
246 if (cachel->merged_faces) {
247 Dynarr_free(cachel->merged_faces);
248 cachel->merged_faces = 0;
251 Dynarr_free(w->face_cachels);
255 if (w->glyph_cachels) {
256 Dynarr_free(w->glyph_cachels);
257 w->glyph_cachels = 0;
261 DEFINE_LRECORD_IMPLEMENTATION("window", window,
262 mark_window, print_window, finalize_window,
263 0, 0, 0, struct window);
265 #define INIT_DISP_VARIABLE(field, initialization) \
266 p->field[CURRENT_DISP] = initialization; \
267 p->field[DESIRED_DISP] = initialization; \
268 p->field[CMOTION_DISP] = initialization;
270 /* We have an implicit assertion that the first two elements (default
271 and modeline faces) are always present in the face_element_cache.
272 Normally redisplay ensures this. However, it is possible for a
273 window to get created and functions which reference these values
274 called before redisplay works with the window for the first time.
275 All callers of allocate_window should therefore call
276 reset_face_cachels on the created window. We can't do it
277 here because the window must have its frame pointer set or
278 reset_face_cachels will fail. */
279 Lisp_Object allocate_window(void)
282 struct window *p = alloc_lcrecord_type(struct window, &lrecord_window);
296 INIT_DISP_VARIABLE(start, Fmake_marker());
297 INIT_DISP_VARIABLE(pointm, Fmake_marker());
298 p->sb_point = Fmake_marker();
300 INIT_DISP_VARIABLE(last_modified, Qzero);
301 INIT_DISP_VARIABLE(last_point, Fmake_marker());
302 INIT_DISP_VARIABLE(last_start, Fmake_marker());
303 INIT_DISP_VARIABLE(last_facechange, Qzero);
304 p->face_cachels = Dynarr_new(face_cachel);
305 p->glyph_cachels = Dynarr_new(glyph_cachel);
306 p->line_start_cache = Dynarr_new(line_start_cache);
307 p->subwindow_instance_cache = make_image_instance_cache_hash_table();
309 p->line_cache_last_updated = Qzero;
310 INIT_DISP_VARIABLE(last_point_x, 0);
311 INIT_DISP_VARIABLE(last_point_y, 0);
312 INIT_DISP_VARIABLE(window_end_pos, 0);
313 p->redisplay_end_trigger = Qnil;
315 p->gutter_extent_modiff[0] = 0;
316 p->gutter_extent_modiff[1] = 0;
317 p->gutter_extent_modiff[2] = 0;
318 p->gutter_extent_modiff[3] = 0;
320 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
321 #include "winslots.h"
323 p->windows_changed = 1;
324 p->shadow_thickness_changed = 1;
329 #undef INIT_DISP_VARIABLE
332 * The redisplay structures used to be stored with each window. While
333 * they are logically something associated with frames they can't be
334 * stored there with a redisplay which handles variable height lines.
335 * Lines in horizontally split windows might not line up. So they get
336 * stored with the windows.
338 * The problem with this is window configurations. When restoring a
339 * window configuration it now becomes problematic to do an
340 * incremental redisplay. The solution is to store the redisplay
341 * structures with the frame as they should be but laid out in the
342 * same manner as the window structure. Thus is born the window
345 * It also becomes a convenient place to stick scrollbar instances
346 * since they extrapolate out to having the same problem described for
347 * the display structures.
350 /* Create a new window mirror structure and associated redisplay
352 static struct window_mirror *new_window_mirror(struct frame *f)
354 struct window_mirror *t = xnew_and_zero(struct window_mirror);
358 t->current_display_lines = Dynarr_new(display_line);
359 t->desired_display_lines = Dynarr_new(display_line);
362 #ifdef HAVE_SCROLLBARS
363 t->scrollbar_vertical_instance = NULL;
364 t->scrollbar_horizontal_instance = NULL;
370 /* Synchronize the mirror structure with a given window structure.
371 This is normally called from update_frame_window_mirror with a
372 starting window of f->root_window. */
373 static struct window_mirror *update_mirror_internal(Lisp_Object win,
374 struct window_mirror *mir)
378 free_window_mirror(mir);
383 mir = new_window_mirror(XFRAME(XWINDOW(win)->frame));
385 mir->next = update_mirror_internal(XWINDOW(win)->next, mir->next);
386 mir->hchild = update_mirror_internal(XWINDOW(win)->hchild, mir->hchild);
387 mir->vchild = update_mirror_internal(XWINDOW(win)->vchild, mir->vchild);
390 * If the redisplay structs are not empty and the mirror has
391 * children, then this mirror structure was formerly being used for
392 * display but is no longer. Reset its current display structs so
393 * that redisplay doesn't accidentally think they are accurate if it
394 * is later used for display purposes once again. Also, mark the
395 * scrollbar instance as not active.
397 if (mir->vchild || mir->hchild) {
398 /* The redisplay structures are big. Leaving them around in
399 non-leaf windows can add up to a lot of wasted space. So
401 free_display_structs(mir);
402 mir->current_display_lines = Dynarr_new(display_line);
403 mir->desired_display_lines = Dynarr_new(display_line);
405 #ifdef HAVE_SCROLLBARS
406 update_window_scrollbars(XWINDOW(win), mir, 0, 0);
414 /* Given a window mirror, determine which real window it contains the
415 redisplay structures for. */
417 real_window_internal(Lisp_Object win, struct window_mirror *rmir,
418 struct window_mirror *mir)
420 for (; !NILP(win) && rmir; win = XWINDOW(win)->next, rmir = rmir->next) {
423 if (!NILP(XWINDOW(win)->vchild)) {
425 real_window_internal(XWINDOW(win)->vchild,
430 if (!NILP(XWINDOW(win)->hchild)) {
432 real_window_internal(XWINDOW(win)->hchild,
442 /* Given a real window, find the mirror structure which contains its
443 redisplay structures. */
444 static struct window_mirror *find_window_mirror_internal(Lisp_Object win,
449 for (; !NILP(win); win = XWINDOW(win)->next, rmir = rmir->next) {
450 if (w == XWINDOW(win))
453 if (!NILP(XWINDOW(win)->vchild)) {
454 struct window_mirror *retval =
455 find_window_mirror_internal(XWINDOW(win)->vchild,
461 if (!NILP(XWINDOW(win)->hchild)) {
462 struct window_mirror *retval =
463 find_window_mirror_internal(XWINDOW(win)->hchild,
473 /* Update the mirror structure for the given frame. */
474 void update_frame_window_mirror(struct frame *f)
476 f->root_mirror = update_mirror_internal(f->root_window, f->root_mirror);
480 /* Free a given mirror structure along with all of its children as
481 well as their associated display structures. */
482 void free_window_mirror(struct window_mirror *mir)
485 struct window_mirror *free_me = mir;
487 free_window_mirror(mir->hchild);
489 free_window_mirror(mir->vchild);
490 #ifdef HAVE_SCROLLBARS
491 release_window_mirror_scrollbars(mir);
493 free_display_structs(mir);
499 /* Given a mirror structure, return the window it mirrors. Calls
500 real_window_internal to do most of the work. */
501 Lisp_Object real_window(struct window_mirror *mir, int no_abort)
503 Lisp_Object retval = real_window_internal(mir->frame->root_window,
504 mir->frame->root_mirror, mir);
505 if (NILP(retval) && !no_abort)
511 /* Given a real window, return its mirror structure. Calls
512 find_window_mirror_internal to do all of the work. */
513 struct window_mirror *find_window_mirror(struct window *w)
515 struct frame *f = XFRAME(w->frame);
517 update_frame_window_mirror(f);
518 return find_window_mirror_internal(f->root_window, f->root_mirror, w);
521 /*****************************************************************************
522 find_window_by_pixel_pos
524 Given a pixel position relative to a frame, find the window at that
526 ****************************************************************************/
527 struct window *find_window_by_pixel_pos(int pix_x, int pix_y, Lisp_Object win)
532 for (; !NILP(win); win = XWINDOW(win)->next) {
535 if (!NILP(XWINDOW(win)->vchild)) {
536 w = find_window_by_pixel_pos(pix_x, pix_y,
537 XWINDOW(win)->vchild);
541 if (!NILP(XWINDOW(win)->hchild)) {
542 w = find_window_by_pixel_pos(pix_x, pix_y,
543 XWINDOW(win)->hchild);
548 if (pix_x >= WINDOW_LEFT(w)
549 && pix_x <= WINDOW_RIGHT(w)
550 && pix_y >= WINDOW_TOP(w)
551 && pix_y <= WINDOW_BOTTOM(w))
557 /* Return a pointer to the display structures for the given window. */
558 display_line_dynarr *window_display_lines(struct window * w, int which)
560 struct window_mirror *t;
562 if (XFRAME(w->frame)->mirror_dirty)
563 update_frame_window_mirror(XFRAME(w->frame));
564 t = find_window_mirror(w);
568 if (which == CURRENT_DISP)
569 return t->current_display_lines;
570 else if (which == DESIRED_DISP)
571 return t->desired_display_lines;
572 else if (which == CMOTION_DISP)
573 /* The CMOTION_DISP display lines are global. */
574 return cmotion_display_lines;
578 return 0; /* shut up compiler */
581 struct buffer *window_display_buffer(struct window *w)
583 struct window_mirror *t;
585 if (XFRAME(w->frame)->mirror_dirty)
586 update_frame_window_mirror(XFRAME(w->frame));
587 t = find_window_mirror(w);
594 void set_window_display_buffer(struct window *w, struct buffer *b)
596 struct window_mirror *t;
598 if (XFRAME(w->frame)->mirror_dirty)
599 update_frame_window_mirror(XFRAME(w->frame));
600 t = find_window_mirror(w);
607 /* Determining a window's position based solely on its pixel
608 positioning doesn't work. Instead, we do it the intelligent way,
609 by checking its positioning in the window hierarchy. */
610 int window_is_leftmost(struct window *w)
612 Lisp_Object parent, current_ancestor, window;
614 XSETWINDOW(window, w);
616 parent = XWINDOW(window)->parent;
617 current_ancestor = window;
619 while (!NILP(parent)) {
620 if (!NILP(XWINDOW(parent)->hchild) &&
621 !EQ(XWINDOW(parent)->hchild, current_ancestor))
624 current_ancestor = parent;
625 parent = XWINDOW(parent)->parent;
631 int window_is_rightmost(struct window *w)
633 Lisp_Object parent, current_ancestor, window;
635 XSETWINDOW(window, w);
637 parent = XWINDOW(window)->parent;
638 current_ancestor = window;
640 while (!NILP(parent)) {
641 if (!NILP(XWINDOW(parent)->hchild)
642 && !NILP(XWINDOW(current_ancestor)->next))
645 current_ancestor = parent;
646 parent = XWINDOW(parent)->parent;
652 static int window_full_width_p(struct window *w)
654 return window_is_leftmost(w) && window_is_rightmost(w);
657 int window_is_highest(struct window *w)
659 Lisp_Object parent, current_ancestor, window;
661 XSETWINDOW(window, w);
663 parent = XWINDOW(window)->parent;
664 current_ancestor = window;
666 while (!NILP(parent)) {
667 if (!NILP(XWINDOW(parent)->vchild) &&
668 !EQ(XWINDOW(parent)->vchild, current_ancestor))
671 current_ancestor = parent;
672 parent = XWINDOW(parent)->parent;
675 /* This is really to catch the minibuffer but we make it generic in
676 case we ever change things around to let the minibuffer be on top. */
677 if (NILP(XWINDOW(current_ancestor)->prev))
683 int window_is_lowest(struct window *w)
685 Lisp_Object parent, current_ancestor, window;
687 XSETWINDOW(window, w);
689 parent = XWINDOW(window)->parent;
690 current_ancestor = window;
692 while (!NILP(parent)) {
693 if (!NILP(XWINDOW(parent)->vchild)
694 && !NILP(XWINDOW(current_ancestor)->next))
697 current_ancestor = parent;
698 parent = XWINDOW(parent)->parent;
704 #if 0 /* not currently used */
706 static int window_full_height_p(struct window *w)
708 return window_is_highest(w) && window_is_lowest(w);
713 int window_truncation_on(struct window *w)
715 /* Minibuffer windows are never truncated.
716 #### is this the right way ? */
717 if (MINI_WINDOW_P(w))
720 /* Horizontally scrolled windows are truncated. */
724 /* If truncate_partial_width_windows is true and the window is not
725 the full width of the frame it is truncated. */
726 if (!NILP(symbol_value_in_buffer(Qtruncate_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;
749 static int have_undivided_common_edge(struct window *w_right, void *closure)
751 struct window *w_left = (struct window *)closure;
752 return (WINDOW_RIGHT(w_left) == WINDOW_LEFT(w_right)
753 && WINDOW_TOP(w_left) < WINDOW_BOTTOM(w_right)
754 && WINDOW_TOP(w_right) < WINDOW_BOTTOM(w_left)
755 #ifdef HAVE_SCROLLBARS
756 && (NILP(w_right->scrollbar_on_left_p)
757 || NILP(w_right->vertical_scrollbar_visible_p)
758 || ZEROP(w_right->scrollbar_width))
763 static int window_needs_vertical_divider_1(struct window *w)
765 /* Never if we're on the right */
766 if (window_is_rightmost(w))
769 /* Always if draggable */
770 if (!NILP(w->vertical_divider_always_visible_p))
773 #ifdef HAVE_SCROLLBARS
774 /* Our right scrollbar is enough to separate us at the right */
775 if (NILP(w->scrollbar_on_left_p)
776 && !NILP(w->vertical_scrollbar_visible_p)
777 && !ZEROP(w->scrollbar_width))
781 /* Ok. to determine whether we need a divider on the left, we must
782 check that our right neighbor windows have scrollbars on their
783 left sides. We must check all such windows which have common
784 left edge with our window's right edge. */
785 return map_windows(XFRAME(WINDOW_FRAME(w)),
786 have_undivided_common_edge, (void *)w);
789 int window_needs_vertical_divider(struct window *w)
791 if (!w->need_vertical_divider_valid_p) {
792 w->need_vertical_divider_p = window_needs_vertical_divider_1(w);
793 w->need_vertical_divider_valid_p = 1;
795 return w->need_vertical_divider_p;
798 /* Called from invalidate_vertical_divider_cache_in_frame */
800 invalidate_vertical_divider_cache_in_window(struct window *w, void *u_n_u_s_e_d)
802 w->need_vertical_divider_valid_p = 0;
806 /* Calculate width of vertical divider, including its shadows
807 and spacing. The returned value is effectively the distance
808 between adjacent window edges. This function does not check
809 whether a window needs a vertical divider, so the returned
810 value is a "theoretical" one */
811 int window_divider_width(struct window *w)
813 /* the shadow thickness can be negative. This means that the divider
814 will have a depressed look */
816 if (FRAME_WIN_P(XFRAME(WINDOW_FRAME(w))))
817 return XINT(w->vertical_divider_line_width)
818 + 2 * XINT(w->vertical_divider_spacing)
819 + 2 * abs(XINT(w->vertical_divider_shadow_thickness));
821 return XINT(w->vertical_divider_line_width) == 0 ? 0 : 1;
824 int window_scrollbar_width(struct window *w)
826 #ifdef HAVE_SCROLLBARS
830 || NILP(w->vertical_scrollbar_visible_p))
831 /* #### when does NILP (w->buffer) happen? */
834 return XINT(w->scrollbar_width);
837 #endif /* HAVE_SCROLLBARS */
840 /* Horizontal scrollbars are only active on windows with truncation
842 int window_scrollbar_height(struct window *w)
844 #ifdef HAVE_SCROLLBARS
848 || NILP(w->horizontal_scrollbar_visible_p)
849 || !window_truncation_on(w))
852 return XINT(w->scrollbar_height);
855 #endif /* HAVE_SCROLLBARS */
858 int window_modeline_height(struct window *w)
860 struct frame *f = XFRAME(w->frame);
863 if (MINI_WINDOW_P(w) || NILP(w->buffer)) {
865 } else if (!WINDOW_HAS_MODELINE_P(w)) {
866 if (window_scrollbar_height(w))
869 modeline_height = FRAMEMETH(f, divider_height, ());
871 if (!EQ(Qzero, w->modeline_shadow_thickness)
874 (2 * MODELINE_SHADOW_THICKNESS(w));
880 display_line_dynarr *dla;
882 /* We don't force a regeneration of the modeline here.
883 Instead it is now a precondition that any function calling
884 this should make sure that one of these structures is
885 up-to-date. In practice this only affects two internal
886 redisplay functions, regenerate_window and
887 regenerate_window_point_center. */
888 /* We check DESIRED_DISP because if it is valid it is more
889 up-to-date than CURRENT_DISP. For calls to this outside
890 of redisplay it doesn't matter which structure we check
891 since there is a redisplay condition that these
892 structures be identical outside of redisplay. */
893 dla = window_display_lines(w, DESIRED_DISP);
894 if (dla && Dynarr_length(dla)
895 && Dynarr_atp(dla, 0)->modeline)
897 (Dynarr_atp(dla, 0)->ascent +
898 Dynarr_atp(dla, 0)->descent);
900 dla = window_display_lines(w, CURRENT_DISP);
901 if (dla && Dynarr_length(dla)
902 && Dynarr_atp(dla, 0)->modeline)
904 (Dynarr_atp(dla, 0)->ascent +
905 Dynarr_atp(dla, 0)->descent);
907 /* This should be an abort except I'm not yet 100%
908 confident that it won't ever get hit (though I
909 haven't been able to trigger it). It is extremely
910 unlikely to cause any noticeable problem and even if
911 it does it will be a minor display glitch. */
912 /* #### Bullshit alert. It does get hit and it causes
913 noticeable glitches. real_current_modeline_height
914 is a kludge to fix this for 19.14. */
916 real_current_modeline_height(w);
919 if (!EQ(Qzero, w->modeline_shadow_thickness)
922 (2 * MODELINE_SHADOW_THICKNESS(w));
926 return modeline_height;
929 /*****************************************************************************
930 margin_width_internal
932 For a given window, return the width in pixels of the specified margin.
933 ****************************************************************************/
934 static int margin_width_internal(struct window *w, int left_margin)
937 int window_cwidth = window_char_width(w, 1);
942 /* We might be getting called on a non-leaf. */
946 /* The minibuffer never has margins. */
947 if (MINI_WINDOW_P(w))
950 XSETWINDOW(window, w);
951 b = XBUFFER(w->buffer);
952 margin_cwidth = (left_margin ? XINT(w->left_margin_width) :
953 XINT(w->right_margin_width));
955 default_face_height_and_width(window, 0, &font_width);
957 /* The left margin takes precedence over the right margin so we
958 subtract its width from the space available for the right
961 window_cwidth -= XINT(w->left_margin_width);
963 /* The margin cannot be wider than the window is. We allow the
964 value to be bigger since it is possible for the user to enlarge
965 the window such that the left margin value would no longer be too
966 big, but we won't return a value that is larger. */
967 if (margin_cwidth > window_cwidth)
968 margin_cwidth = window_cwidth;
970 /* At the user level the margin is always specified in characters.
971 Internally however it is manipulated in terms of pixels. */
972 return margin_cwidth * font_width;
975 int window_left_margin_width(struct window *w)
977 return margin_width_internal(w, 1);
980 int window_right_margin_width(struct window *w)
982 return margin_width_internal(w, 0);
985 /*****************************************************************************
988 The gutters of a window are those areas in the boundary defined by
989 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
990 do not contain text. Items which may be in the gutters include
991 scrollbars, toolbars and modelines. The margin areas are not
992 included. This is an exception made because redisplay special cases
993 the handling of those areas in many places in such a way that
994 including them in the gutter area would make life difficult.
996 The size functions refer to height for the bottom and top gutters and
997 width for the left and right gutters. The starting position
998 functions refer to the Y coord for bottom and top gutters and the X
999 coord for left and right gutters. All starting positions are
1000 relative to the frame, not the window.
1001 ****************************************************************************/
1003 static int window_top_window_gutter_height(struct window *w)
1005 if (!NILP(w->hchild) || !NILP(w->vchild))
1008 #ifdef HAVE_SCROLLBARS
1009 if (!NILP(w->scrollbar_on_top_p))
1010 return window_scrollbar_height(w);
1016 int window_top_gutter_height(struct window *w)
1018 return window_top_window_gutter_height(w);
1021 static int window_bottom_window_gutter_height(struct window *w)
1025 if (!NILP(w->hchild) || !NILP(w->vchild))
1028 gutter = window_modeline_height(w);
1030 #ifdef HAVE_SCROLLBARS
1031 if (NILP(w->scrollbar_on_top_p))
1032 return window_scrollbar_height(w) + gutter;
1038 int window_bottom_gutter_height(struct window *w)
1040 return window_bottom_window_gutter_height(w);
1043 static int window_left_window_gutter_width(struct window *w, int modeline)
1045 if (!NILP(w->hchild) || !NILP(w->vchild))
1048 #ifdef HAVE_SCROLLBARS
1049 if (!modeline && !NILP(w->scrollbar_on_left_p))
1050 return window_scrollbar_width(w);
1056 int window_left_gutter_width(struct window *w, int modeline)
1058 return window_left_window_gutter_width(w, modeline);
1061 static int window_right_window_gutter_width(struct window *w, int modeline)
1065 if (!NILP(w->hchild) || !NILP(w->vchild))
1068 #ifdef HAVE_SCROLLBARS
1069 if (!modeline && NILP(w->scrollbar_on_left_p))
1070 gutter += window_scrollbar_width(w);
1073 if (window_needs_vertical_divider(w))
1074 gutter += window_divider_width(w);
1079 int window_right_gutter_width(struct window *w, int modeline)
1081 return window_right_window_gutter_width(w, modeline);
1084 static int window_pixel_height(struct window *w)
1086 return WINDOW_HEIGHT(w);
1089 DEFUN("windowp", Fwindowp, 1, 1, 0, /*
1090 Return t if OBJECT is a window.
1094 return WINDOWP(object) ? Qt : Qnil;
1097 DEFUN("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1098 Return t if OBJECT is a window which is currently visible.
1102 return WINDOWP(object) && WINDOW_LIVE_P(XWINDOW(object))
1106 DEFUN("selected-window", Fselected_window, 0, 1, 0, /*
1107 Return the window that the cursor now appears in and commands apply
1108 to. If the optional argument CON-DEV-OR-FRAME is specified and is a
1109 frame, return the selected window used by that frame. If
1110 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1111 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1112 that console's selected device will be used. Otherwise, the selected
1117 if (NILP(con_dev_or_frame) && NILP(Fselected_device(Qnil)))
1118 return Qnil; /* happens at startup */
1121 struct frame *f = decode_frame_or_selected(con_dev_or_frame);
1122 return FRAME_SELECTED_WINDOW(f);
1126 DEFUN("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1127 Return the last selected window that is not a minibuffer window.
1128 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1129 return the last non-minibuffer window used by that frame. If
1130 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1131 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1132 that console's selected device will be used. Otherwise, the selected
1137 if (NILP(con_dev_or_frame) && NILP(Fselected_device(Qnil)))
1138 return Qnil; /* happens at startup */
1141 struct frame *f = decode_frame_or_selected(con_dev_or_frame);
1142 return FRAME_LAST_NONMINIBUF_WINDOW(f);
1146 DEFUN("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1147 Return the window used now for minibuffers.
1148 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1149 return the minibuffer window used by that frame. If CON-DEV-OR-FRAME
1150 is a device, then the selected frame on that device will be used. If
1151 CON-DEV-OR-FRAME is a console, the selected frame on that console's
1152 selected device will be used. Otherwise, the selected frame is used.
1156 return FRAME_MINIBUF_WINDOW(decode_frame_or_selected(con_dev_or_frame));
1159 DEFUN("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1160 Return non-nil if WINDOW is a minibuffer window.
1164 return MINI_WINDOW_P(decode_window(window)) ? Qt : Qnil;
1167 DEFUN("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1168 Return the first horizontal child of WINDOW, or nil.
1172 return decode_window(window)->hchild;
1175 DEFUN("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1176 Return the first vertical child of WINDOW, or nil.
1180 return decode_window(window)->vchild;
1183 DEFUN("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1184 Return the next window on the same level as WINDOW, or nil.
1188 return decode_window(window)->next;
1191 DEFUN("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1192 Return the previous window on the same level as WINDOW, or nil.
1196 return decode_window(window)->prev;
1199 DEFUN("window-parent", Fwindow_parent, 1, 1, 0, /*
1200 Return the parent of WINDOW, or nil.
1204 return decode_window(window)->parent;
1207 DEFUN("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1208 Return non-nil if WINDOW is along the bottom of its frame.
1212 return window_is_lowest(decode_window(window)) ? Qt : Qnil;
1215 DEFUN("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1216 Return non-nil if WINDOW is along the top of its frame.
1220 return window_is_highest(decode_window(window)) ? Qt : Qnil;
1223 DEFUN("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1224 Return non-nil if WINDOW is along the left edge of its frame.
1228 return window_is_leftmost(decode_window(window)) ? Qt : Qnil;
1231 DEFUN("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1232 Return non-nil if WINDOW is along the right edge of its frame.
1236 return window_is_rightmost(decode_window(window)) ? Qt : Qnil;
1239 DEFUN("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1240 Return t if position POS is currently on the frame in WINDOW.
1241 Returns nil if that position is scrolled vertically out of view. POS
1242 defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1246 struct window *w = decode_window(window);
1247 Bufpos top = marker_position(w->start[CURRENT_DISP]);
1249 struct buffer *buf = XBUFFER(w->buffer);
1252 posint = BUF_PT(buf);
1254 CHECK_INT_COERCE_MARKER(pos);
1258 if (posint < top || posint > BUF_ZV(buf))
1261 /* w->start can be out of range. If it is, do something reasonable. */
1262 if (top < BUF_BEGV(buf) || top > BUF_ZV(buf))
1265 return point_would_be_visible(w, top, posint) ? Qt : Qnil;
1268 struct window *decode_window(Lisp_Object window)
1271 Lisp_Object tmp = Fselected_window(Qnil);
1272 return XWINDOW(tmp);
1274 CHECK_LIVE_WINDOW(window);
1275 return XWINDOW(window);
1278 DEFUN("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1279 Return the buffer that WINDOW is displaying.
1283 return decode_window(window)->buffer;
1286 DEFUN("window-frame", Fwindow_frame, 0, 1, 0, /*
1287 Return the frame that window WINDOW is on.
1291 return decode_window(window)->frame;
1294 DEFUN("window-height", Fwindow_height, 0, 1, 0, /*
1295 Return the number of default lines in WINDOW.
1296 This actually works by dividing the window's pixel height (including
1297 the modeline and horizontal scrollbar, if any) by the height of the
1298 default font; therefore, the number of displayed lines will probably
1301 Use `window-height' to get consistent results in geometry calculations.
1302 Use `window-displayed-height' to get the actual number of lines
1303 currently displayed in a window.
1305 The names are somewhat confusing; here's a table to help out:
1308 ---------------------------------------------------------------------
1310 (rows/columns) window-width window-text-area-height
1311 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1314 (rows/columns) window-full-width window-height
1315 (pixels) window-pixel-width window-pixel-height
1318 (rows/columns) ---- window-displayed-height
1319 (pixels) ---- window-displayed-text-pixel-height
1323 return make_int(window_char_height(decode_window(window), 1));
1326 DEFUN("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1327 Return the number of lines currently displayed in WINDOW.
1328 This counts the actual number of lines displayed in WINDOW
1329 \(as opposed to `window-height'). The modeline and horizontal
1330 scrollbar do not count as lines. If there is some blank space
1331 between the end of the buffer and the end of the window, this
1332 function pretends that there are lines of text in the default
1337 return make_int(window_displayed_height(decode_window(window)));
1340 DEFUN("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1341 Return the height of WINDOW in pixels. Defaults to current window.
1342 This includes the window's modeline and horizontal scrollbar (if any).
1346 return make_int(window_pixel_height(decode_window(window)));
1349 DEFUN("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1350 Return the number of default lines in the text area of WINDOW.
1351 This actually works by dividing the window's text area pixel height
1352 (i.e. excluding the modeline and horizontal scrollbar, if any) by the
1353 height of the default font; therefore, the number of displayed lines
1354 will probably be different.
1356 See also `window-height' and `window-displayed-height'.
1360 return make_int(window_char_height(decode_window(window), 0));
1363 DEFUN("window-text-area-pixel-height", Fwindow_text_area_pixel_height, 0, 1, 0, /*
1364 Return the height in pixels of the text-displaying portion of WINDOW.
1365 Unlike `window-pixel-height', the space occupied by the modeline and
1366 horizontal scrollbar, if any, is not counted.
1370 struct window *w = decode_window(window);
1372 return make_int(WINDOW_TEXT_HEIGHT(w));
1375 DEFUN("window-displayed-text-pixel-height", Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1376 Return the height in pixels of the text displayed in WINDOW.
1377 Unlike `window-text-area-pixel-height', any blank space below the
1378 end of the buffer is not included. If optional argument NOCLIPPED
1379 is non-nil, do not include space occupied by clipped lines.
1381 (window, noclipped))
1384 Bufpos start, eobuf;
1386 int hlimit, height, prev_height = -1;
1390 line_start_cache_dynarr *cache;
1393 window = Fselected_window(Qnil);
1395 CHECK_LIVE_WINDOW(window);
1396 w = XWINDOW(window);
1398 start = marker_position(w->start[CURRENT_DISP]);
1399 hlimit = WINDOW_TEXT_HEIGHT(w);
1400 eobuf = BUF_ZV(XBUFFER(w->buffer));
1402 default_face_height_and_width(window, &defheight, NULL);
1404 /* guess lines needed in line start cache + a few extra */
1405 needed = (hlimit + defheight - 1) / defheight + 3;
1408 elt = point_in_line_start_cache(w, start, needed);
1409 assert(elt >= 0); /* in the cache */
1411 cache = w->line_start_cache;
1412 nelt = Dynarr_length(cache);
1415 for (i = elt; i < nelt; i++) {
1416 line = Dynarr_atp(cache, i)->height;
1418 if (height + line > hlimit)
1419 return make_int(!NILP(noclipped) ? height :
1424 if (height == hlimit
1425 || Dynarr_atp(cache, i)->end >= eobuf)
1426 return make_int(height);
1429 /* get here => need more cache lines. try again. */
1430 assert(height > prev_height); /* progress? */
1431 prev_height = height;
1434 ((hlimit - height) * (nelt - elt) + height - 1) / height +
1438 RETURN_NOT_REACHED(make_int(0)) /* shut up compiler */
1441 DEFUN("window-width", Fwindow_width, 0, 1, 0, /*
1442 Return the number of display columns in WINDOW.
1443 This is the width that is usable columns available for text in WINDOW,
1444 and does not include vertical scrollbars, dividers, or the like. See also
1445 `window-full-width' and `window-height'.
1449 return make_int(window_char_width(decode_window(window), 0));
1452 DEFUN("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1453 Return the total number of columns in WINDOW.
1454 This is like `window-width' but includes vertical scrollbars, dividers,
1459 return make_int(window_char_width(decode_window(window), 1));
1462 DEFUN("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1463 Return the width of WINDOW in pixels. Defaults to current window.
1467 return make_int(decode_window(window)->pixel_width);
1470 DEFUN("window-text-area-pixel-width", Fwindow_text_area_pixel_width, 0, 1, 0, /*
1471 Return the width in pixels of the text-displaying portion of WINDOW.
1472 Unlike `window-pixel-width', the space occupied by the vertical
1473 scrollbar or divider, if any, is not counted.
1477 struct window *w = decode_window(window);
1479 return make_int(WINDOW_TEXT_WIDTH(w));
1482 DEFUN("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1483 Return the number of columns by which WINDOW is scrolled from left margin.
1487 return make_int(decode_window(window)->hscroll);
1490 DEFUN("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1491 Return the horizontal scrolling amount of WINDOW's modeline.
1492 If the window has no modeline, return nil.
1496 struct window *w = decode_window(window);
1498 return (WINDOW_HAS_MODELINE_P(w)) ? make_int((int)w->modeline_hscroll) :
1502 DEFUN("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1503 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1504 If NCOL is negative, it will silently be forced to 0.
1505 If the window has no modeline, return nil. Otherwise, return the actual
1510 struct window *w = decode_window(window);
1512 if (WINDOW_HAS_MODELINE_P(w)) {
1516 ncols = (XINT(ncol) <= 0) ? 0 : (Charcount) XINT(ncol);
1517 if (ncols != w->modeline_hscroll) {
1518 MARK_MODELINE_CHANGED;
1519 w->modeline_hscroll = ncols;
1521 return make_int((int)ncols);
1527 DEFUN("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1528 Set number of columns WINDOW is scrolled from left margin to NCOL.
1529 NCOL should be zero or positive.
1540 w = decode_window(window);
1541 if (w->hscroll != ncols)
1542 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1547 #if 0 /* bogus FSF crock */
1549 xxDEFUN("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1550 Return WINDOW's redisplay end trigger value.
1551 See `set-window-redisplay-end-trigger' for more information.
1555 return decode_window(window)->redisplay_end_trigger;
1558 xxDEFUN("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1559 Set WINDOW's redisplay end trigger value to VALUE.
1560 VALUE should be a buffer position (typically a marker) or nil.
1561 If it is a buffer position, then if redisplay in WINDOW reaches a position
1562 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1563 with two arguments: WINDOW, and the end trigger value.
1564 Afterwards the end-trigger value is reset to nil.
1568 return (decode_window(window)->redisplay_end_trigger = value);
1573 DEFUN("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1574 Return a list of the pixel edge coordinates of WINDOW.
1575 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1576 all relative to 0, 0 at the top left corner of WINDOW's frame.
1577 The frame toolbars, menubars and gutters are considered to be outside
1578 of this area, while the scrollbars are considered to be inside.
1582 struct window *w = decode_window(window);
1583 struct frame *f = XFRAME(w->frame);
1586 w->pixel_left - FRAME_LEFT_BORDER_END(f) -
1587 FRAME_LEFT_GUTTER_BOUNDS(f);
1589 w->pixel_top - FRAME_TOP_BORDER_END(f) - FRAME_TOP_GUTTER_BOUNDS(f);
1591 return list4(make_int(left),
1593 make_int(left + w->pixel_width),
1594 make_int(top + w->pixel_height));
1597 DEFUN("window-text-area-pixel-edges", Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1598 Return a list of the pixel edge coordinates of the text area of WINDOW.
1599 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1600 all relative to 0, 0 at the top left corner of the total area allocated
1601 to the window, which includes the scrollbars.
1605 struct window *w = decode_window(window);
1607 int left = window_left_gutter_width(w, /* modeline = */ 0);
1608 int top = window_top_gutter_height(w);
1609 int right = WINDOW_WIDTH(w) - window_right_gutter_width(w, 0);
1610 int bottom = WINDOW_HEIGHT(w) - window_bottom_gutter_height(w);
1612 return list4(make_int(left),
1613 make_int(top), make_int(right), make_int(bottom));
1616 DEFUN("window-point", Fwindow_point, 0, 1, 0, /*
1617 Return current value of point in WINDOW.
1618 For a non-selected window, this is the value point would have
1619 if that window were selected.
1621 Note that, when WINDOW is the selected window and its buffer
1622 is also currently selected, the value returned is the same as (point).
1623 It would be more strictly correct to return the `top-level' value
1624 of point, outside of any save-excursion forms.
1625 But that value is hard to find.
1629 struct window *w = decode_window(window);
1630 Lisp_Object tmp_win = Fselected_window(XFRAME(w->frame)->device);
1632 /* The special check for current buffer is necessary for this
1633 function to work as defined when called within an excursion. */
1634 if (w == XWINDOW(tmp_win)
1635 && current_buffer == XBUFFER(w->buffer)) {
1636 return Fpoint(Qnil);
1638 return Fmarker_position(w->pointm[CURRENT_DISP]);
1641 DEFUN("window-start", Fwindow_start, 0, 1, 0, /*
1642 Return position at which display currently starts in WINDOW.
1643 This is updated by redisplay or by calling `set-window-start'.
1647 return Fmarker_position(decode_window(window)->start[CURRENT_DISP]);
1650 DEFUN("window-end", Fwindow_end, 0, 2, 0, /*
1651 Return position at which display currently ends in WINDOW.
1652 This is updated by redisplay, when it runs to completion.
1653 Simply changing the buffer text or setting `window-start' does not
1654 update this value. WINDOW defaults to the selected window.
1656 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1657 to be the same value as this function would return at the end of the
1658 next full redisplay assuming nothing else changes in the meantime.
1659 This function is potentially much slower with this flag set.
1661 (window, guarantee))
1663 struct window *w = decode_window(window);
1665 if (NILP(guarantee)) {
1669 return make_int(BUF_Z(XBUFFER(buf)) -
1670 w->window_end_pos[CURRENT_DISP]);
1672 Bufpos startp = marker_position(w->start[CURRENT_DISP]);
1673 return make_int(end_of_last_line(w, startp));
1677 DEFUN("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1678 Return pixel height of visible part of last window line if it is clipped.
1679 If the last line is not clipped, return nil.
1683 struct window *w = decode_window(window);
1684 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
1685 int num_lines = Dynarr_length(dla);
1686 struct display_line *dl;
1688 /* No lines - no clipped lines */
1689 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp(dla, 0)->modeline))
1692 dl = Dynarr_atp(dla, num_lines - 1);
1696 return make_int(dl->ascent + dl->descent - dl->clip);
1699 DEFUN("set-window-point", Fset_window_point, 2, 2, 0, /*
1700 Make point value in WINDOW be at position POS in WINDOW's buffer.
1704 struct window *w = decode_window(window);
1705 Lisp_Object tmp_win;
1707 CHECK_INT_COERCE_MARKER(pos);
1709 tmp_win = Fselected_window(Qnil);
1710 if (w == XWINDOW(tmp_win)) {
1711 Fgoto_char(pos, Qnil);
1713 set_marker_restricted(w->pointm[CURRENT_DISP], pos, w->buffer);
1719 DEFUN("set-window-start", Fset_window_start, 2, 3, 0, /*
1720 Make display in WINDOW start at position POS in WINDOW's buffer.
1721 Optional third arg NOFORCE non-nil inhibits next redisplay
1722 from overriding motion of point in order to display at this exact start.
1724 (window, pos, noforce))
1726 struct window *w = decode_window(window);
1728 CHECK_INT_COERCE_MARKER(pos);
1729 set_marker_restricted(w->start[CURRENT_DISP], pos, w->buffer);
1730 /* this is not right, but much easier than doing what is right. */
1731 /* w->start_at_line_beg = 0; */
1732 /* WTF is the above supposed to mean? GE */
1733 w->start_at_line_beg = beginning_of_line_p(XBUFFER(w->buffer),
1739 w->redo_modeline = 1;
1740 SET_LAST_MODIFIED(w, 0);
1741 SET_LAST_FACECHANGE(w);
1743 MARK_WINDOWS_CHANGED(w);
1748 DEFUN("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1749 Return WINDOW's dedicated object, usually t or nil.
1750 See also `set-window-dedicated-p'.
1754 return decode_window(window)->dedicated;
1757 DEFUN("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1758 Control whether WINDOW is dedicated to the buffer it displays.
1759 If it is dedicated, Emacs will not automatically change
1760 which buffer appears in it.
1761 The second argument is the new value for the dedication flag;
1766 struct window *w = decode_window(window);
1768 w->dedicated = NILP(arg) ? Qnil : Qt;
1770 return w->dedicated;
1773 /* FSFmacs has window-display-table here. We have display table as a
1776 /* Record info on buffer window w is displaying
1777 when it is about to cease to display that buffer. */
1778 static void unshow_buffer(struct window *w)
1780 Lisp_Object buf = w->buffer;
1782 if (XBUFFER(buf) != XMARKER(w->pointm[CURRENT_DISP])->buffer)
1785 /* FSF disables this check, so I'll do it too. I hope it won't
1786 break things. --ben */
1788 if (w == XWINDOW(Fselected_window(Qnil))
1789 || !EQ(buf, XWINDOW(Fselected_window(Qnil))->buffer))
1790 /* Do this except when the selected window's buffer
1791 is being removed from some other window. */
1793 /* last_window_start records the start position that this buffer
1794 had in the last window to be disconnected from it. Now that
1795 this statement is unconditional, it is possible for the
1796 buffer to be displayed in the selected window, while
1797 last_window_start reflects another window which was recently
1798 showing the same buffer. Some people might say that might be
1799 a good thing. Let's see. */
1800 XBUFFER(buf)->last_window_start =
1801 marker_position(w->start[CURRENT_DISP]);
1803 /* Point in the selected window's buffer is actually stored in that
1804 buffer, and the window's pointm isn't used. So don't clobber point
1807 Lisp_Object tmp = Fselected_window(Qnil);
1808 if (!EQ(buf, XWINDOW(tmp)->buffer)) {
1809 struct buffer *b = XBUFFER(buf);
1810 BUF_SET_PT(b, bufpos_clip_to_bounds(
1813 w->pointm[CURRENT_DISP]),
1819 /* Put REPLACEMENT into the window structure in place of OLD. */
1820 static void replace_window(Lisp_Object old, Lisp_Object replacement)
1823 struct window *o = XWINDOW(old), *p = XWINDOW(replacement);
1825 /* If OLD is its frame's root_window, then replacement is the new
1826 root_window for that frame. */
1828 if (EQ(old, FRAME_ROOT_WINDOW(XFRAME(o->frame))))
1829 FRAME_ROOT_WINDOW(XFRAME(o->frame)) = replacement;
1831 WINDOW_LEFT(p) = WINDOW_LEFT(o);
1832 WINDOW_TOP(p) = WINDOW_TOP(o);
1833 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
1834 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
1836 p->next = tem = o->next;
1838 XWINDOW(tem)->prev = replacement;
1840 p->prev = tem = o->prev;
1842 XWINDOW(tem)->next = replacement;
1844 p->parent = tem = o->parent;
1846 if (EQ(XWINDOW(tem)->vchild, old))
1847 XWINDOW(tem)->vchild = replacement;
1848 if (EQ(XWINDOW(tem)->hchild, old))
1849 XWINDOW(tem)->hchild = replacement;
1852 /* #### Here, if replacement is a vertical combination
1853 and so is its new parent, we should make replacement's
1854 children be children of that parent instead. */
1856 ERROR_CHECK_SUBWINDOW_CACHE(p);
1859 static void window_unmap_subwindows(struct window *w)
1861 assert(!NILP(w->subwindow_instance_cache));
1862 elisp_maphash(unmap_subwindow_instance_cache_mapper,
1863 w->subwindow_instance_cache, (void *)1);
1866 /* we're deleting W; set the structure of W to indicate this. */
1868 static void mark_window_as_deleted(struct window *w)
1870 /* The window instance cache is going away now, so need to get the
1871 cachels reset by redisplay. */
1872 MARK_FRAME_SUBWINDOWS_CHANGED(XFRAME(WINDOW_FRAME(w)));
1874 /* The cache is going away. If we leave unmapping to
1875 reset_subwindow_cachels then we get in a situation where the
1876 domain (the window) has been deleted but we still need access to
1877 its attributes in order to unmap windows properly. Since the
1878 subwindows are going to get GC'd anyway as a result of the domain
1879 going away, it is safer to just unmap them all while we know the
1880 domain is still valid. */
1881 ERROR_CHECK_SUBWINDOW_CACHE(w);
1882 window_unmap_subwindows(w);
1885 (while t (split-window) (delete-window))
1886 we end up with a tree of deleted windows which are all connected
1887 through the `next' slot. This might not seem so bad, as they're
1888 deleted, and will presumably be GCed - but if even *one* of those
1889 windows is still being pointed to, by the user, or by a window
1890 configuration, then *all* of those windows stick around.
1892 Since the window-configuration code doesn't need any of the
1893 pointers to other windows (they are all recreated from the
1894 window-config data), we set them all to nil so that we
1895 are able to collect more actual garbage. */
1901 w->subwindow_instance_cache = Qnil;
1905 /* Free the extra data structures attached to windows immediately so
1906 they don't sit around consuming excess space. They will be
1907 reinitialized by the window-configuration code as necessary. */
1908 finalize_window((void *)w, 0);
1911 DEFUN("delete-window", Fdelete_window, 0, 2, "", /*
1912 Remove WINDOW from the display. Default is selected window.
1913 If window is the only one on its frame, the frame is deleted as well.
1914 Normally, you cannot delete the last non-minibuffer-only frame (you
1915 must use `save-buffers-kill-emacs' or `kill-emacs'). However, if
1916 optional second argument FORCE is non-nil, you can delete the last
1917 frame. (This will automatically call `save-buffers-kill-emacs'.)
1922 /* This function can GC if this is the only window in the frame */
1930 /* Note: this function is called by other C code on non-leaf
1933 /* Do the equivalent of decode_window() but don't error out on
1934 deleted window; it's OK to delete an already-deleted window. */
1936 window = Fselected_window(Qnil);
1938 CHECK_WINDOW(window);
1940 w = XWINDOW(window);
1942 /* It's okay to delete an already-deleted window. */
1943 if (!WINDOW_LIVE_P(w))
1946 frame = WINDOW_FRAME(w);
1948 d = XDEVICE(FRAME_DEVICE(f));
1950 if (TOP_LEVEL_WINDOW_P(w)) {
1951 if (NILP(memq_no_quit(frame, DEVICE_FRAME_LIST(d))))
1952 /* this frame isn't fully initialized yet; don't blow up. */
1955 if (MINI_WINDOW_P(XWINDOW(window)))
1956 error("Attempt to delete the minibuffer window");
1958 /* It has been suggested that it's a good thing for C-x 0 to have this
1959 behavior, but not such a good idea for #'delete-window to have it.
1960 Maybe C-x 0 should be bound to something else, or maybe frame
1961 deletion should only happen when this is called interactively.
1963 delete_frame_internal(f, !NILP(force), 0, 0);
1967 /* At this point, we know the window has a parent. */
1969 par = XWINDOW(parent);
1971 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1972 /* It's quite likely that deleting a window will result in
1973 subwindows needing to be deleted also (since they are cached
1974 per-window). So we mark them as changed, so that the cachels will
1975 get reset by redisplay and thus deleted subwindows can get
1977 MARK_FRAME_SUBWINDOWS_CHANGED(f);
1979 /* Are we trying to delete any frame's selected window?
1980 Note that we could be dealing with a non-leaf window
1981 where the selected window is one of our children.
1982 So, we check by scanning all the ancestors of the
1983 frame's selected window and comparing each one with
1986 Lisp_Object pwindow;
1988 pwindow = FRAME_SELECTED_WINDOW(f);
1990 while (!NILP(pwindow)) {
1991 if (EQ(window, pwindow))
1993 pwindow = XWINDOW(pwindow)->parent;
1996 if (EQ(window, pwindow)) {
1997 /* OK, we found it. */
1998 Lisp_Object alternative;
1999 alternative = Fnext_window(window, Qlambda, Qnil, Qnil);
2001 /* If we're about to delete the selected window on the
2002 selected frame, then we should use Fselect_window to select
2003 the new window. On the other hand, if we're about to
2004 delete the selected window on any other frame, we shouldn't do
2005 anything but set the frame's selected_window slot. */
2006 if (EQ(frame, Fselected_frame(Qnil)))
2007 Fselect_window(alternative, Qnil);
2009 set_frame_selected_window(f, alternative);
2013 /* w->buffer is nil in a non-leaf window; in this case,
2014 get rid of the markers we maintain that point into that buffer. */
2015 if (!NILP(w->buffer)) {
2017 unchain_marker(w->pointm[CURRENT_DISP]);
2018 unchain_marker(w->pointm[DESIRED_DISP]);
2019 unchain_marker(w->pointm[CMOTION_DISP]);
2020 unchain_marker(w->start[CURRENT_DISP]);
2021 unchain_marker(w->start[DESIRED_DISP]);
2022 unchain_marker(w->start[CMOTION_DISP]);
2023 unchain_marker(w->sb_point);
2024 /* This breaks set-window-configuration if windows in the saved
2025 configuration get deleted and multiple frames are in use. */
2026 /* w->buffer = Qnil; */
2029 /* close up the hole in the sibling list */
2031 XWINDOW(w->next)->prev = w->prev;
2033 XWINDOW(w->prev)->next = w->next;
2034 if (EQ(window, par->hchild))
2035 par->hchild = w->next;
2036 if (EQ(window, par->vchild))
2037 par->vchild = w->next;
2039 /* Find one of our siblings to give our space to. */
2041 Lisp_Object sib = w->prev;
2043 /* If w gives its space to its next sibling, that sibling needs
2044 to have its top/left side pulled back to where w's is.
2045 set_window_{height,width} will re-position the sibling's
2048 WINDOW_TOP(XWINDOW(sib)) = WINDOW_TOP(w);
2049 WINDOW_LEFT(XWINDOW(sib)) = WINDOW_LEFT(w);
2052 /* Stretch that sibling. */
2053 if (!NILP(par->vchild))
2054 set_window_pixheight
2056 (WINDOW_HEIGHT(XWINDOW(sib)) + WINDOW_HEIGHT(w)),
2058 if (!NILP(par->hchild))
2061 (WINDOW_WIDTH(XWINDOW(sib)) + WINDOW_WIDTH(w)), 1);
2064 run_window_configuration_hook( sib );
2068 /* If parent now has only one child,
2069 put the child into the parent's place. */
2071 Lisp_Object parchild = par->hchild;
2073 parchild = par->vchild;
2074 if (NILP(XWINDOW(parchild)->next)) {
2075 replace_window(parent, parchild);
2076 mark_window_as_deleted(XWINDOW(parent));
2080 /* Since we may be deleting combination windows, we must make sure that
2081 not only W but all its children have been marked as deleted. */
2082 if (!NILP(w->hchild))
2083 delete_all_subwindows(XWINDOW(w->hchild));
2084 else if (!NILP(w->vchild))
2085 delete_all_subwindows(XWINDOW(w->vchild));
2087 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and
2088 therefore redisplay, so it requires the mirror structure to be
2089 correct. We must dirty the mirror before it is called. */
2090 f->mirror_dirty = 1;
2092 mark_window_as_deleted(w);
2097 DEFUN("next-window", Fnext_window, 0, 4, 0, /*
2098 Return the next window after WINDOW in the canonical ordering of windows.
2099 If omitted, WINDOW defaults to the selected window.
2101 Optional second arg MINIBUF t means count the minibuffer window even
2102 if not active. MINIBUF nil or omitted means count the minibuffer iff
2103 it is active. MINIBUF neither t nor nil means not to count the
2104 minibuffer even if it is active.
2106 Several frames may share a single minibuffer; if the minibuffer
2107 counts, all windows on all frames that share that minibuffer count
2108 too. Therefore, `next-window' can be used to iterate through the
2109 set of windows even when the minibuffer is on another frame. If the
2110 minibuffer does not count, only windows from WINDOW's frame count.
2112 By default, only the windows in the selected frame are considered.
2113 The optional argument WHICH-FRAMES changes this behavior:
2114 WHICH-FRAMES = `visible' means search windows on all visible frames.
2115 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2116 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2117 WHICH-FRAMES = a frame means search only windows on that frame.
2118 Anything else means restrict to the selected frame.
2120 The optional fourth argument WHICH-DEVICES further clarifies on which
2121 devices to search for frames as specified by WHICH-FRAMES. This value
2122 is only meaningful if WHICH-FRAMES is non-nil.
2123 If nil or omitted, search all devices on the selected console.
2124 If a device, only search that device.
2125 If a console, search all devices on that console.
2126 If a device type, search all devices of that type.
2127 If `window-system', search all window-system devices.
2128 Any other non-nil value means search all devices.
2130 If you use consistent values for MINIBUF, WHICH-FRAMES, and
2131 WHICH-DEVICES, you can use `next-window' to iterate through the entire
2132 cycle of acceptable windows, eventually ending up back at the window
2133 you started with. `previous-window' traverses the same cycle, in the
2136 (window, minibuf, which_frames, which_devices))
2139 Lisp_Object start_window;
2142 window = Fselected_window(Qnil);
2144 CHECK_LIVE_WINDOW(window);
2146 start_window = window;
2148 /* minibuf == nil may or may not include minibuffers.
2149 Decide if it does. */
2151 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2152 else if (!EQ(minibuf, Qt))
2154 /* Now `minibuf' is one of:
2155 t => count all minibuffer windows
2156 lambda => count none of them
2157 or a specific minibuffer window (the active one) to count. */
2159 /* which_frames == nil doesn't specify which frames to include. */
2160 if (NILP(which_frames))
2161 which_frames = (!EQ(minibuf, Qlambda)
2162 ? (FRAME_MINIBUF_WINDOW
2163 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2165 else if (EQ(which_frames, Qvisible)) ;
2166 else if (ZEROP(which_frames)) ;
2167 else if (FRAMEP(which_frames)
2168 && !EQ(which_frames, Fwindow_frame(window)))
2169 /* If which_frames is a frame and window arg isn't on that frame, just
2170 return the first window on the frame. */
2171 return frame_first_window(XFRAME(which_frames));
2172 else if (!EQ(which_frames, Qt))
2173 which_frames = Qnil;
2174 /* Now `which_frames' is one of:
2175 t => search all frames
2176 nil => search just the current frame
2177 visible => search just visible frames
2178 0 => search visible and iconified frames
2179 a window => search the frame that window belongs to. */
2181 /* Do this loop at least once, to get the next window, and perhaps
2182 again, if we hit the minibuffer and that is not acceptable. */
2184 /* Find a window that actually has a next one. This loop
2185 climbs up the tree. */
2186 while (tem = XWINDOW(window)->next, NILP(tem))
2187 if (tem = XWINDOW(window)->parent, !NILP(tem))
2189 else { /* window must be minibuffer window now */
2191 /* We've reached the end of this frame.
2192 Which other frames are acceptable? */
2193 tem = WINDOW_FRAME(XWINDOW(window));
2195 if (!NILP(which_frames)) {
2196 Lisp_Object tem1 = tem;
2198 next_frame(tem, which_frames,
2201 /* In the case where the minibuffer is active,
2202 and we include its frame as well as the selected one,
2203 next_frame may get stuck in that frame.
2204 If that happens, go back to the selected frame
2205 so we can complete the cycle. */
2211 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2217 /* If we're in a combination window, find its first child and
2218 recurse on that. Otherwise, we've found the window we want. */
2220 if (!NILP(XWINDOW(window)->hchild))
2221 window = XWINDOW(window)->hchild;
2222 else if (!NILP(XWINDOW(window)->vchild))
2223 window = XWINDOW(window)->vchild;
2228 /* Which windows are acceptable?
2229 Exit the loop and accept this window if
2230 this isn't a minibuffer window,
2231 or we're accepting all minibuffer windows,
2232 or this is the active minibuffer and we are accepting that one, or
2233 we've come all the way around and we're back at the original window. */
2234 while (MINI_WINDOW_P(XWINDOW(window))
2236 && !EQ(minibuf, window)
2237 && !EQ(window, start_window));
2242 DEFUN("previous-window", Fprevious_window, 0, 4, 0, /*
2243 Return the window preceding WINDOW in the canonical ordering of windows.
2244 If omitted, WINDOW defaults to the selected window.
2246 Optional second arg MINIBUF t means count the minibuffer window even
2247 if not active. MINIBUF nil or omitted means count the minibuffer iff
2248 it is active. MINIBUF neither t nor nil means not to count the
2249 minibuffer even if it is active.
2251 Several frames may share a single minibuffer; if the minibuffer
2252 counts, all windows on all frames that share that minibuffer count
2253 too. Therefore, `previous-window' can be used to iterate through
2254 the set of windows even when the minibuffer is on another frame. If
2255 the minibuffer does not count, only windows from WINDOW's frame count.
2257 By default, only the windows in the selected frame are considered.
2258 The optional argument WHICH-FRAMES changes this behavior:
2259 WHICH-FRAMES = `visible' means search windows on all visible frames.
2260 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2261 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2262 WHICH-FRAMES = a frame means search only windows on that frame.
2263 Anything else means restrict to the selected frame.
2265 The optional fourth argument WHICH-DEVICES further clarifies on which
2266 devices to search for frames as specified by WHICH-FRAMES. This value
2267 is only meaningful if WHICH-FRAMES is non-nil.
2268 If nil or omitted, search all devices on the selected console.
2269 If a device, only search that device.
2270 If a console, search all devices on that console.
2271 If a device type, search all devices of that type.
2272 If `window-system', search all window-system devices.
2273 Any other non-nil value means search all devices.
2275 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2276 you can use `previous-window' to iterate through the entire cycle of
2277 acceptable windows, eventually ending up back at the window you started with.
2278 `next-window' traverses the same cycle, in the reverse order.
2280 (window, minibuf, which_frames, devices))
2283 Lisp_Object start_window;
2286 window = Fselected_window(Qnil);
2288 CHECK_LIVE_WINDOW(window);
2290 start_window = window;
2292 /* minibuf == nil may or may not include minibuffers.
2293 Decide if it does. */
2295 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2296 else if (!EQ(minibuf, Qt))
2298 /* Now `minibuf' is one of:
2299 t => count all minibuffer windows
2300 lambda => count none of them
2301 or a specific minibuffer window (the active one) to count. */
2303 /* which_frames == nil doesn't specify which frames to include.
2304 Decide which frames it includes. */
2305 if (NILP(which_frames))
2306 which_frames = (!EQ(minibuf, Qlambda)
2307 ? (FRAME_MINIBUF_WINDOW
2308 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2310 else if (EQ(which_frames, Qvisible)) ;
2311 else if (ZEROP(which_frames)) ;
2312 else if (FRAMEP(which_frames)
2313 && !EQ(which_frames, Fwindow_frame(window)))
2314 /* If which_frames is a frame and window arg isn't on that frame, just
2315 return the first window on the frame. */
2316 return frame_first_window(XFRAME(which_frames));
2317 else if (!EQ(which_frames, Qt))
2318 which_frames = Qnil;
2319 /* Now `which_frames' is one of:
2320 t => search all frames
2321 nil => search just the current frame
2322 visible => search just visible frames
2323 0 => search visible and iconified frames
2324 a window => search the frame that window belongs to. */
2326 /* Do this loop at least once, to get the next window, and perhaps
2327 again, if we hit the minibuffer and that is not acceptable. */
2329 /* Find a window that actually has a next one. This loop
2330 climbs up the tree. */
2331 while (tem = XWINDOW(window)->prev, NILP(tem))
2332 if (tem = XWINDOW(window)->parent, !NILP(tem))
2334 else { /* window must be minibuffer window now */
2336 /* We have found the top window on the frame.
2337 Which frames are acceptable? */
2338 tem = WINDOW_FRAME(XWINDOW(window));
2340 if (!NILP(which_frames))
2341 /* It's actually important that we use previous_frame here,
2342 rather than next_frame. All the windows acceptable
2343 according to the given parameters should form a ring;
2344 Fnext_window and Fprevious_window should go back and
2345 forth around the ring. If we use next_frame here,
2346 then Fnext_window and Fprevious_window take different
2347 paths through the set of acceptable windows.
2348 window_loop assumes that these `ring' requirement are
2351 Lisp_Object tem1 = tem;
2353 previous_frame(tem, which_frames,
2355 /* In the case where the minibuffer is active,
2356 and we include its frame as well as the selected one,
2357 next_frame may get stuck in that frame.
2358 If that happens, go back to the selected frame
2359 so we can complete the cycle. */
2365 /* If this frame has a minibuffer, find that window first,
2366 because it is conceptually the last window in that frame. */
2367 if (FRAME_HAS_MINIBUF_P(XFRAME(tem)))
2368 tem = FRAME_MINIBUF_WINDOW(XFRAME(tem));
2370 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2377 /* If we're in a combination window, find its first child and
2378 recurse on that. Otherwise, we've found the window we want. */
2380 if (!NILP(XWINDOW(window)->hchild))
2381 window = XWINDOW(window)->hchild;
2382 else if (!NILP(XWINDOW(window)->vchild))
2383 window = XWINDOW(window)->vchild;
2386 while (tem = XWINDOW(window)->next, !NILP(tem))
2390 /* Which windows are acceptable?
2391 Exit the loop and accept this window if
2392 this isn't a minibuffer window,
2393 or we're accepting all minibuffer windows,
2394 or this is the active minibuffer and we are accepting that one, or
2395 we've come all the way around and we're back at the original window. */
2396 while (MINI_WINDOW_P(XWINDOW(window))
2398 && !EQ(minibuf, window)
2399 && !EQ(window, start_window));
2404 DEFUN("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2405 Return the next window which is vertically after WINDOW.
2410 struct window *w = decode_window(window);
2411 XSETWINDOW(window, w);
2413 if (MINI_WINDOW_P(XWINDOW(window)))
2416 root = FRAME_ROOT_WINDOW(XFRAME(WINDOW_FRAME(XWINDOW(window))));
2418 if (EQ(window, root)) {
2420 if (!NILP(XWINDOW(window)->hchild))
2421 window = XWINDOW(window)->hchild;
2422 else if (!NILP(XWINDOW(window)->vchild))
2423 window = XWINDOW(window)->vchild;
2429 if (!NILP(XWINDOW(window)->parent) &&
2430 !NILP(XWINDOW(XWINDOW(window)->parent)->vchild)) {
2431 if (!NILP(XWINDOW(window)->next))
2432 return XWINDOW(window)->next;
2434 window = XWINDOW(window)->parent;
2436 window = XWINDOW(window)->parent;
2438 while (!EQ(window, root));
2441 if (!NILP(XWINDOW(window)->hchild))
2442 window = XWINDOW(window)->hchild;
2443 else if (!NILP(XWINDOW(window)->vchild))
2444 window = XWINDOW(window)->vchild;
2449 DEFUN("other-window", Fother_window, 1, 3, "p", /*
2450 Select the COUNT'th different window on this frame.
2451 All windows on current frame are arranged in a cyclic order.
2452 This command selects the window COUNT steps away in that order.
2453 A negative COUNT moves in the opposite order.
2455 By default, only the windows in the selected frame are considered.
2456 The optional argument WHICH-FRAMES changes this behavior:
2457 WHICH-FRAMES = `visible' means search windows on all visible frames.
2458 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2459 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2460 WHICH-FRAMES = a frame means search only windows on that frame.
2461 Anything else means restrict to the selected frame.
2463 The optional argument WHICH-DEVICES further clarifies on which devices
2464 to search for frames as specified by WHICH-FRAMES. This value is only
2465 meaningful if WHICH-FRAMES is non-nil.
2466 If nil or omitted, search all devices on the selected console.
2467 If a device, only search that device.
2468 If a console, search all devices on that console.
2469 If a device type, search all devices of that type.
2470 If `window-system', search all window-system devices.
2471 Any other non-nil value means search all devices.
2473 (count, which_frames, which_devices))
2479 w = Fselected_window(Qnil);
2483 w = Fnext_window(w, Qnil, which_frames, which_devices);
2487 w = Fprevious_window(w, Qnil, which_frames, which_devices);
2490 Fselect_window(w, Qnil);
2494 /* Look at all windows, performing an operation specified by TYPE
2497 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2498 frame. If FRAMES is a frame, just look at windows on that frame.
2499 If MINI is non-zero, perform the operation on minibuffer windows too.
2504 GET_BUFFER_WINDOW, /* Arg is buffer */
2505 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2506 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2507 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2508 UNDEDICATE_BUFFER, /* Arg is buffer */
2510 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2511 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2515 window_loop(enum window_loop type,
2518 Lisp_Object which_frames,
2519 int dedicated_too, Lisp_Object which_devices)
2521 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2523 Lisp_Object best_window = Qnil;
2524 Lisp_Object next_window;
2525 Lisp_Object last_window;
2526 struct frame *frame;
2527 Lisp_Object frame_arg = Qt;
2528 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2529 /* #### I think the change of "precomputing" last_window and next_window
2530 * #### catch the lossage this is meant(?) to punt on...
2533 Lisp_Object devcons, concons;
2535 /* If we're only looping through windows on a particular frame,
2536 FRAME points to that frame. If we're looping through windows
2537 on all frames, FRAME is 0. */
2538 if (FRAMEP(which_frames))
2539 frame = XFRAME(which_frames);
2540 else if (NILP(which_frames))
2541 frame = selected_frame();
2545 /* FRAME_ARG is Qlambda to stick to one frame,
2546 Qvisible to consider all visible frames,
2549 frame_arg = Qlambda;
2550 } else if (ZEROP(which_frames)) {
2551 frame_arg = which_frames;
2552 } else if (EQ(which_frames, Qvisible)) {
2553 frame_arg = which_frames;
2556 DEVICE_LOOP_NO_BREAK(devcons, concons) {
2557 Lisp_Object device = XCAR(devcons);
2558 Lisp_Object the_frame;
2561 XSETFRAME(the_frame, frame);
2563 the_frame = DEVICE_SELECTED_FRAME(XDEVICE(device));
2565 if (NILP(the_frame))
2568 if (!device_matches_device_spec(device,
2569 NILP(which_devices) ?
2570 FRAME_CONSOLE(XFRAME(the_frame))
2574 /* Pick a window to start with. */
2578 w = FRAME_SELECTED_WINDOW(XFRAME(the_frame));
2580 /* Figure out the last window we're going to mess with. Since
2581 Fnext_window, given the same options, is guaranteed to go in a
2582 ring, we can just use Fprevious_window to find the last one.
2584 We can't just wait until we hit the first window again,
2585 because it might be deleted. */
2588 Fprevious_window(w, mini ? Qt : Qnil, frame_arg, device);
2592 struct window *p = XWINDOW(w);
2594 /* Pick the next window now, since some operations will delete
2595 the current window. */
2597 Fnext_window(w, mini ? Qt : Qnil, frame_arg,
2600 /* #### Still needed ?? */
2601 /* Given the outstanding quality of the rest of this code,
2602 I feel no shame about putting this piece of shit in. */
2603 if (++lose_lose >= 500) {
2604 /* Call to abort() added by Darryl Okahata (16 Nov. 2001),
2605 at Ben's request, to catch any remaining bugs.
2607 If you find that SXEmacs is aborting here, and you
2608 need to be up and running ASAP, it should be safe to
2609 comment out the following abort(), as long as you
2610 leave the "break;" alone. */
2612 break; /* <--- KEEP THIS HERE! Do not delete! */
2615 /* Note that we do not pay attention here to whether
2616 the frame is visible, since Fnext_window skips non-visible frames
2617 if that is desired, under the control of frame_arg. */
2618 if (!MINI_WINDOW_P(p)
2619 || (mini && minibuf_level > 0))
2621 case GET_BUFFER_WINDOW: {
2622 if (XBUFFER(p->buffer) ==
2628 case GET_BUFFER_WINDOW_COUNT: {
2629 if (XBUFFER(p->buffer) ==
2635 case GET_LRU_WINDOW: {
2636 /* t as arg means consider only
2637 full-width windows */
2639 && !window_full_width_p(p))
2641 /* Ignore dedicated windows and
2643 if (MINI_WINDOW_P(p)
2644 || (dedicated_too ? 0 :
2645 !NILP(p->dedicated)))
2647 if (NILP(best_window) ||
2648 (XINT(XWINDOW(best_window)->
2650 > XINT(p->use_time)))
2655 case GET_BUFFER_MRU_WINDOW: {
2656 /* #### what about the first check in
2658 /* Ignore dedicated windows and
2660 if (MINI_WINDOW_P(p)
2661 || (dedicated_too ? 0 :
2662 !NILP(p->dedicated)))
2665 if (XBUFFER(p->buffer) ==
2667 if (NILP(best_window)
2680 case UNDEDICATE_BUFFER: {
2681 if ((XBUFFER(p->buffer) ==
2683 p->dedicated = Qnil;
2688 case DELETE_OTHER_WINDOWS: {
2689 /* Don't delete the last window on a
2690 frame; this can happen when the
2691 minibuffer is selected, and would
2692 cause the frame to be deleted. */
2693 if (p != XWINDOW(obj) &&
2694 !TOP_LEVEL_WINDOW_P(XWINDOW (w))) {
2695 Fdelete_window(w, Qnil);
2700 case DELETE_BUFFER_WINDOWS: {
2701 if (EQ(p->buffer, obj)) {
2703 XFRAME(WINDOW_FRAME(p));
2705 /* If this window is dedicated,
2706 and in a frame of its own,
2708 if (EQ (w, FRAME_ROOT_WINDOW (f))
2709 && !NILP(p->dedicated)
2710 && (allow_deletion_of_last_visible_frame
2711 || other_visible_frames (f)))
2728 /* As we go, check for the end of the
2729 loop. We mustn't start going
2730 around a second time. */
2731 if (EQ(next_window, last_window)) {
2749 /* Now we can safely delete the frame. */
2754 /* If we're deleting the
2757 the frame, find a new
2760 if (NILP(p->parent)) {
2793 case GET_LARGEST_WINDOW: {
2794 /* Ignore dedicated windows and
2796 if (MINI_WINDOW_P(p)
2797 || (dedicated_too ? 0 :
2798 !NILP(p->dedicated)))
2801 /* write the check as follows to
2803 error_check_window() --ben */
2807 XWINDOW(best_window);
2808 if (NILP(best_window) ||
2809 ((WINDOW_HEIGHT(p) *
2811 > (WINDOW_HEIGHT(b) *
2812 WINDOW_WIDTH(b)))) {
2819 case WINDOW_LOOP_UNUSED:
2824 if (EQ(w, last_window)) {
2832 return type == GET_BUFFER_WINDOW_COUNT ? make_int(count) : best_window;
2835 #if 0 /* not currently used */
2837 int buffer_window_count(struct buffer *b, struct frame *f)
2839 Lisp_Object buffer, frame;
2841 XSETFRAME(frame, f);
2842 XSETBUFFER(buffer, b);
2844 return XINT(window_loop(GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2848 int buffer_window_mru(struct window *w)
2850 Lisp_Object window =
2851 window_loop(GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2855 else if (XWINDOW(window) == w)
2863 void undedicate_windows(Lisp_Object buffer, Lisp_Object frame)
2865 window_loop(UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2868 DEFUN("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2869 Return the window least recently selected or used for display.
2871 By default, only the windows in the selected frame are considered.
2872 The optional argument WHICH-FRAMES changes this behavior:
2873 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2874 If WHICH-FRAMES is 0, search all visible and iconified frames.
2875 If WHICH-FRAMES is t, search all frames.
2876 If WHICH-FRAMES is nil, search only the selected frame.
2877 If WHICH-FRAMES is a frame, search only that frame.
2879 The optional argument WHICH-DEVICES further clarifies on which devices
2880 to search for frames as specified by WHICH-FRAMES. This value is only
2881 meaningful if WHICH-FRAMES is non-nil.
2882 If nil or omitted, search all devices on the selected console.
2883 If a device, only search that device.
2884 If a console, search all devices on that console.
2885 If a device type, search all devices of that type.
2886 If `window-system', search all devices on window-system consoles.
2887 Any other non-nil value means search all devices.
2889 (which_frames, which_devices))
2892 /* First try for a non-dedicated window that is full-width */
2893 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2894 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2897 /* Then try for any non-dedicated window */
2898 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 0,
2900 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2904 /* FSFmacs never returns a dedicated window here. If we do,
2905 it makes `display-buffer' not work right. #### All of this
2906 shit is so disgusting and awful that it needs to be rethought
2908 /* then try for a dedicated window that is full-width */
2909 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2910 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2913 /* If none of them, then all windows, dedicated or not. */
2914 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 1,
2917 /* At this point we damn well better have found something. */
2925 DEFUN("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2926 Return the window largest in area.
2928 By default, only the windows in the selected frame are considered.
2929 The optional argument WHICH-FRAMES changes this behavior:
2930 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2931 If WHICH-FRAMES is 0, search all visible and iconified frames.
2932 If WHICH-FRAMES is t, search all frames.
2933 If WHICH-FRAMES is nil, search only the selected frame.
2934 If WHICH-FRAMES is a frame, search only that frame.
2936 The optional argument WHICH-DEVICES further clarifies on which devices
2937 to search for frames as specified by WHICH-FRAMES. This value is only
2938 meaningful if WHICH-FRAMES is non-nil.
2939 If nil or omitted, search all devices on the selected console.
2940 If a device, only search that device.
2941 If a console, search all devices on that console.
2942 If a device type, search all devices of that type.
2943 If `window-system', search all devices on window-system consoles.
2944 Any other non-nil value means search all devices.
2946 (which_frames, which_devices))
2948 /* Don't search dedicated windows because FSFmacs doesn't.
2949 This stuff is all black magic so don't try to apply common
2951 return window_loop(GET_LARGEST_WINDOW, Qnil, 0,
2952 which_frames, 0, which_devices);
2955 DEFUN("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2956 Return a window currently displaying BUFFER, or nil if none.
2958 By default, only the windows in the selected frame are considered.
2959 The optional argument WHICH-FRAMES changes this behavior:
2960 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2961 If WHICH-FRAMES is 0, search all visible and iconified frames.
2962 If WHICH-FRAMES is t, search all frames.
2963 If WHICH-FRAMES is nil, search only the selected frame.
2964 If WHICH-FRAMES is a frame, search only that frame.
2966 The optional argument WHICH-DEVICES further clarifies on which devices
2967 to search for frames as specified by WHICH-FRAMES. This value is only
2968 meaningful if WHICH-FRAMES is non-nil.
2969 If nil or omitted, search all devices on the selected console.
2970 If a device, only search that device.
2971 If a console, search all devices on that console.
2972 If a device type, search all devices of that type.
2973 If `window-system', search all devices on window-system consoles.
2974 Any other non-nil value means search all devices.
2976 (buffer, which_frames, which_devices))
2978 buffer = Fget_buffer(buffer);
2979 if (BUFFERP(buffer))
2980 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2981 return window_loop(GET_BUFFER_WINDOW, buffer, 1,
2982 which_frames, 1, which_devices);
2987 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2988 but there is no sensible way to implement those functions, since
2989 you can't in general derive a window from a buffer. */
2991 DEFUN("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width, 0, 1, 0, /*
2992 Return the width in pixels of the left outside margin of window WINDOW.
2993 If WINDOW is nil, the selected window is assumed.
2997 return make_int(window_left_margin_width(decode_window(window)));
3000 DEFUN("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width, 0, 1, 0, /*
3001 Return the width in pixels of the right outside margin of window WINDOW.
3002 If WINDOW is nil, the selected window is assumed.
3006 return make_int(window_right_margin_width(decode_window(window)));
3009 DEFUN("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
3010 Make WINDOW (or the selected window) fill its frame.
3011 Only the frame WINDOW is on is affected.
3012 This function tries to reduce display jumps
3013 by keeping the text previously visible in WINDOW
3014 in the same place on the frame. Doing this depends on
3015 the value of (window-start WINDOW), so if calling this function
3016 in a program gives strange scrolling, make sure the window-start
3017 value is reasonable when this function is called.
3022 struct window *w = decode_window(window);
3023 struct buffer *b = XBUFFER(w->buffer);
3025 int old_top = WINDOW_TOP(w);
3027 XSETWINDOW(window, w);
3029 if (MINI_WINDOW_P(w) && old_top > 0)
3030 error("Can't expand minibuffer to full frame");
3032 /* Ignore dedicated windows. */
3033 window_loop(DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3035 start_pos = marker_position(w->start[CURRENT_DISP]);
3037 /* Try to minimize scrolling, by setting the window start to the
3038 point which will cause the text at the old window start to be at
3039 the same place on the frame. But don't try to do this if the
3040 window start is outside the visible portion (as might happen when
3041 the display is not current, due to typeahead). */
3042 if (start_pos >= BUF_BEGV(b) && start_pos <= BUF_ZV(b)
3043 && !MINI_WINDOW_P(w)) {
3045 start_with_line_at_pixpos(w, start_pos, old_top);
3047 if (new_start >= BUF_BEGV(b) && new_start <= BUF_ZV(b)) {
3048 Fset_marker(w->start[CURRENT_DISP], make_int(new_start),
3050 w->start_at_line_beg =
3051 beginning_of_line_p(b, new_start);
3053 /* We need to do this, so that the window-scroll-functions
3058 run_window_configuration_hook( window );
3063 DEFUN("delete-windows-on", Fdelete_windows_on, 1, 3, "bDelete windows on (buffer): ", /*
3064 Delete all windows showing BUFFER.
3066 Optional second argument WHICH-FRAMES controls which frames are affected.
3067 If nil or omitted, delete all windows showing BUFFER in any frame.
3068 If t, delete only windows showing BUFFER in the selected frame.
3069 If `visible', delete all windows showing BUFFER in any visible frame.
3070 If a frame, delete only windows showing BUFFER in that frame.
3071 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3072 except that the meanings of nil and t are reversed.
3074 The optional third argument WHICH-DEVICES further clarifies on which
3075 devices to search for frames as specified by WHICH-FRAMES. This value
3076 is only meaningful if WHICH-FRAMES is not t.
3077 If nil or omitted, search only the selected console.
3078 If a device, only search that device.
3079 If a console, search all devices on that console.
3080 If a device type, search all devices of that type.
3081 If `window-system', search all devices on a window system.
3082 Any other non-nil value means search all devices.
3084 (buffer, which_frames, which_devices))
3086 /* This function can GC */
3087 buffer = Fget_buffer(buffer);
3088 CHECK_BUFFER(buffer);
3090 /* WHICH-FRAMES values t and nil mean the opposite of what
3091 window_loop expects. */
3092 if (EQ(which_frames, Qnil))
3094 else if (EQ(which_frames, Qt))
3095 which_frames = Qnil;
3097 /* Ignore dedicated windows. */
3098 window_loop(DELETE_BUFFER_WINDOWS, buffer, 0,
3099 which_frames, 0, which_devices);
3103 static Lisp_Object list_windows(struct window *w, Lisp_Object value)
3106 if (!NILP(w->hchild))
3107 value = list_windows(XWINDOW(w->hchild), value);
3108 else if (!NILP(w->vchild))
3109 value = list_windows(XWINDOW(w->vchild), value);
3112 XSETWINDOW(window, w);
3113 value = Fcons(window, value);
3117 w = XWINDOW(w->next);
3123 list_all_windows(Lisp_Object frame_spec, Lisp_Object device_spec)
3125 Lisp_Object devcons, concons;
3126 Lisp_Object retval = Qnil;
3128 DEVICE_LOOP_NO_BREAK(devcons, concons) {
3129 Lisp_Object frame_list, the_window;
3130 Lisp_Object device, tail;
3132 device = XCAR(devcons);
3133 frame_list = DEVICE_FRAME_LIST(XDEVICE(device));
3135 LIST_LOOP(tail, frame_list) {
3136 if ((NILP(frame_spec)
3138 DEVICE_SELECTED_FRAME(XDEVICE(device))))
3139 || (EQ(frame_spec, Qvisible)
3140 && !FRAME_VISIBLE_P(XFRAME(XCAR(tail))))
3141 || (FRAMEP(frame_spec)
3142 && !EQ(frame_spec, XCAR(tail)))
3143 || (!NILP(frame_spec)
3144 && !device_matches_device_spec(device,
3150 the_window = FRAME_ROOT_WINDOW(XFRAME(XCAR(tail)));
3151 retval = list_windows(XWINDOW(the_window), retval);
3154 return Fnreverse(retval);
3157 DEFUN("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3, "bReplace buffer in windows: ", /*
3158 Replace BUFFER with some other buffer in all windows showing it.
3160 Optional second argument WHICH-FRAMES controls which frames are affected.
3161 If nil or omitted, all frames are affected.
3162 If t, only the selected frame is affected.
3163 If `visible', all visible frames are affected.
3164 If a frame, only that frame is affected.
3165 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3166 except that the meanings of nil and t are reversed.
3168 The optional third argument WHICH-DEVICES further clarifies on which
3169 devices to search for frames as specified by WHICH-FRAMES. This value
3170 is only meaningful if WHICH-FRAMES is not t.
3171 If nil or omitted, search only the selected console.
3172 If a device, only search that device.
3173 If a console, search all devices on that console.
3174 If a device type, search all devices of that type.
3175 If `window-system', search all devices on a window system.
3176 Any other non-nil value means search all devices.
3178 (buffer, which_frames, which_devices))
3180 /* This function can GC */
3181 Lisp_Object window_list;
3183 struct gcpro gcpro1, gcpro2;
3185 if (EQ(which_frames, Qnil))
3187 else if (EQ(which_frames, Qt))
3188 which_frames = Qnil;
3189 window_list = list_all_windows(which_frames, which_devices);
3191 buffer = Fget_buffer(buffer);
3192 CHECK_BUFFER(buffer);
3194 GCPRO2(window_list, buffer);
3195 LIST_LOOP(tail, window_list) {
3196 Lisp_Object window = XCAR(tail);
3197 if (!MINI_WINDOW_P(XWINDOW(window))
3198 && EQ(XWINDOW(window)->buffer, buffer)) {
3199 Lisp_Object another_buffer =
3200 Fother_buffer(buffer, Qnil, Qnil);
3201 Lisp_Object frame = WINDOW_FRAME(XWINDOW(window));
3202 if (NILP(another_buffer))
3203 another_buffer = Fget_buffer_create(QSscratch);
3204 if (!NILP(XWINDOW(window)->dedicated)
3205 && EQ(window, FRAME_ROOT_WINDOW(XFRAME(frame)))
3206 && (allow_deletion_of_last_visible_frame
3207 || other_visible_frames (XFRAME (frame))))
3209 delete_frame_internal(XFRAME(frame), 0, 0, 0); /* GC */
3211 Fset_window_buffer(window, another_buffer,
3213 if (EQ(window, Fselected_window(Qnil)))
3214 Fset_buffer(XWINDOW(window)->buffer);
3222 /* The smallest acceptable dimensions for a window. Anything smaller
3223 might crash Emacs. */
3224 #define MIN_SAFE_WINDOW_WIDTH (2)
3225 #define MIN_SAFE_WINDOW_HEIGHT (2)
3227 /* Make sure that window_min_height and window_min_width are
3228 not too small; if they are, set them to safe minima. */
3230 static void check_min_window_sizes(void)
3232 /* Smaller values might permit a crash. */
3233 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3234 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3235 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3236 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3239 static int frame_min_height(struct frame *frame)
3241 /* For height, we have to see whether the frame has a minibuffer, and
3242 whether it wants a modeline. */
3243 return (FRAME_MINIBUF_ONLY_P(frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3244 : (!FRAME_HAS_MINIBUF_P(frame)) ? MIN_SAFE_WINDOW_HEIGHT
3245 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3248 /* Return non-zero if both frame sizes are less than or equal to
3249 minimal allowed values. ROWS and COLS are in characters */
3250 int frame_size_valid_p(struct frame *frame, int rows, int cols)
3252 return (rows >= frame_min_height(frame)
3253 && cols >= MIN_SAFE_WINDOW_WIDTH);
3256 /* Return non-zero if both frame sizes are less than or equal to
3257 minimal allowed values. WIDTH and HEIGHT are in pixels */
3258 int frame_pixsize_valid_p(struct frame *frame, int width, int height)
3261 pixel_to_real_char_size(frame, width, height, &cols, &rows);
3262 return frame_size_valid_p(frame, rows, cols);
3265 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3266 minimum allowable size. */
3267 void check_frame_size(struct frame *frame, int *rows, int *cols)
3269 int min_height = frame_min_height(frame);
3271 if (*rows < min_height)
3273 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3274 *cols = MIN_SAFE_WINDOW_WIDTH;
3277 /* Normally the window is deleted if it gets too small.
3278 nodelete nonzero means do not do this.
3279 (The caller should check later and do so if appropriate) */
3281 set_window_pixsize(Lisp_Object window, int new_pixsize, int nodelete,
3284 struct window *w = XWINDOW(window);
3285 struct frame *f = XFRAME(w->frame);
3287 int old_pixsize = (set_height ? WINDOW_HEIGHT(w) : WINDOW_WIDTH(w));
3288 Lisp_Object child, minor_kid, major_kid;
3291 int defheight, defwidth;
3293 /* #### This is very likely incorrect and instead the char_to_pixel_
3294 functions should be called. */
3295 default_face_height_and_width(window, &defheight, &defwidth);
3296 line_size = (set_height ? defheight : defwidth);
3298 check_min_window_sizes();
3300 minsize = (set_height ? window_min_height : window_min_width);
3301 minsize *= line_size;
3303 if (!nodelete && !TOP_LEVEL_WINDOW_P(w)
3304 && new_pixsize < minsize) {
3305 Fdelete_window(window, Qnil);
3309 SET_LAST_MODIFIED(w, 0);
3310 SET_LAST_FACECHANGE(w);
3311 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f); /* multiple windows affected */
3313 WINDOW_HEIGHT(w) = new_pixsize;
3314 major_kid = w->vchild;
3315 minor_kid = w->hchild;
3317 WINDOW_WIDTH(w) = new_pixsize;
3318 major_kid = w->hchild;
3319 minor_kid = w->vchild;
3322 if (!NILP(minor_kid)) {
3323 for (child = minor_kid; !NILP(child);
3324 child = XWINDOW(child)->next) {
3326 WINDOW_TOP(XWINDOW(child)) = WINDOW_TOP(w);
3328 WINDOW_LEFT(XWINDOW(child)) = WINDOW_LEFT(w);
3330 set_window_pixsize(child, new_pixsize, nodelete,
3333 } else if (!NILP(major_kid)) {
3334 int last_pos, last_old_pos, pos, old_pos, first;
3335 int pixel_adj_left = new_pixsize - old_pixsize;
3336 int div_val = old_pixsize << 1;
3339 * Previously we bailed out here if there was no size change.
3340 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3341 * toolbar appears or disappears, windows may not change size,
3342 * but their top and left coordinates need to be updated.
3344 * So we don't bail until after the loop below.
3348 (set_height ? WINDOW_TOP(w) : WINDOW_LEFT(w));
3351 for (child = major_kid; !NILP(child); child = c->next) {
3355 old_pos = last_old_pos + WINDOW_HEIGHT(c);
3356 WINDOW_TOP(c) = last_pos;
3358 old_pos = last_old_pos + WINDOW_WIDTH(c);
3359 WINDOW_LEFT(c) = last_pos;
3363 (((old_pos * new_pixsize) << 1) +
3364 old_pixsize) / div_val;
3365 /* All but the last window should have a height which is
3366 a multiple of the default line height. */
3368 pos = (pos / line_size) * line_size;
3370 /* Avoid confusion: don't delete child if it becomes too small */
3371 set_window_pixsize(child, pos + first - last_pos, 1,
3374 last_pos = pos + first;
3375 last_old_pos = old_pos;
3378 /* Sometimes we may get called with our old size. In that case
3379 we don't need to do anything else. */
3380 if (!pixel_adj_left)
3383 /* Now delete any children that became too small. */
3385 for (child = major_kid; !NILP(child);
3386 child = XWINDOW(child)->next) {
3388 set_window_pixheight(child,
3393 set_window_pixwidth(child,
3394 WINDOW_WIDTH(XWINDOW
3401 /* Set the height of WINDOW and all its inferiors. */
3402 void set_window_pixheight(Lisp_Object window, int new_pixheight, int nodelete)
3404 set_window_pixsize(window, new_pixheight, nodelete, 1);
3407 /* Recursively set width of WINDOW and its inferiors. */
3408 void set_window_pixwidth(Lisp_Object window, int new_pixwidth, int nodelete)
3410 set_window_pixsize(window, new_pixwidth, nodelete, 0);
3413 static int window_select_count;
3415 DEFUN("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3416 Make WINDOW display BUFFER as its contents.
3417 When WINDOW is nil, the `selected-window' is used.
3418 BUFFER can be a buffer or buffer name.
3420 With non-nil optional argument NORECORD, do not modify the
3421 global or per-frame buffer ordering.
3424 (window, buffer, norecord))
3427 struct window *w = decode_window(window);
3428 int old_buffer_local_face_property = 0;
3430 buffer = Fget_buffer(buffer);
3431 CHECK_BUFFER(buffer);
3433 if (!BUFFER_LIVE_P(XBUFFER(buffer)))
3434 error("Attempt to display deleted buffer");
3438 error("Window is deleted");
3440 /* While this seems like a logical thing to do, it causes problems
3441 because of saved window configurations. It is possible for a
3442 buffer to get restored into a window in which it is already being
3443 displayed, but start and point are actually at completely
3444 different locations. So we let this function complete fully and
3445 it will then make sure redisplay correctly updates things.
3447 #### This is a kludge. The correct approach is not to do this
3448 but to fix set-window-configuration. */
3450 else if (EQ(tem, buffer))
3453 else if (!EQ(tem, Qt)) { /* w->buffer is t when the window
3454 is first being set up. */
3455 if (!NILP(w->dedicated) && !EQ(tem, buffer))
3456 error("Window is dedicated to buffer %s",
3457 XSTRING_DATA(XBUFFER(tem)->name));
3459 old_buffer_local_face_property =
3460 XBUFFER(w->buffer)->buffer_local_face_property;
3465 w->window_end_pos[CURRENT_DISP] = 0;
3467 w->modeline_hscroll = 0;
3468 Fset_marker(w->pointm[CURRENT_DISP],
3469 make_int(BUF_PT(XBUFFER(buffer))), buffer);
3470 set_marker_restricted(w->start[CURRENT_DISP],
3471 make_int(XBUFFER(buffer)->last_window_start),
3473 Fset_marker(w->sb_point, w->start[CURRENT_DISP], buffer);
3474 /* set start_at_line_beg correctly. GE */
3475 w->start_at_line_beg = beginning_of_line_p(XBUFFER(buffer),
3479 w->force_start = 0; /* Lucid fix */
3480 SET_LAST_MODIFIED(w, 1);
3481 SET_LAST_FACECHANGE(w);
3482 MARK_WINDOWS_CHANGED(w);
3484 int new_buffer_local_face_property =
3485 XBUFFER(w->buffer)->buffer_local_face_property;
3487 if (new_buffer_local_face_property
3488 || new_buffer_local_face_property !=
3489 old_buffer_local_face_property)
3490 MARK_WINDOW_FACES_CHANGED(w);
3492 recompute_all_cached_specifiers_in_window(w);
3493 if (EQ(window, Fselected_window(Qnil))) {
3495 Frecord_buffer(buffer);
3497 Fset_buffer(buffer);
3500 run_window_configuration_hook( window );
3505 DEFUN("select-window", Fselect_window, 1, 2, 0, /*
3506 Select WINDOW. Most editing will apply to WINDOW's buffer.
3507 The main editor command loop selects the buffer of the selected window
3508 before each command.
3510 With non-nil optional argument NORECORD, do not modify the
3511 global or per-frame buffer ordering.
3516 Lisp_Object old_selected_window = Fselected_window(Qnil);
3518 CHECK_LIVE_WINDOW(window);
3519 w = XWINDOW(window);
3521 /* we have already caught dead-window errors */
3522 if (!NILP(w->hchild) || !NILP(w->vchild))
3523 error("Trying to select non-leaf window");
3525 w->use_time = make_int(++window_select_count);
3527 if (EQ(window, old_selected_window))
3530 /* deselect the old window, if it exists (it might not exist if
3531 the selected device has no frames, which occurs at startup) */
3532 if (!NILP(old_selected_window)) {
3533 struct window *ow = XWINDOW(old_selected_window);
3535 Fset_marker(ow->pointm[CURRENT_DISP],
3536 make_int(BUF_PT(XBUFFER(ow->buffer))), ow->buffer);
3538 MARK_WINDOWS_CHANGED(ow);
3541 /* now select the window's frame */
3542 set_frame_selected_window(XFRAME(WINDOW_FRAME(w)), window);
3544 select_frame_1(WINDOW_FRAME(w));
3546 /* also select the window's buffer */
3548 Frecord_buffer(w->buffer);
3549 Fset_buffer(w->buffer);
3551 /* Go to the point recorded in the window.
3552 This is important when the buffer is in more
3553 than one window. It also matters when
3554 redisplay_window has altered point after scrolling,
3555 because it makes the change only in the window. */
3557 Bufpos new_point = marker_position(w->pointm[CURRENT_DISP]);
3558 if (new_point < BUF_BEGV(current_buffer))
3559 new_point = BUF_BEGV(current_buffer);
3560 else if (new_point > BUF_ZV(current_buffer))
3561 new_point = BUF_ZV(current_buffer);
3563 BUF_SET_PT(current_buffer, new_point);
3566 MARK_WINDOWS_CHANGED(w);
3572 display_buffer(Lisp_Object buffer, Lisp_Object not_this_window_p,
3573 Lisp_Object override_frame)
3575 return call3(Qdisplay_buffer, buffer, not_this_window_p,
3579 void temp_output_buffer_show(Lisp_Object buf, Lisp_Object same_frame)
3581 /* This function can GC */
3584 struct buffer *b = XBUFFER(buf);
3586 BUF_SAVE_MODIFF(XBUFFER(buf)) = BUF_MODIFF(b);
3588 BUF_SET_PT(b, BUF_BEG(b));
3590 if (!NILP(Vtemp_buffer_show_function))
3591 call1(Vtemp_buffer_show_function, buf);
3593 window = display_buffer(buf, Qnil, same_frame);
3595 if (!EQ(XWINDOW(window)->frame, Fselected_frame(Qnil)))
3596 Fmake_frame_visible(WINDOW_FRAME(XWINDOW(window)));
3598 Vminibuffer_scroll_window = window;
3599 w = XWINDOW(window);
3601 w->modeline_hscroll = 0;
3602 set_marker_restricted(w->start[CURRENT_DISP], make_int(1), buf);
3603 set_marker_restricted(w->pointm[CURRENT_DISP], make_int(1),
3605 set_marker_restricted(w->sb_point, make_int(1), buf);
3607 /* Run temp-buffer-show-hook, with the chosen window selected. */
3608 if (!preparing_for_armageddon) {
3610 tem = Fboundp(Qtemp_buffer_show_hook);
3612 tem = Fsymbol_value(Qtemp_buffer_show_hook);
3614 int count = specpdl_depth();
3616 /* Select the window that was chosen, for running
3618 record_unwind_protect
3619 (save_window_excursion_unwind,
3620 Fcurrent_window_configuration
3623 Fselect_window(window, Qnil);
3624 run_hook(Qtemp_buffer_show_hook);
3625 unbind_to(count, Qnil);
3632 static void make_dummy_parent(Lisp_Object window)
3635 struct window *o = XWINDOW(window);
3636 struct window *p = alloc_lcrecord_type(struct window, &lrecord_window);
3639 copy_lcrecord(p, o);
3641 /* Don't copy the pointers to the line start cache or the face
3643 p->line_start_cache = Dynarr_new(line_start_cache);
3644 p->face_cachels = Dynarr_new(face_cachel);
3645 p->glyph_cachels = Dynarr_new(glyph_cachel);
3646 p->subwindow_instance_cache = make_image_instance_cache_hash_table();
3648 /* Put new into window structure in place of window */
3649 replace_window(window, new);
3657 p->start[CURRENT_DISP] = Qnil;
3658 p->start[DESIRED_DISP] = Qnil;
3659 p->start[CMOTION_DISP] = Qnil;
3660 p->pointm[CURRENT_DISP] = Qnil;
3661 p->pointm[DESIRED_DISP] = Qnil;
3662 p->pointm[CMOTION_DISP] = Qnil;
3667 DEFUN("split-window", Fsplit_window, 0, 3, "", /*
3668 Split WINDOW, putting SIZE lines in the first of the pair.
3669 WINDOW defaults to the selected one and SIZE to half its size.
3670 If optional third arg HORFLAG is non-nil, split side by side and put
3671 SIZE columns in the first of the pair. The newly created window is
3675 (window, size, horflag))
3678 struct window *o, *p;
3684 window = Fselected_window(Qnil);
3686 CHECK_LIVE_WINDOW(window);
3688 o = XWINDOW(window);
3689 f = XFRAME(WINDOW_FRAME(o));
3693 /* In the new scheme, we are symmetric with respect to separators
3694 so there is no need to do weird things here. */
3697 (WINDOW_WIDTH(o) + window_divider_width(o)) >> 1;
3698 csize = window_pixel_width_to_char_width(o, psize, 0);
3700 psize = WINDOW_HEIGHT(o) >> 1;
3701 csize = window_pixel_height_to_char_height(o, psize, 1);
3707 psize = window_char_width_to_pixel_width(o, csize, 0);
3709 psize = window_char_height_to_pixel_height(o, csize, 1);
3712 if (MINI_WINDOW_P(o))
3713 error("Attempt to split minibuffer window");
3714 else if (FRAME_NO_SPLIT_P(XFRAME(WINDOW_FRAME(o))))
3715 error("Attempt to split unsplittable frame");
3717 check_min_window_sizes();
3719 if (NILP(horflag)) {
3720 if (csize < window_min_height)
3721 error("Window height %d too small (after splitting)",
3723 if (csize + window_min_height > window_char_height(o, 1))
3724 error("Window height %d too small (after splitting)",
3725 window_char_height(o, 1) - csize);
3727 || NILP(XWINDOW(o->parent)->vchild)) {
3728 make_dummy_parent(window);
3730 /* #### I can't understand why you have to reset face
3731 cachels here. This can cause crash so let's disable it
3732 and see the difference. See redisplay-tests.el --yh */
3733 reset_face_cachels(XWINDOW(window));
3736 XWINDOW(new)->vchild = window;
3737 XFRAME(o->frame)->mirror_dirty = 1;
3740 if (csize < window_min_width)
3741 error("Window width %d too small (after splitting)",
3743 if (csize + window_min_width > window_char_width(o, 0))
3744 error("Window width %d too small (after splitting)",
3745 window_char_width(o, 0) - csize);
3747 || NILP(XWINDOW(o->parent)->hchild)) {
3748 make_dummy_parent(window);
3750 /* #### See above. */
3751 reset_face_cachels(XWINDOW(window));
3754 XWINDOW(new)->hchild = window;
3755 XFRAME(o->frame)->mirror_dirty = 1;
3759 /* Now we know that window's parent is a vertical combination
3760 if we are dividing vertically, or a horizontal combination
3761 if we are making side-by-side windows */
3763 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
3764 new = allocate_window();
3767 p->frame = o->frame;
3770 XWINDOW(p->next)->prev = new;
3773 p->parent = o->parent;
3776 reset_face_cachels(p);
3777 reset_glyph_cachels(p);
3779 /* Apportion the available frame space among the two new windows */
3781 if (!NILP(horflag)) {
3782 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
3783 WINDOW_TOP(p) = WINDOW_TOP(o);
3784 WINDOW_WIDTH(p) = WINDOW_WIDTH(o) - psize;
3785 WINDOW_WIDTH(o) = psize;
3786 WINDOW_LEFT(p) = WINDOW_LEFT(o) + psize;
3788 WINDOW_LEFT(p) = WINDOW_LEFT(o);
3789 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
3790 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o) - psize;
3791 WINDOW_HEIGHT(o) = psize;
3792 WINDOW_TOP(p) = WINDOW_TOP(o) + psize;
3795 XFRAME(p->frame)->mirror_dirty = 1;
3796 /* do this last (after the window is completely initialized and
3797 the mirror-dirty flag is set) so that specifier recomputation
3798 caused as a result of this will work properly and not abort. */
3799 Fset_window_buffer(new, o->buffer, Qt);
3801 /* window-configuration-hook is called indirectly, in
3802 set-window-buffer. */
3807 DEFUN("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3808 Make the selected window COUNT lines taller.
3809 From program, optional second arg HORIZONTALP non-nil means grow
3810 sideways COUNT columns, and optional third arg WINDOW specifies the
3811 window to change instead of the selected window.
3814 (count, horizontalp, window))
3817 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3822 DEFUN("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3823 Make the selected window COUNT pixels taller.
3824 From program, optional second arg HORIZONTALP non-nil means grow
3825 sideways COUNT pixels, and optional third arg WINDOW specifies the
3826 window to change instead of the selected window.
3829 (count, horizontalp, window))
3832 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3837 DEFUN("shrink-window", Fshrink_window, 1, 3, "_p", /*
3838 Make the selected window COUNT lines shorter.
3839 From program, optional second arg HORIZONTALP non-nil means shrink
3840 sideways COUNT columns, and optional third arg WINDOW specifies the
3841 window to change instead of the selected window.
3844 (count, horizontalp, window))
3847 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3852 DEFUN("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3853 Make the selected window COUNT pixels smaller.
3854 From program, optional second arg HORIZONTALP non-nil means shrink
3855 sideways COUNT pixels, and optional third arg WINDOW specifies the
3856 window to change instead of the selected window.
3859 (count, horizontalp, window))
3862 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3868 window_pixel_height_to_char_height(struct window *w, int pixel_height,
3869 int include_gutters_p)
3872 int defheight, defwidth;
3876 XSETWINDOW(window, w);
3878 avail_height = (pixel_height -
3879 (include_gutters_p ? 0 :
3880 window_top_window_gutter_height(w) +
3881 window_bottom_window_gutter_height(w)));
3883 default_face_height_and_width(window, &defheight, &defwidth);
3885 char_height = avail_height / defheight;
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, char_height);
3896 window_char_height_to_pixel_height(struct window *w, int char_height,
3897 int include_gutters_p)
3900 int defheight, defwidth;
3905 XSETWINDOW(window, w);
3907 default_face_height_and_width(window, &defheight, &defwidth);
3909 avail_height = char_height * defheight;
3910 pixel_height = (avail_height +
3911 (include_gutters_p ? 0 :
3912 window_top_window_gutter_height(w) +
3913 window_bottom_window_gutter_height(w)));
3915 /* It's the calling function's responsibility to check these values
3916 and make sure they're not out of range.
3918 #### We need to go through the calling functions and actually
3920 return max(0, pixel_height);
3923 /* Return number of default lines of text can fit in the window W.
3924 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3925 horizontal scrollbar) in the space that is used for the calculation.
3926 This doesn't include space used by the frame gutters.
3928 int window_char_height(struct window *w, int include_gutters_p)
3930 return window_pixel_height_to_char_height(w, window_pixel_height(w),
3935 * Return number of lines currently displayed in window w. If
3936 * end-of-buffer is displayed then the area below end-of-buffer is assume
3937 * to be blank lines of default height.
3938 * Does not include the modeline.
3940 int window_displayed_height(struct window *w)
3942 struct buffer *b = XBUFFER(w->buffer);
3943 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
3946 (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV(b)
3947 ? -1 : w->window_end_pos[CURRENT_DISP]);
3949 if (!Dynarr_length(dla))
3950 return window_char_height(w, 0);
3952 num_lines = Dynarr_length(dla);
3954 /* #### Document and assert somewhere that w->window_end_pos == -1
3955 indicates that end-of-buffer is being displayed. */
3956 if (end_pos == -1) {
3957 struct display_line *dl = Dynarr_atp(dla, 0);
3958 int ypos1 = dl->ypos + dl->descent;
3959 int ypos2 = WINDOW_TEXT_BOTTOM(w);
3961 int defheight, defwidth;
3963 XSETWINDOW(window, w);
3968 if (Dynarr_length(dla) == 1)
3969 ypos1 = WINDOW_TEXT_TOP(w);
3971 dl = Dynarr_atp(dla, Dynarr_length(dla) - 1);
3972 /* If this line is clipped then we know that there is no
3973 blank room between eob and the modeline. If we are
3974 scrolling on clipped lines just know off the clipped
3975 line and return . */
3976 if (scroll_on_clipped_lines && dl->clip)
3977 return num_lines - 1;
3978 ypos1 = dl->ypos + dl->descent - dl->clip;
3982 default_face_height_and_width(window, &defheight, &defwidth);
3983 /* #### This probably needs to know about the clipping area once a
3984 final definition is decided on. */
3985 num_lines += ((ypos2 - ypos1) / defheight);
3987 if (num_lines > 1 && Dynarr_atp(dla, 0)->modeline)
3990 if (scroll_on_clipped_lines
3991 && Dynarr_atp(dla, Dynarr_length(dla) - 1)->clip)
3998 static int window_pixel_width(Lisp_Object window)
4000 return WINDOW_WIDTH(XWINDOW(window));
4003 /* Calculate the pixel of a window, optionally including margin space
4004 but no vertical gutters. */
4006 window_pixel_width_to_char_width(struct window *w, int pixel_width,
4007 int include_margins_p)
4011 int defheight, defwidth;
4014 XSETWINDOW(window, w);
4016 avail_width = (pixel_width -
4017 window_left_gutter_width(w, 0) -
4018 window_right_gutter_width(w, 0) -
4019 (include_margins_p ? 0 : window_left_margin_width(w)) -
4020 (include_margins_p ? 0 : window_right_margin_width(w)));
4022 default_face_height_and_width(window, &defheight, &defwidth);
4024 char_width = (avail_width / defwidth);
4026 /* It's the calling function's responsibility to check these values
4027 and make sure they're not out of range.
4029 #### We need to go through the calling functions and actually
4031 return max(0, char_width);
4035 window_char_width_to_pixel_width(struct window *w, int char_width,
4036 int include_margins_p)
4040 int defheight, defwidth;
4043 XSETWINDOW(window, w);
4045 default_face_height_and_width(window, &defheight, &defwidth);
4047 avail_width = char_width * defwidth;
4048 pixel_width = (avail_width +
4049 window_left_window_gutter_width(w, 0) +
4050 window_right_window_gutter_width(w, 0) +
4051 (include_margins_p ? 0 : window_left_margin_width(w)) +
4052 (include_margins_p ? 0 : window_right_margin_width(w)));
4054 /* It's the calling function's responsibility to check these values
4055 and make sure they're not out of range.
4057 #### We need to go through the calling functions and actually
4059 return max(0, pixel_width);
4062 /* This returns the usable space which doesn't include space needed by
4063 scrollbars or divider lines. */
4064 int window_char_width(struct window *w, int include_margins_p)
4066 return window_pixel_width_to_char_width(w, WINDOW_WIDTH(w),
4070 #define MINSIZE(w) \
4072 ? window_min_width * defwidth \
4073 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4076 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4078 #define CURSIZE(w) \
4079 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4081 #define CURCHARSIZE(w) \
4082 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4084 #define MINCHARSIZE(window) \
4085 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4086 ? 1 : window_min_height)
4088 static int window_pixheight(Lisp_Object w)
4090 return window_pixel_height(XWINDOW(w));
4093 /* Unlike set_window_pixheight, this function
4094 also changes the heights of the siblings so as to
4095 keep everything consistent. */
4098 change_window_height(Lisp_Object window, int delta, Lisp_Object horizontalp,
4101 struct window *win = decode_window(window);
4102 int widthflag = !NILP(horizontalp);
4107 int (*sizefun) (Lisp_Object) = (widthflag
4108 ? window_pixel_width
4109 : window_pixheight);
4110 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4111 ? set_window_pixwidth
4112 : set_window_pixheight);
4114 int defheight, defwidth;
4119 check_min_window_sizes();
4121 XSETWINDOW(window, win);
4122 f = XFRAME(win->frame);
4123 if (EQ(window, FRAME_ROOT_WINDOW(f)))
4124 error("Won't change only window");
4126 /* #### This is very likely incorrect and instead the char_to_pixel_
4127 functions should be called. */
4128 default_face_height_and_width(window, &defheight, &defwidth);
4131 w = XWINDOW(window);
4136 sizep = &CURSIZE (w);
4137 dim = CURCHARSIZE (w);
4138 new_pixsize = inpixels?(*sizep + delta):(dim+delta);
4139 set_window_pixsize (window, new_pixsize, 0, 0);
4144 if (widthflag ? !NILP(XWINDOW(parent)->hchild)
4145 : !NILP(XWINDOW(parent)->vchild))
4150 sizep = &CURSIZE(w);
4151 dim = CURCHARSIZE(w);
4153 if ((inpixels && (*sizep + delta) < MINSIZE(window)) ||
4154 (!inpixels && (dim + delta) < MINCHARSIZE(window))) {
4155 if (MINI_WINDOW_P(XWINDOW(window)))
4157 else if (!NILP(parent)) {
4158 Fdelete_window(window, Qnil);
4164 delta *= (widthflag ? defwidth : defheight);
4169 maxdelta = ((!NILP(parent))
4170 ? (*sizefun) (parent) - *sizep : ((!NILP(w->next))
4180 /* This is a frame with only one window,
4181 a minibuffer-only or a minibufferless frame. */
4185 if (delta > maxdelta)
4186 /* This case traps trying to make the minibuffer
4187 the full frame, or make the only window aside from the
4188 minibuffer the full frame. */
4195 /* #### Chuck: is this correct? */
4196 if (*sizep + delta < MINSIZE(window)) {
4197 Fdelete_window(window);
4203 if (!NILP(w->next) &&
4204 (*sizefun) (w->next) - delta >= (int)MINSIZE(w->next)) {
4205 CURBEG(XWINDOW(w->next)) += delta;
4206 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4207 (*setsizefun) (window, *sizep + delta, 0);
4208 } else if (!NILP(w->prev) &&
4209 (*sizefun) (w->prev) - delta >= (int)MINSIZE(w->prev)) {
4210 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4212 (*setsizefun) (window, *sizep + delta, 0);
4215 int opht = (*sizefun) (parent);
4217 /* If trying to grow this window to or beyond size of the parent,
4218 make delta1 so big that, on shrinking back down,
4219 all the siblings end up with less than one line and are deleted. */
4220 if (opht <= *sizep + delta)
4221 delta1 = opht * opht * 2;
4222 /* Otherwise, make delta1 just right so that if we add delta1
4223 lines to this window and to the parent, and then shrink
4224 the parent back to its original size, the new proportional
4225 size of this window will increase by delta. */
4228 (delta * opht * 100) / ((opht - *sizep - delta) *
4231 /* Add delta1 lines or columns to this window, and to the parent,
4232 keeping things consistent while not affecting siblings. */
4233 CURSIZE(XWINDOW(parent)) = opht + delta1;
4234 (*setsizefun) (window, *sizep + delta1, 0);
4236 /* Squeeze out delta1 lines or columns from our parent,
4237 shrinking this window and siblings proportionately.
4238 This brings parent back to correct size.
4239 Delta1 was calculated so this makes this window the desired size,
4240 taking it all out of the siblings. */
4241 (*setsizefun) (parent, opht, 0);
4244 SET_LAST_MODIFIED(w, 0);
4245 SET_LAST_FACECHANGE(w);
4246 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
4247 /* overkill maybe, but better to be correct */
4248 MARK_FRAME_GUTTERS_CHANGED(f);
4250 run_window_configuration_hook( window );
4259 /* Scroll contents of window WINDOW up COUNT lines.
4260 If COUNT < (top line height / average line height) then we just adjust
4263 window_scroll(Lisp_Object window, Lisp_Object count, int direction,
4264 Error_behavior errb)
4266 struct window *w = XWINDOW(window);
4267 struct buffer *b = XBUFFER(w->buffer);
4268 int selected = EQ(window, Fselected_window(Qnil));
4270 Lisp_Object point, tem;
4271 display_line_dynarr *dla;
4272 int fheight, fwidth, modeline = 0;
4273 struct display_line *dl;
4276 point = make_int(BUF_PT(b));
4278 Bufpos pos = marker_position(w->pointm[CURRENT_DISP]);
4280 if (pos < BUF_BEGV(b))
4282 else if (pos > BUF_ZV(b))
4285 point = make_int(pos);
4288 /* Always set force_start so that redisplay_window will run
4289 the window-scroll-functions. */
4292 /* #### When the fuck does this happen? I'm so glad that history has
4293 completely documented the behavior of the scrolling functions under
4294 all circumstances. */
4295 tem = Fpos_visible_in_window_p(point, window);
4297 Fvertical_motion(make_int(-window_char_height(w, 0) / 2),
4299 Fset_marker(w->start[CURRENT_DISP], point, w->buffer);
4300 w->start_at_line_beg = beginning_of_line_p(b, XINT(point));
4301 WINDOW_TEXT_TOP_CLIP(w) = 0;
4302 MARK_WINDOWS_CHANGED(w);
4306 if (EQ(count, Qminus))
4309 count = Fprefix_numeric_value(count);
4310 value = XINT(count) * direction;
4313 return; /* someone just made a pointless call */
4317 /* If the user didn't specify how far to scroll then we have to figure it
4318 out by ourselves. */
4319 if (NILP(count) || EQ(count, Qminus)) {
4320 /* Going forwards is easy. If that is what we are doing then just
4321 set value and the section which handles the user specifying a
4322 positive value will work. */
4323 if (direction == 1) {
4325 window_displayed_height(w) -
4326 next_screen_context_lines;
4327 value = (value < 1 ? 1 : value);
4330 /* Going backwards is hard. We can't use the same loop used if the
4331 user specified a negative value because we care about
4332 next_screen_context_lines. In a variable height world you don't
4333 know how many lines above you can actually be displayed and still
4334 have the context lines appear. So we leave value set to 0 and add
4335 a separate section to deal with this. */
4339 if (direction == 1 && !value) {
4343 /* Determine parameters to test for partial line scrolling with. */
4344 dla = window_display_lines(w, CURRENT_DISP);
4346 if (INTP(Vwindow_pixel_scroll_increment))
4347 fheight = XINT(Vwindow_pixel_scroll_increment);
4348 else if (!NILP(Vwindow_pixel_scroll_increment))
4349 default_face_height_and_width(window, &fheight, &fwidth);
4351 if (Dynarr_length(dla) >= 1)
4352 modeline = Dynarr_atp(dla, 0)->modeline;
4354 dl = Dynarr_atp(dla, modeline);
4357 /* Go for partial display line scrolling. This just means bumping
4358 the clip by a reasonable amount and redisplaying, everything else
4359 remains unchanged. */
4360 if (!NILP(Vwindow_pixel_scroll_increment)
4361 && Dynarr_length(dla) >= (1 + modeline)
4362 && (dl->ascent - dl->top_clip) > fheight * value) {
4363 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4364 MARK_WINDOWS_CHANGED(w);
4367 Bufpos startp, old_start;
4369 if (WINDOW_TEXT_TOP_CLIP(w)) {
4370 WINDOW_TEXT_TOP_CLIP(w) = 0;
4371 MARK_WINDOWS_CHANGED(w);
4374 old_start = marker_position(w->start[CURRENT_DISP]);
4375 startp = vmotion(w, old_start, value, &vtarget);
4377 if (vtarget < value &&
4378 (w->window_end_pos[CURRENT_DISP] == -1
4379 || (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] >
4381 maybe_signal_error(Qend_of_buffer, Qnil,
4385 set_marker_restricted(w->start[CURRENT_DISP],
4389 w->start_at_line_beg =
4390 beginning_of_line_p(b, startp);
4391 MARK_WINDOWS_CHANGED(w);
4393 if (!point_would_be_visible
4394 (w, startp, XINT(point))) {
4396 BUF_SET_PT(b, startp);
4398 set_marker_restricted(w->
4408 } else if (value < 0) {
4409 /* Go for partial display line scrolling. This just means bumping
4410 the clip by a reasonable amount and redisplaying, everything else
4411 remains unchanged. */
4412 if (!NILP(Vwindow_pixel_scroll_increment)
4413 && Dynarr_length(dla) >= (1 + modeline)
4415 (dl->ascent - dl->top_clip) - fheight * value <
4416 (dl->ascent + dl->descent - dl->clip)
4417 && WINDOW_TEXT_TOP_CLIP(w) + value * fheight > 0) {
4418 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4419 MARK_WINDOWS_CHANGED(w);
4422 Bufpos startp, old_start;
4424 if (WINDOW_TEXT_TOP_CLIP(w)) {
4425 WINDOW_TEXT_TOP_CLIP(w) = 0;
4426 MARK_WINDOWS_CHANGED(w);
4429 old_start = marker_position(w->start[CURRENT_DISP]);
4430 startp = vmotion(w, old_start, value, &vtarget);
4433 && marker_position(w->start[CURRENT_DISP]) ==
4435 maybe_signal_error(Qbeginning_of_buffer, Qnil,
4439 set_marker_restricted(w->start[CURRENT_DISP],
4443 w->start_at_line_beg =
4444 beginning_of_line_p(b, startp);
4445 MARK_WINDOWS_CHANGED(w);
4447 /* #### Scroll back by less than a line. This code was
4448 originally for scrolling over large pixmaps and it
4449 loses when a line being *exposed* at the top of the
4450 window is bigger than the current one. However, for
4451 pixel based scrolling in general we can guess that
4452 the line we are going to display is probably the same
4453 size as the one we are on. In that instance we can
4454 have a reasonable stab at a suitable top clip. Fixing
4455 this properly is hard (and probably slow) as we would
4456 have to call redisplay to figure out the exposed line
4458 if (!NILP(Vwindow_pixel_scroll_increment)
4459 && Dynarr_length(dla) >= (1 + modeline)
4460 && dl->ascent + fheight * value > 0) {
4461 WINDOW_TEXT_TOP_CLIP(w) =
4462 (dl->ascent + fheight * value);
4465 if (!point_would_be_visible
4466 (w, startp, XINT(point))) {
4469 if (MINI_WINDOW_P(w))
4473 start_of_last_line(w,
4477 BUF_SET_PT(b, new_point);
4479 set_marker_restricted(w->
4489 } else { /* value == 0 && direction == -1 */
4491 if (WINDOW_TEXT_TOP_CLIP(w)) {
4492 WINDOW_TEXT_TOP_CLIP(w) = 0;
4493 MARK_WINDOWS_CHANGED(w);
4495 if (marker_position(w->start[CURRENT_DISP]) == BUF_BEGV(b)) {
4496 maybe_signal_error(Qbeginning_of_buffer, Qnil, Qwindow,
4501 int movement = next_screen_context_lines - 1;
4503 marker_position(w->start[CURRENT_DISP]);
4505 vmotion(w, old_startp, movement, &vtarget);
4507 start_with_point_on_display_line(w, bottom,
4511 if (startp >= old_startp)
4512 startp = vmotion(w, old_startp, -1, NULL);
4514 set_marker_restricted(w->start[CURRENT_DISP],
4515 make_int(startp), w->buffer);
4517 w->start_at_line_beg = beginning_of_line_p(b, startp);
4518 MARK_WINDOWS_CHANGED(w);
4520 if (!point_would_be_visible(w, startp, XINT(point))) {
4522 start_of_last_line(w, startp);
4525 BUF_SET_PT(b, new_point);
4527 set_marker_restricted(w->
4538 DEFUN("scroll-up", Fscroll_up, 0, 1, "_P", /*
4539 Scroll text of current window up COUNT lines; or near full screen if no arg.
4540 A near full screen is `next-screen-context-lines' less than a full screen.
4541 Negative COUNT means scroll downward.
4542 When calling from a program, supply an integer as argument or nil.
4543 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4544 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4547 The characters that are moved over may be added to the current selection
4548 \(i.e. active region) if the Shift key is held down, a motion key is used
4549 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4550 the documentation for this variable for more details.
4554 window_scroll(Fselected_window(Qnil), count, 1, ERROR_ME);
4558 DEFUN("scroll-down", Fscroll_down, 0, 1, "_P", /*
4559 Scroll text of current window down COUNT lines; or near full screen if no arg.
4560 A near full screen is `next-screen-context-lines' less than a full screen.
4561 Negative COUNT means scroll upward.
4562 When calling from a program, supply a number as argument or nil.
4563 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4564 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4567 The characters that are moved over may be added to the current selection
4568 \(i.e. active region) if the Shift key is held down, a motion key is used
4569 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4570 the documentation for this variable for more details.
4574 window_scroll(Fselected_window(Qnil), count, -1, ERROR_ME);
4578 DEFUN("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4579 Return the other window for "other window scroll" commands.
4580 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4581 specifies the window.
4582 If `other-window-scroll-buffer' is non-nil, a window
4583 showing that buffer is used.
4588 Lisp_Object selected_window = Fselected_window(Qnil);
4590 if (MINI_WINDOW_P(XWINDOW(selected_window))
4591 && !NILP(Vminibuffer_scroll_window))
4592 window = Vminibuffer_scroll_window;
4593 /* If buffer is specified, scroll that buffer. */
4594 else if (!NILP(Vother_window_scroll_buffer)) {
4596 Fget_buffer_window(Vother_window_scroll_buffer, Qnil, Qnil);
4599 display_buffer(Vother_window_scroll_buffer, Qt,
4602 /* Nothing specified; look for a neighboring window on the same
4604 window = Fnext_window(selected_window, Qnil, Qnil, Qnil);
4606 if (EQ(window, selected_window))
4607 /* That didn't get us anywhere; look for a window on another
4610 window = Fnext_window(window, Qnil, Qt, Qnil);
4611 while (!FRAME_VISIBLE_P
4612 (XFRAME(WINDOW_FRAME(XWINDOW(window))))
4613 && !EQ(window, selected_window));
4616 CHECK_LIVE_WINDOW(window);
4618 if (EQ(window, selected_window))
4619 error("There is no other window");
4624 DEFUN("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4625 Scroll next window upward COUNT lines; or near full frame if no arg.
4626 The next window is the one below the current one; or the one at the top
4627 if the current one is at the bottom. Negative COUNT means scroll downward.
4628 When calling from a program, supply a number as argument or nil.
4630 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4631 specifies the window to scroll.
4632 If `other-window-scroll-buffer' is non-nil, scroll the window
4633 showing that buffer, popping the buffer up if necessary.
4637 window_scroll(Fother_window_for_scrolling(), count, 1, ERROR_ME);
4641 DEFUN("scroll-left", Fscroll_left, 0, 1, "_P", /*
4642 Scroll selected window display COUNT columns left.
4643 Default for COUNT is window width minus 2.
4645 The characters that are moved over may be added to the current selection
4646 \(i.e. active region) if the Shift key is held down, a motion key is used
4647 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4648 the documentation for this variable for more details.
4652 Lisp_Object window = Fselected_window(Qnil);
4653 struct window *w = XWINDOW(window);
4654 int n = (NILP(count) ?
4655 window_char_width(w, 0) - 2 :
4656 XINT(Fprefix_numeric_value(count)));
4658 return Fset_window_hscroll(window, make_int(w->hscroll + n));
4661 DEFUN("scroll-right", Fscroll_right, 0, 1, "_P", /*
4662 Scroll selected window display COUNT columns right.
4663 Default for COUNT is window width minus 2.
4665 The characters that are moved over may be added to the current selection
4666 \(i.e. active region) if the Shift key is held down, a motion key is used
4667 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4668 the documentation for this variable for more details.
4672 Lisp_Object window = Fselected_window(Qnil);
4673 struct window *w = XWINDOW(window);
4674 int n = (NILP(count) ?
4675 window_char_width(w, 0) - 2 :
4676 XINT(Fprefix_numeric_value(count)));
4678 return Fset_window_hscroll(window, make_int(w->hscroll - n));
4681 DEFUN("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4682 Center point in WINDOW. With N, put point on line N.
4683 The desired position of point is always relative to the window.
4684 If WINDOW is nil, the selected window is used.
4688 struct window *w = decode_window(window);
4689 struct buffer *b = XBUFFER(w->buffer);
4690 Bufpos opoint = BUF_PT(b);
4695 start_with_line_at_pixpos(w, opoint, window_half_pixpos(w));
4697 n = Fprefix_numeric_value(n);
4699 startp = start_with_point_on_display_line(w, opoint, XINT(n));
4702 Fset_marker(w->start[CURRENT_DISP], make_int(startp), w->buffer);
4704 w->start_at_line_beg = beginning_of_line_p(b, startp);
4706 MARK_WINDOWS_CHANGED(w);
4710 DEFUN("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4711 Position point relative to WINDOW.
4712 With no argument, position text at center of window.
4713 An argument specifies window line; zero means top of window,
4714 negative means relative to bottom of window.
4715 If WINDOW is nil, the selected window is used.
4722 Bufpos start, new_point;
4725 /* Don't use decode_window() because we need the new value of
4728 window = Fselected_window(Qnil);
4730 CHECK_LIVE_WINDOW(window);
4731 w = XWINDOW(window);
4732 b = XBUFFER(w->buffer);
4734 height = window_displayed_height(w);
4735 selected = EQ(window, Fselected_window(w->frame));
4740 if (XINT(w->last_modified[CURRENT_DISP]) >= BUF_MODIFF(b)
4741 && XINT(w->last_facechange[CURRENT_DISP]) >=
4742 BUF_FACECHANGE(b)) {
4743 new_point = point_at_center(w, CURRENT_DISP, 0, 0);
4746 BUF_SET_PT(b, new_point);
4748 Fset_window_point(window, make_int(new_point));
4750 retval = line_at_center(w, CURRENT_DISP, 0, 0);
4752 start = marker_position(w->start[CURRENT_DISP]);
4753 if (start < BUF_BEGV(b))
4754 start = BUF_BEGV(b);
4755 else if (start > BUF_ZV(b))
4759 new_point = BUF_PT(b);
4762 marker_position(w->pointm[CURRENT_DISP]);
4765 point_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4768 BUF_SET_PT(b, new_point);
4770 Fset_window_point(window, make_int(new_point));
4773 line_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4776 return make_int(retval);
4778 /* #### Is this going to work right when at eob? */
4779 arg = Fprefix_numeric_value(arg);
4781 XSETINT(arg, XINT(arg) + height);
4784 start = marker_position(w->start[CURRENT_DISP]);
4785 if (start < BUF_BEGV(b) || start > BUF_ZV(b)) {
4787 new_point = BUF_PT(b);
4789 new_point = marker_position(w->pointm[CURRENT_DISP]);
4791 new_point = vmotion(XWINDOW(window), new_point, -height / 2, 0);
4794 BUF_SET_PT(b, new_point);
4796 Fset_window_point(window, make_int(new_point));
4798 Fset_marker(w->start[CURRENT_DISP], make_int(new_point),
4800 w->start_at_line_beg = beginning_of_line_p(b, new_point);
4804 BUF_SET_PT(b, start);
4806 Fset_window_point(window, make_int(start));
4810 return Fvertical_motion(arg, window, Qnil);
4813 new_point = vmotion(XWINDOW(window),
4814 marker_position(w->pointm[CURRENT_DISP]),
4816 Fset_window_point(window, make_int(new_point));
4817 return make_int(vpos);
4822 map_windows_1(Lisp_Object window,
4823 int (*mapfun) (struct window * w, void *closure), void *closure)
4825 for (; !NILP(window); window = XWINDOW(window)->next) {
4827 struct window *w = XWINDOW(window);
4829 if (!NILP(w->vchild))
4830 retval = map_windows_1(w->vchild, mapfun, closure);
4831 else if (!NILP(w->hchild))
4832 retval = map_windows_1(w->hchild, mapfun, closure);
4834 retval = (mapfun) (w, closure);
4843 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4844 invocation of MAPFUN. If any invocation of MAPFUN returns
4845 non-zero, the mapping is halted. Otherwise, map_windows() maps
4846 over all windows in F.
4848 If MAPFUN creates or deletes windows, the behavior is undefined. */
4851 map_windows(struct frame *f, int (*mapfun) (struct window * w, void *closure),
4855 return map_windows_1(FRAME_ROOT_WINDOW(f), mapfun, closure);
4857 Lisp_Object frmcons, devcons, concons;
4859 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
4861 map_windows_1(FRAME_ROOT_WINDOW
4862 (XFRAME(XCAR(frmcons))),
4873 modeline_shadow_thickness_changed(Lisp_Object specifier, struct window *w,
4876 w->shadow_thickness_changed = 1;
4877 MARK_WINDOWS_CHANGED(w);
4881 vertical_divider_changed_in_window(Lisp_Object specifier,
4882 struct window *w, Lisp_Object oldval)
4884 MARK_WINDOWS_CHANGED(w);
4885 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(XFRAME(WINDOW_FRAME(w)));
4888 /* also used in scrollbar.c */
4890 some_window_value_changed(Lisp_Object specifier, struct window *w,
4893 MARK_WINDOWS_CHANGED(w);
4896 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
4898 struct window_stats {
4901 #ifdef HAVE_SCROLLBARS
4905 int other_redisplay;
4910 compute_window_mirror_usage(struct window_mirror *mir,
4911 struct window_stats *stats,
4912 struct overhead_stats *ovstats)
4916 stats->other += malloced_storage_size(mir, sizeof(struct window_mirror),
4918 #ifdef HAVE_SCROLLBARS
4920 struct device *d = XDEVICE(FRAME_DEVICE(mir->frame));
4923 compute_scrollbar_instance_usage(d,
4925 scrollbar_vertical_instance,
4928 compute_scrollbar_instance_usage(d,
4930 scrollbar_horizontal_instance,
4933 #endif /* HAVE_SCROLLBARS */
4934 stats->other_redisplay +=
4935 compute_display_line_dynarr_usage(mir->current_display_lines,
4937 stats->other_redisplay +=
4938 compute_display_line_dynarr_usage(mir->desired_display_lines,
4943 compute_window_usage(struct window *w, struct window_stats *stats,
4944 struct overhead_stats *ovstats)
4948 malloced_storage_size(w, sizeof(struct window), ovstats);
4949 stats->face += compute_face_cachel_usage(w->face_cachels, ovstats);
4950 stats->glyph += compute_glyph_cachel_usage(w->glyph_cachels, ovstats);
4951 stats->line_start +=
4952 compute_line_start_cache_dynarr_usage(w->line_start_cache, ovstats);
4953 compute_window_mirror_usage(find_window_mirror(w), stats, ovstats);
4956 DEFUN("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4957 Return stats about the memory usage of window WINDOW.
4958 The values returned are in the form of an alist of usage types and byte
4959 counts. The byte counts attempt to encompass all the memory used
4960 by the window (separate from the memory logically associated with a
4961 buffer or frame), including internal structures and any malloc()
4962 overhead associated with them. In practice, the byte counts are
4963 underestimated because certain memory usage is very hard to determine
4964 \(e.g. the amount of memory used inside the Xt library or inside the
4965 X server) and because there is other stuff that might logically
4966 be associated with a window, buffer, or frame (e.g. window configurations,
4967 glyphs) but should not obviously be included in the usage counts.
4969 Multiple slices of the total memory usage may be returned, separated
4970 by a nil. Each slice represents a particular view of the memory, a
4971 particular way of partitioning it into groups. Within a slice, there
4972 is no overlap between the groups of memory, and each slice collectively
4973 represents all the memory concerned.
4977 struct window_stats stats;
4978 struct overhead_stats ovstats;
4979 Lisp_Object val = Qnil;
4981 CHECK_WINDOW(window); /* dead windows should be allowed, no? */
4983 compute_window_usage(XWINDOW(window), &stats, &ovstats);
4985 val = acons(Qface_cache, make_int(stats.face), val);
4986 val = acons(Qglyph_cache, make_int(stats.glyph), val);
4987 #ifdef HAVE_SCROLLBARS
4988 val = acons(Qscrollbar_instances, make_int(stats.scrollbar), val);
4990 val = acons(Qline_start_cache, make_int(stats.line_start), val);
4991 val = acons(Qother_redisplay, make_int(stats.other_redisplay), val);
4992 val = acons(Qother, make_int(stats.other), val);
4993 val = Fcons(Qnil, val);
4994 val = acons(Qactually_requested, make_int(ovstats.was_requested), val);
4995 val = acons(Qmalloc_overhead, make_int(ovstats.malloc_overhead), val);
4996 val = acons(Qdynarr_overhead, make_int(ovstats.dynarr_overhead), val);
4998 return Fnreverse(val);
5001 #endif /* MEMORY_USAGE_STATS */
5003 /************************************************************************/
5004 /* Window configurations */
5005 /************************************************************************/
5007 /* #### This window configuration stuff has had serious bugs lurking in it
5008 for years; it would be a -huge- win if this was reimplemented in lisp.
5011 /* If you add anything to this structure make sure saved_window_equal
5013 struct saved_window {
5014 Lisp_Object window; /* window */
5015 Lisp_Object buffer; /* buffer */
5016 Lisp_Object start; /* copied marker */
5017 Lisp_Object pointm; /* copied marker */
5018 Lisp_Object sb_point; /* copied marker */
5019 Lisp_Object mark; /* copied marker */
5025 Charcount modeline_hscroll;
5026 int parent_index; /* index into saved_windows */
5027 int prev_index; /* index into saved_windows */
5028 char start_at_line_beg; /* boolean */
5030 #define WINDOW_SLOT_DECLARATION
5031 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5032 #include "winslots.h"
5035 /* If you add anything to this structure make sure window_config_equal
5037 struct window_config {
5038 struct lcrecord_header header;
5039 /* int frame_width; No longer needed, JV
5040 int frame_height; */
5042 Lisp_Object selected_frame;
5044 Lisp_Object current_window;
5045 Lisp_Object current_buffer;
5046 Lisp_Object minibuffer_scroll_window;
5047 Lisp_Object root_window;
5048 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5049 /* Record the values of window-min-width and window-min-height
5050 so that window sizes remain consistent with them. */
5051 int min_width, min_height;
5052 unsigned int saved_windows_count;
5053 /* Zero-sized arrays aren't ANSI C */
5054 struct saved_window saved_windows[1];
5057 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5058 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5059 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5060 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5061 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5063 static Lisp_Object mark_window_config(Lisp_Object obj)
5065 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5067 mark_object(config->current_window);
5068 mark_object(config->current_buffer);
5069 mark_object(config->minibuffer_scroll_window);
5070 mark_object(config->root_window);
5072 for (i = 0; i < config->saved_windows_count; i++) {
5073 struct saved_window *s = SAVED_WINDOW_N(config, i);
5074 mark_object(s->window);
5075 mark_object(s->buffer);
5076 mark_object(s->start);
5077 mark_object(s->pointm);
5078 mark_object(s->sb_point);
5079 mark_object(s->mark);
5081 /* #### This looked like this. I do not see why specifier cached
5082 values should not be marked, as such specifiers as toolbars
5083 might have GC-able instances. Freed configs are not marked,
5084 aren't they? -- kkm */
5085 mark_object(s->dedicated);
5087 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5088 #include "winslots.h"
5094 inline static size_t sizeof_window_config_for_n_windows(unsigned int n)
5096 return FLEXIBLE_ARRAY_STRUCT_SIZEOF(struct window_config,
5097 struct saved_window, saved_windows,
5101 static size_t sizeof_window_config(const void *h)
5103 const struct window_config *c = (const struct window_config *)h;
5104 return sizeof_window_config_for_n_windows(c->saved_windows_count);
5108 print_window_config(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5110 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5113 error("printing unreadable object #<window-configuration 0x%x>",
5114 config->header.uid);
5115 write_c_string("#<window-configuration ", printcharfun);
5116 sprintf(buf, "0x%x>", config->header.uid);
5117 write_c_string(buf, printcharfun);
5120 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("window-configuration",
5121 window_configuration,
5123 print_window_config,
5124 0, 0, 0, 0, sizeof_window_config,
5125 struct window_config);
5127 /* Returns a boolean indicating whether the two saved windows are
5130 saved_window_equal(struct saved_window *win1, struct saved_window *win2)
5132 #define WINDOW_SLOT(slot, compare) \
5133 if (!compare (win1->slot, win2->slot)) \
5135 #include "winslots.h"
5138 EQ(win1->window, win2->window) &&
5139 EQ(win1->buffer, win2->buffer) &&
5140 internal_equal(win1->start, win2->start, 0) &&
5141 internal_equal(win1->pointm, win2->pointm, 0) &&
5142 internal_equal(win1->sb_point, win2->sb_point, 0) &&
5143 internal_equal(win1->mark, win2->mark, 0) &&
5144 win1->pixel_left == win2->pixel_left &&
5145 win1->pixel_top == win2->pixel_top &&
5146 win1->pixel_width == win2->pixel_width &&
5147 win1->pixel_height == win2->pixel_height &&
5148 win1->hscroll == win2->hscroll &&
5149 win1->modeline_hscroll == win2->modeline_hscroll &&
5150 win1->parent_index == win2->parent_index &&
5151 win1->prev_index == win2->prev_index &&
5152 win1->start_at_line_beg == win2->start_at_line_beg;
5155 /* Returns a boolean indicating whether the two given configurations
5157 static int window_config_equal(Lisp_Object conf1, Lisp_Object conf2)
5159 struct window_config *fig1, *fig2;
5162 /* First check if they are truly the same. */
5163 if (EQ(conf1, conf2))
5166 fig1 = XWINDOW_CONFIGURATION(conf1);
5167 fig2 = XWINDOW_CONFIGURATION(conf2);
5169 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5170 EQ(fig1->current_window, fig2->current_window) &&
5171 EQ(fig1->current_buffer, fig2->current_buffer) &&
5172 EQ(fig1->root_window, fig2->root_window) &&
5173 EQ(fig1->minibuffer_scroll_window,
5174 fig2->minibuffer_scroll_window)))
5176 fig1->frame_width == fig2->frame_width &&
5177 fig1->frame_height == fig2->frame_height)) */
5180 for (i = 0; i < fig1->saved_windows_count; i++) {
5181 if (!saved_window_equal(SAVED_WINDOW_N(fig1, i),
5182 SAVED_WINDOW_N(fig2, i)))
5189 DEFUN("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5190 Return t if OBJECT is a window-configuration object.
5194 return WINDOW_CONFIGURATIONP(object) ? Qt : Qnil;
5197 static int mark_windows_in_use_closure(struct window *w, void *closure)
5199 int mark = *(int *)closure;
5200 w->config_mark = mark;
5204 static void mark_windows_in_use(struct frame *f, int mark)
5206 map_windows(f, mark_windows_in_use_closure, &mark);
5209 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5210 static Lisp_Object free_window_configuration(Lisp_Object window_config)
5213 struct window_config *config = XWINDOW_CONFIGURATION(window_config);
5215 /* Free all the markers. It's not completely necessary that
5216 we do this (window configs sitting in a free list aren't
5217 marked normally so the markers wouldn't be marked anyway)
5218 but it's more efficient. */
5219 for (i = 0; i < config->saved_windows_count; i++) {
5220 struct saved_window *p = SAVED_WINDOW_N(config, i);
5222 if (!NILP(p->pointm)) {
5223 free_marker(XMARKER(p->pointm));
5226 if (!NILP(p->start)) {
5227 free_marker(XMARKER(p->start));
5230 if (!NILP(p->sb_point)) {
5231 free_marker(XMARKER(p->sb_point));
5234 if (!NILP(p->mark)) {
5235 free_marker(XMARKER(p->mark));
5240 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5241 xfree(window_config);
5244 if (config->saved_windows_count <=
5245 countof(Vwindow_configuration_free_list)) {
5246 free_managed_lcrecord(Vwindow_configuration_free_list
5247 [config->saved_windows_count - 1],
5254 DEFUN("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5255 Set the configuration of windows and buffers as specified by CONFIGURATION.
5256 CONFIGURATION must be a value previously returned
5257 by `current-window-configuration' (which see).
5262 struct window_config *config;
5263 struct saved_window *p;
5264 Lisp_Object new_current_buffer;
5268 struct gcpro gcpro1;
5269 Lisp_Object old_window_config;
5270 /* int previous_frame_height;
5271 int previous_frame_width; */
5272 int previous_pixel_top;
5273 int previous_pixel_height;
5274 int previous_pixel_left;
5275 int previous_pixel_width;
5276 int previous_minibuf_height, previous_minibuf_top,
5277 previous_minibuf_width;
5278 int real_font_height;
5279 int converted_minibuf_height, target_minibuf_height;
5280 int specpdl_count = specpdl_depth();
5282 GCPRO1(configuration);
5284 CHECK_WINDOW_CONFIGURATION(configuration);
5285 config = XWINDOW_CONFIGURATION(configuration);
5287 frame = XWINDOW(SAVED_WINDOW_N(config, 0)->window)->frame;
5290 /* Do not signal an error here if the frame was deleted. There are
5291 reasonable cases where we could get here with a deleted frame and
5292 just want to do close to nothing instead. */
5294 if (FRAME_LIVE_P(f)) {
5295 /* restore the frame characteristics */
5297 new_current_buffer = config->current_buffer;
5298 if (!BUFFER_LIVE_P(XBUFFER(new_current_buffer)))
5299 new_current_buffer = Qnil;
5302 * Assumed precondition: w->config_mark = 0 for all w
5303 * This procedure should ensure this is true by the time it exits
5304 * to ensure the precondition for future calls.
5306 * We use w->config_mark to know whether we're modifying a
5307 * window that is currently visible on the frame (#### we
5308 * should just be able to check whether the window is dead
5309 * or not, but this way is safer?). As we process each
5310 * window, we set its config_mark to 0. At the end, we
5311 * go through all the windows that used to be on the frame,
5312 * set each one's config_mark to 0 (to maintain the
5313 * assumed precondition) and delete each one that's no
5316 * #### Using a window-configuration to keep track of
5317 * the current windows is wasteful. All we need is the
5318 * list of windows, so we could just use a dynarr.
5320 old_window_config = Fcurrent_window_configuration(frame);
5322 /* If the new configuration is already equal to the old, then stop
5323 right here. This saves the work below and it also saves
5324 triggering a full redisplay of this window. This is a huge win
5325 when using the mouse since the mode motion code uses
5326 save-window-excursion extensively but will rarely cause the
5327 configuration to actually change. */
5328 if (window_config_equal(configuration, old_window_config)) {
5329 free_window_configuration(old_window_config);
5334 /* We can't quit or even check for quit because that may cause
5335 investigation of the frame state, which may crash if the frame is
5336 in an inconsistent state. */
5337 begin_dont_check_for_quit();
5338 record_unwind_protect(free_window_configuration,
5341 mark_windows_in_use(f, 1);
5342 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5343 /* Force subwindows to be remapped. This is overkill but saves
5344 us having to rely on the redisplay code to unmap any extant
5347 #### It does cause some extra flashing though which we could
5348 possibly avoid. So consider trying to get redisplay to work
5351 Removing the instances from the frame cache is wrong because
5352 an instance is only put in the frame cache when it is
5353 instantiated. So if we do this there is a chance that stuff
5354 will never get put back in the frame cache. */
5355 reset_frame_subwindow_instance_cache(f);
5358 /* JV: This is bogus,
5359 First of all, the units are inconsistent. The frame sizes are measured
5360 in characters but the window sizes are stored in pixels. So if a
5361 font size change happened between saving and restoring, the
5362 frame "sizes" maybe equal but the windows still should be
5363 resized. This is tickled a lot by the new "character size
5364 stays constant" policy in 21.0. It leads to very weird
5365 glitches (and possibly crashes when asserts are tickled).
5367 Just changing the units doesn't help because changing the
5368 toolbar configuration can also change the pixel positions.
5369 Luckily there is a much simpler way of doing this, see below.
5371 previous_frame_width = FRAME_WIDTH(f);
5372 previous_frame_height = FRAME_HEIGHT(f);
5373 /* If the frame has been resized since this window configuration was
5374 made, we change the frame to the size specified in the
5375 configuration, restore the configuration, and then resize it
5376 back. We keep track of the prevailing height in these variables. */
5377 if (config->frame_height != FRAME_HEIGHT(f)
5378 || config->frame_width != FRAME_WIDTH(f))
5379 change_frame_size(f, config->frame_height,
5380 config->frame_width, 0);
5383 previous_pixel_top = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top;
5384 previous_pixel_height =
5385 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_height;
5386 previous_pixel_left = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left;
5387 previous_pixel_width =
5388 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_width;
5390 /* remember some properties of the minibuffer */
5392 default_face_height_and_width(frame, &real_font_height, 0);
5393 assert(real_font_height > 0);
5395 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f)) {
5396 previous_minibuf_height
5397 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5398 previous_minibuf_top
5399 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5400 previous_minibuf_width
5401 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5403 previous_minibuf_height = 0;
5404 previous_minibuf_top = 0;
5405 previous_minibuf_width = 0;
5407 converted_minibuf_height = (previous_minibuf_height % real_font_height) == 0 ? -(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++) {
5420 p = SAVED_WINDOW_N(config, k);
5421 w = XWINDOW(p->window);
5424 /* The window might be dead. In this case, its redisplay
5425 structures were freed, so we need to reallocate them. */
5426 if (!w->face_cachels) {
5427 w->face_cachels = Dynarr_new(face_cachel);
5428 reset_face_cachels(w);
5430 if (!w->glyph_cachels)
5431 w->glyph_cachels = Dynarr_new(glyph_cachel);
5432 if (!w->line_start_cache)
5433 w->line_start_cache =
5434 Dynarr_new(line_start_cache);
5435 w->gutter_extent_modiff[0] = 0;
5436 w->gutter_extent_modiff[1] = 0;
5437 w->gutter_extent_modiff[2] = 0;
5438 w->gutter_extent_modiff[3] = 0;
5441 if (p->parent_index >= 0)
5443 SAVED_WINDOW_N(config,
5444 p->parent_index)->window;
5448 if (p->prev_index >= 0) {
5450 SAVED_WINDOW_N(config,
5451 p->prev_index)->window;
5453 /* This is true for a minibuffer-only frame. */
5454 if (!NILP(w->mini_p) && EQ(w->prev, p->window))
5457 XWINDOW(w->prev)->next = p->window;
5460 if (!NILP(w->parent)) {
5461 if (WINDOW_WIDTH(p) ==
5462 WINDOW_WIDTH(XWINDOW(w->parent))) {
5463 XWINDOW(w->parent)->vchild =
5465 XWINDOW(w->parent)->hchild =
5468 XWINDOW(w->parent)->hchild =
5470 XWINDOW(w->parent)->vchild =
5475 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);
5480 } else { /* if (!EQ (w->buffer, p->buffer)) */
5482 /* With the new redisplay we let it know that a change has
5483 been made and it will take care of the rest. If we don't
5484 tell it something has possibly changed it could lead to
5485 incorrect display. */
5486 MARK_WINDOWS_CHANGED(w);
5489 WINDOW_LEFT(w) = WINDOW_LEFT(p);
5490 WINDOW_TOP(w) = WINDOW_TOP(p);
5491 WINDOW_WIDTH(w) = WINDOW_WIDTH(p);
5492 WINDOW_HEIGHT(w) = WINDOW_HEIGHT(p);
5493 w->hscroll = p->hscroll;
5494 w->modeline_hscroll = p->modeline_hscroll;
5495 w->line_cache_last_updated = Qzero;
5496 /* When we restore a window's configuration, the identity of
5497 the window hasn't actually changed - so there is no
5498 reason why we shouldn't preserve the instance cache for
5499 it - unless it was originally deleted. This will often
5500 buy us something as we will not have to re-instantiate
5501 all the instances. This is because this is an instance
5502 cache - not a display cache. Preserving the display cache
5503 would definitely be wrong.
5505 We specifically want to do this for tabs, since for some
5506 reason finding a file will cause the configuration to be
5508 if (NILP(w->subwindow_instance_cache))
5509 w->subwindow_instance_cache =
5510 make_image_instance_cache_hash_table();
5512 SET_LAST_MODIFIED(w, 1);
5513 SET_LAST_FACECHANGE(w);
5516 /* #### Consider making the instance cache a winslot. */
5517 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5518 #include "winslots.h"
5520 /* Reinstall the saved buffer and pointers into it. */
5521 if (NILP(p->buffer))
5522 w->buffer = p->buffer;
5524 if (BUFFER_LIVE_P(XBUFFER(p->buffer)))
5525 /* If saved buffer is alive, install it. */
5527 w->buffer = p->buffer;
5528 w->start_at_line_beg =
5529 p->start_at_line_beg;
5530 set_marker_restricted(w->
5536 set_marker_restricted(w->
5542 set_marker_restricted(w->sb_point,
5546 Fset_marker(XBUFFER(w->buffer)->mark,
5547 Fmarker_position(p->mark),
5550 /* As documented in Fcurrent_window_configuration, don't
5551 save the location of point in the buffer which was current
5552 when the window configuration was recorded. */
5553 if (!EQ(p->buffer, new_current_buffer)
5554 && XBUFFER(p->buffer) ==
5557 pointm[CURRENT_DISP],
5559 } else if (NILP(w->buffer)
5561 !BUFFER_LIVE_P(XBUFFER(w->buffer)))
5562 /* Else if window's old buffer is dead too, get a live one. */
5564 /* #### The following line makes me nervous... */
5565 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist)); */
5567 Fget_buffer_create(QSscratch);
5568 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5569 /* This will set the markers to beginning of visible
5571 set_marker_restricted(w->
5575 set_marker_restricted(w->
5579 set_marker_restricted(w->sb_point,
5581 w->start_at_line_beg = 1;
5583 /* Keeping window's old buffer; make sure the markers
5586 /* Set window markers at start of visible range. */
5587 if (XMARKER(w->start[CURRENT_DISP])->
5589 set_marker_restricted(w->
5595 if (XMARKER(w->sb_point)->buffer == 0)
5596 set_marker_restricted(w->
5601 if (XMARKER(w->pointm[CURRENT_DISP])->
5603 set_marker_restricted(w->
5613 w->start_at_line_beg = 1;
5618 FRAME_ROOT_WINDOW(f) = config->root_window;
5619 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5620 then calls do_switch_frame() below to select the frame that was
5621 recorded in the window config as being selected.
5623 Instead, we don't ever change the selected frame, and either
5624 call Fselect_window() below if the window config's frame is
5625 currently selected, or just set the selected window of the
5626 window config's frame. */
5629 /* Set the frame height to the value it had before this function. */
5630 if (previous_frame_height != FRAME_HEIGHT(f)
5631 || previous_frame_width != FRAME_WIDTH(f))
5632 change_frame_size(f, previous_frame_height,
5633 previous_frame_width, 0);
5635 /* We just reset the size and position of the minibuffer, to its old
5636 value, which needn't be valid. So we do some magic to see which value
5637 to actually take. Then we set it.
5640 We take the old value if is in the same units but differs from the
5643 #### Now we get more cases correct then ever before, but
5644 are we treating all? For instance what if the frames minibuf window
5645 is no longer the same one?
5647 target_minibuf_height = previous_minibuf_height;
5648 if (converted_minibuf_height &&
5649 (converted_minibuf_height * config->minibuf_height) > 0 &&
5650 (converted_minibuf_height != config->minibuf_height)) {
5651 target_minibuf_height = config->minibuf_height < 0 ?
5652 -(config->minibuf_height * real_font_height) :
5653 config->minibuf_height;
5654 target_minibuf_height =
5655 max(target_minibuf_height, real_font_height);
5657 if (previous_minibuf_height) {
5658 XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top
5659 = previous_minibuf_top -
5660 (target_minibuf_height - previous_minibuf_height);
5661 set_window_pixheight(FRAME_MINIBUF_WINDOW(f),
5662 target_minibuf_height, 0);
5663 set_window_pixwidth(FRAME_MINIBUF_WINDOW(f),
5664 previous_minibuf_width, 0);
5667 /* This is a better way to deal with frame resizing, etc.
5668 What we _actually_ want is for the old (just restored)
5670 into the place of the new one. So we just do that. Simple! */
5671 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top = previous_pixel_top;
5672 /* Note that this function also updates the subwindow
5674 set_window_pixheight(FRAME_ROOT_WINDOW(f),
5675 previous_pixel_height -
5676 (target_minibuf_height -
5677 previous_minibuf_height), 0);
5678 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left = previous_pixel_left;
5679 /* Note that this function also updates the subwindow
5681 set_window_pixwidth(FRAME_ROOT_WINDOW(f), previous_pixel_width,
5684 /* If restoring in the current frame make the window current,
5685 otherwise just update the frame selected_window slot to be
5686 the restored current_window. */
5687 if (f == selected_frame()) {
5689 /* When using `pop-window-configuration', often the minibuffer
5690 ends up as the selected window even though it's not active ...
5691 I really don't know the cause of this, but it should never
5692 happen. This kludge should fix it.
5694 #### Find out why this is really going wrong. */
5695 if (!minibuf_level &&
5696 MINI_WINDOW_P(XWINDOW(config->current_window)))
5698 Fnext_window(config->current_window, Qnil,
5701 window_to_select = config->current_window;
5703 /* Do this last so that buffer stacking is calculated
5705 Fselect_window(config->current_window, Qnil);
5707 if (!NILP(new_current_buffer)) {
5708 Fset_buffer(new_current_buffer);
5709 Frecord_buffer(new_current_buffer);
5711 Fset_buffer(XWINDOW(config->current_window)->
5713 Frecord_buffer(XWINDOW(config->current_window)->
5717 set_frame_selected_window(f, config->current_window);
5719 old_window_config = Qnil; /* Warning suppression */
5721 /* Restore the minimum heights recorded in the configuration. */
5722 window_min_height = config->min_height;
5723 window_min_width = config->min_width;
5726 /* see above comment */
5727 /* Fselect_window will have made f the selected frame, so we
5728 reselect the proper frame here. Fhandle_switch_frame will change the
5729 selected window too, but that doesn't make the call to
5730 Fselect_window above totally superfluous; it still sets f's
5732 if (FRAME_LIVE_P(XFRAME(config->selected_frame)))
5733 do_switch_frame(config->selected_frame, Qnil, 0);
5736 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5738 if (FRAME_LIVE_P(f)) {
5739 /* Do this before calling recompute_all_cached_specifiers_in_window()
5740 so that things like redisplay_redraw_cursor() won't abort due
5741 to no window mirror present. */
5742 f->mirror_dirty = 1;
5744 config = XWINDOW_CONFIGURATION(old_window_config);
5745 for (k = 0; k < config->saved_windows_count; k++) {
5746 p = SAVED_WINDOW_N(config, k);
5747 w = XWINDOW(p->window);
5748 /* Remember, we set w->config_mark on all currently visible
5749 windows, and reset it on all newly visible windows.
5750 Any windows still marked need to be deleted. */
5751 if (w->config_mark) {
5752 mark_window_as_deleted(w);
5755 /* We just potentially changed the window's buffer and
5756 potentially turned a dead window into a live one,
5757 so we need to recompute the cached specifier values. */
5758 recompute_all_cached_specifiers_in_window(w);
5763 /* Now restore things, when everything else if OK. */
5765 unbind_to(specpdl_count, Qnil);
5772 /* Mark all subwindows of a window as deleted. The argument
5773 W is actually the subwindow tree of the window in question. */
5775 void delete_all_subwindows(struct window *w)
5778 delete_all_subwindows(XWINDOW(w->next));
5779 if (!NILP(w->vchild))
5780 delete_all_subwindows(XWINDOW(w->vchild));
5781 if (!NILP(w->hchild))
5782 delete_all_subwindows(XWINDOW(w->hchild));
5784 mark_window_as_deleted(w);
5787 static unsigned int count_windows(struct window *window)
5790 (!NILP(window->next) ? count_windows(XWINDOW(window->next)) : 0) +
5791 (!NILP(window->vchild) ? count_windows(XWINDOW(window->vchild)) : 0)
5793 (!NILP(window->hchild) ? count_windows(XWINDOW(window->hchild)) :
5798 saved_window_index(Lisp_Object window, struct window_config *config, int lim)
5801 for (j = 0; j < lim; j++) {
5802 if (EQ(SAVED_WINDOW_N(config, j)->window, window))
5806 return 0; /* suppress compiler warning */
5810 save_window_save(Lisp_Object window, struct window_config *config, int i)
5814 for (; !NILP(window); window = w->next) {
5815 struct saved_window *p = SAVED_WINDOW_N(config, i);
5817 w = XWINDOW(window);
5820 p->buffer = w->buffer;
5821 WINDOW_LEFT(p) = WINDOW_LEFT(w);
5822 WINDOW_TOP(p) = WINDOW_TOP(w);
5823 WINDOW_WIDTH(p) = WINDOW_WIDTH(w);
5824 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(w);
5825 p->hscroll = w->hscroll;
5826 p->modeline_hscroll = w->modeline_hscroll;
5828 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5829 #include "winslots.h"
5831 if (!NILP(w->buffer)) {
5832 /* Save w's value of point in the window configuration.
5833 If w is the selected window, then get the value of point
5834 from the buffer; pointm is garbage in the selected window. */
5835 if (EQ(window, Fselected_window(Qnil))) {
5836 p->pointm = noseeum_make_marker();
5837 Fset_marker(p->pointm,
5839 (XBUFFER(w->buffer))),
5843 noseeum_copy_marker(w->pointm[CURRENT_DISP],
5847 noseeum_copy_marker(w->start[CURRENT_DISP], Qnil);
5848 p->sb_point = noseeum_copy_marker(w->sb_point, Qnil);
5849 p->start_at_line_beg = w->start_at_line_beg;
5852 noseeum_copy_marker(XBUFFER(w->buffer)->mark, Qnil);
5858 p->start_at_line_beg = 0;
5861 if (NILP(w->parent))
5862 p->parent_index = -1;
5865 saved_window_index(w->parent, config, i);
5869 p->prev_index = saved_window_index(w->prev, config, i);
5870 if (!NILP(w->vchild))
5871 i = save_window_save(w->vchild, config, i);
5872 if (!NILP(w->hchild))
5873 i = save_window_save(w->hchild, config, i);
5880 /* Added to doc string:
5882 This also records the currently selected frame, and FRAME's focus
5883 redirection (see `redirect-frame-focus').
5888 DEFUN("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5889 Return an object representing the current window configuration of FRAME.
5890 If FRAME is nil or omitted, use the selected frame.
5891 This describes the number of windows, their sizes and current buffers,
5892 and for each window on FRAME the displayed buffer, where display
5893 starts, and the positions of point and mark.
5894 An exception is made for point in the current buffer:
5895 its value is -not- saved.
5900 struct frame *f = decode_frame(frame);
5901 struct window_config *config;
5902 unsigned int n_windows = count_windows(XWINDOW(FRAME_ROOT_WINDOW(f)));
5904 int real_font_height;
5906 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5907 config = (struct window_config *)
5908 alloc_lcrecord(sizeof_window_config_for_n_windows(
5910 &lrecord_window_configuration);
5912 if (n_windows <= countof(Vwindow_configuration_free_list)) {
5914 allocate_managed_lcrecord(
5915 Vwindow_configuration_free_list[n_windows - 1]);
5916 config = XWINDOW_CONFIGURATION(tmp);
5918 /* More than ten windows; just allocate directly */
5919 config = (struct window_config *)
5920 alloc_lcrecord(sizeof_window_config_for_n_windows(
5922 &lrecord_window_configuration);
5925 XSETWINDOW_CONFIGURATION(result, config);
5927 config->frame_width = FRAME_WIDTH (f);
5928 config->frame_height = FRAME_HEIGHT (f); */
5929 /* #### When using `push-window-configuration', often the minibuffer
5930 ends up as the selected window because functions run as the result
5931 of user interaction e.g. hyper-apropos. It seems to me the sensible
5932 thing to do is not record the minibuffer here.
5934 #### Unfortunately this is a change to previous behaviour,
5935 however logical it may be, so revert for the moment. */
5937 if (FRAME_MINIBUF_ONLY_P(f) || minibuf_level)
5938 config->current_window = FRAME_SELECTED_WINDOW(f);
5940 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW(f);
5942 config->current_window = FRAME_SELECTED_WINDOW(f);
5943 XSETBUFFER(config->current_buffer, current_buffer);
5944 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5945 config->root_window = FRAME_ROOT_WINDOW(f);
5946 config->min_height = window_min_height;
5947 config->min_width = window_min_width;
5948 config->saved_windows_count = n_windows;
5949 save_window_save(FRAME_ROOT_WINDOW(f), config, 0);
5951 /* save the minibuffer height using the heuristics from
5952 change_frame_size_1 */
5954 XSETFRAME(frame, f); /* frame could have been nil ! */
5955 default_face_height_and_width(frame, &real_font_height, 0);
5956 assert(real_font_height > 0);
5958 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f))
5959 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5962 config->minibuf_height = (minibuf_height % real_font_height) == 0 ? -(minibuf_height / real_font_height) : /* lines */
5963 minibuf_height; /* pixels */
5968 Lisp_Object save_window_excursion_unwind(Lisp_Object window_config)
5970 Lisp_Object val = Fset_window_configuration(window_config);
5971 free_window_configuration(window_config);
5975 DEFUN("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5976 Execute body, preserving window sizes and contents.
5977 Restores which buffer appears in which window, where display starts,
5978 as well as the current buffer.
5979 Does not restore the value of point in current buffer.
5983 /* This function can GC */
5985 int speccount = specpdl_depth();
5987 record_unwind_protect(save_window_excursion_unwind,
5988 Fcurrent_window_configuration(Qnil));
5990 return unbind_to(speccount, val);
5993 DEFUN("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5994 Return the horizontal pixel position of POS in window.
5995 Beginning of line is column 0. This is calculated using the redisplay
5996 display tables. If WINDOW is nil, the current window is assumed.
5997 If POS is nil, point is assumed. Note that POS must be visible for
5998 a non-nil result to be returned.
6002 struct window *w = decode_window(window);
6003 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
6005 struct display_line *dl = 0;
6006 struct display_block *db = 0;
6007 struct rune *rb = 0;
6008 int y = w->last_point_y[CURRENT_DISP];
6009 int x = w->last_point_x[CURRENT_DISP];
6011 if (MINI_WINDOW_P(w))
6014 if (y < 0 || x < 0 || y >= Dynarr_length(dla) || !NILP(pos)) {
6019 pos = Fwindow_point(window);
6024 if (Dynarr_length(dla) && Dynarr_atp(dla, 0)->modeline)
6029 for (i = first_line; i < Dynarr_length(dla); i++) {
6030 dl = Dynarr_atp(dla, i);
6031 /* find the vertical location first */
6032 if (point >= dl->bufpos && point <= dl->end_bufpos) {
6033 db = get_display_block_from_line(dl, TEXT);
6034 for (i = 0; i < Dynarr_length(db->runes); i++) {
6035 rb = Dynarr_atp(db->runes, i);
6036 if (point <= rb->bufpos)
6046 /* optimized case */
6047 dl = Dynarr_atp(dla, y);
6048 db = get_display_block_from_line(dl, TEXT);
6050 if (x >= Dynarr_length(db->runes))
6053 rb = Dynarr_atp(db->runes, x);
6056 return make_int(rb->xpos - WINDOW_LEFT(w));
6059 #ifdef DEBUG_SXEMACS
6060 /* This is short and simple in elisp, but... it was written to debug
6061 problems purely on the C side. That is where we need to call it so
6063 static void debug_print_window(Lisp_Object window, int level)
6066 Lisp_Object child = Fwindow_first_vchild(window);
6069 child = Fwindow_first_hchild(window);
6071 for (i = level; i > 0; i--)
6074 stderr_out("#<window");
6076 Lisp_Object buffer = XWINDOW(window)->buffer;
6077 if (!NILP(buffer) && BUFFERP(buffer))
6078 stderr_out(" on %s",
6079 XSTRING_DATA(XBUFFER(buffer)->name));
6081 stderr_out(" 0x%x>", XWINDOW(window)->header.uid);
6083 while (!NILP(child)) {
6084 debug_print_window(child, level + 1);
6085 child = Fwindow_next_child(child);
6089 void debug_print_windows(struct frame *f);
6090 void debug_print_windows(struct frame *f)
6092 debug_print_window(f->root_window, 0);
6095 #endif /* DEBUG_SXEMACS */
6097 /************************************************************************/
6098 /* initialization */
6099 /************************************************************************/
6101 void syms_of_window(void)
6103 INIT_LRECORD_IMPLEMENTATION(window);
6104 INIT_LRECORD_IMPLEMENTATION(window_configuration);
6106 defsymbol(&Qwindowp, "windowp");
6107 defsymbol(&Qwindow_live_p, "window-live-p");
6108 defsymbol(&Qwindow_configurationp, "window-configuration-p");
6109 defsymbol(&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6110 defsymbol(&Qdisplay_buffer, "display-buffer");
6112 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6113 defsymbol(&Qface_cache, "face-cache");
6114 defsymbol(&Qglyph_cache, "glyph-cache");
6115 defsymbol(&Qline_start_cache, "line-start-cache");
6116 #ifdef HAVE_SCROLLBARS
6117 defsymbol(&Qscrollbar_instances, "scrollbar-instances");
6119 defsymbol(&Qother_redisplay, "other-redisplay");
6120 /* Qother in general.c */
6123 DEFSYMBOL(Qtruncate_partial_width_windows);
6124 DEFSYMBOL (Qwindow_configuration_hook);
6126 DEFSUBR(Fselected_window);
6127 DEFSUBR(Flast_nonminibuf_window);
6128 DEFSUBR(Fminibuffer_window);
6129 DEFSUBR(Fwindow_minibuffer_p);
6131 DEFSUBR(Fwindow_live_p);
6132 DEFSUBR(Fwindow_first_hchild);
6133 DEFSUBR(Fwindow_first_vchild);
6134 DEFSUBR(Fwindow_next_child);
6135 DEFSUBR(Fwindow_previous_child);
6136 DEFSUBR(Fwindow_parent);
6137 DEFSUBR(Fwindow_lowest_p);
6138 DEFSUBR(Fwindow_truncated_p);
6139 DEFSUBR(Fwindow_highest_p);
6140 DEFSUBR(Fwindow_leftmost_p);
6141 DEFSUBR(Fwindow_rightmost_p);
6142 DEFSUBR(Fpos_visible_in_window_p);
6143 DEFSUBR(Fwindow_buffer);
6144 DEFSUBR(Fwindow_frame);
6145 DEFSUBR(Fwindow_height);
6146 DEFSUBR(Fwindow_displayed_height);
6147 DEFSUBR(Fwindow_width);
6148 DEFSUBR(Fwindow_full_width);
6149 DEFSUBR(Fwindow_pixel_height);
6150 DEFSUBR(Fwindow_pixel_width);
6151 DEFSUBR(Fwindow_text_area_height);
6152 DEFSUBR(Fwindow_text_area_pixel_height);
6153 DEFSUBR(Fwindow_displayed_text_pixel_height);
6154 DEFSUBR(Fwindow_text_area_pixel_width);
6155 DEFSUBR(Fwindow_hscroll);
6156 DEFSUBR(Fset_window_hscroll);
6157 DEFSUBR(Fmodeline_hscroll);
6158 DEFSUBR(Fset_modeline_hscroll);
6159 #if 0 /* bogus FSF crock */
6160 DEFSUBR(Fwindow_redisplay_end_trigger);
6161 DEFSUBR(Fset_window_redisplay_end_trigger);
6163 DEFSUBR(Fwindow_pixel_edges);
6164 DEFSUBR(Fwindow_text_area_pixel_edges);
6165 DEFSUBR(Fwindow_point);
6166 DEFSUBR(Fwindow_start);
6167 DEFSUBR(Fwindow_end);
6168 DEFSUBR(Fwindow_last_line_visible_height);
6169 DEFSUBR(Fset_window_point);
6170 DEFSUBR(Fset_window_start);
6171 DEFSUBR(Fwindow_dedicated_p);
6172 DEFSUBR(Fset_window_dedicated_p);
6173 DEFSUBR(Fnext_window);
6174 DEFSUBR(Fprevious_window);
6175 DEFSUBR(Fnext_vertical_window);
6176 DEFSUBR(Fother_window);
6177 DEFSUBR(Fget_lru_window);
6178 DEFSUBR(Fget_largest_window);
6179 DEFSUBR(Fget_buffer_window);
6180 DEFSUBR(Fwindow_left_margin_pixel_width);
6181 DEFSUBR(Fwindow_right_margin_pixel_width);
6182 DEFSUBR(Fdelete_other_windows);
6183 DEFSUBR(Fdelete_windows_on);
6184 DEFSUBR(Freplace_buffer_in_windows);
6185 DEFSUBR(Fdelete_window);
6186 DEFSUBR(Fset_window_buffer);
6187 DEFSUBR(Fselect_window);
6188 DEFSUBR(Fsplit_window);
6189 DEFSUBR(Fenlarge_window);
6190 DEFSUBR(Fenlarge_window_pixels);
6191 DEFSUBR(Fshrink_window);
6192 DEFSUBR(Fshrink_window_pixels);
6193 DEFSUBR(Fscroll_up);
6194 DEFSUBR(Fscroll_down);
6195 DEFSUBR(Fscroll_left);
6196 DEFSUBR(Fscroll_right);
6197 DEFSUBR(Fother_window_for_scrolling);
6198 DEFSUBR(Fscroll_other_window);
6199 DEFSUBR(Fcenter_to_window_line);
6200 DEFSUBR(Fmove_to_window_line);
6201 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6202 DEFSUBR(Fwindow_memory_usage);
6204 DEFSUBR(Fwindow_configuration_p);
6205 DEFSUBR(Fset_window_configuration);
6206 DEFSUBR(Fcurrent_window_configuration);
6207 DEFSUBR(Fsave_window_excursion);
6208 DEFSUBR(Fcurrent_pixel_column);
6211 void reinit_vars_of_window(void)
6213 /* Make sure all windows get marked */
6214 minibuf_window = Qnil;
6215 staticpro_nodump(&minibuf_window);
6217 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
6218 for (unsigned int i = 0;
6219 i < countof(Vwindow_configuration_free_list); i++) {
6220 Vwindow_configuration_free_list[i] =
6221 make_lcrecord_list(sizeof_window_config_for_n_windows(
6223 &lrecord_window_configuration);
6224 staticpro_nodump(&Vwindow_configuration_free_list[i]);
6230 void vars_of_window(void)
6232 reinit_vars_of_window();
6234 DEFVAR_BOOL("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6235 *Non-nil means to scroll if point lands on a line which is clipped.
6237 scroll_on_clipped_lines = 1;
6239 DEFVAR_LISP("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6240 See `temp-buffer-show-function'.
6242 Vtemp_buffer_show_hook = Qnil;
6244 DEFVAR_LISP("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6245 Non-nil means call as function to display a help buffer.
6246 The function is called with one argument, the buffer to be displayed.
6247 Used by `with-output-to-temp-buffer'.
6248 If this function is used, then it must do the entire job of showing
6249 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6250 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6252 Vtemp_buffer_show_function = Qnil;
6254 DEFVAR_LISP("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6255 Non-nil means it is the window that
6256 \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should
6259 Vminibuffer_scroll_window = Qnil;
6261 DEFVAR_LISP("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6262 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6264 Vother_window_scroll_buffer = Qnil;
6266 DEFVAR_LISP("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6267 *Number of pixels to scroll by per requested line.
6268 If nil then normal line scrolling occurs regardless of line height.
6269 If t then scrolling is done in increments equal to the height of the default face.
6271 Vwindow_pixel_scroll_increment = Qt;
6273 DEFVAR_LISP ("window-configuration-hook", &Vwindow_configuration_hook /*
6274 Function(s) to call when a frame's window configuration has changed.
6276 Please see (Info-goto-node "(lispref)Window Configuration Hook") where all the
6277 details are documented.
6280 Vwindow_configuration_hook = Qnil;
6283 DEFVAR_INT("next-screen-context-lines", &next_screen_context_lines /*
6284 *Number of lines of continuity when scrolling by screenfuls.
6286 next_screen_context_lines = 2;
6288 DEFVAR_INT("window-min-height", &window_min_height /*
6289 *Delete any window less than this tall (including its modeline).
6291 window_min_height = 4;
6293 DEFVAR_INT("window-min-width", &window_min_width /*
6294 *Delete any window less than this wide.
6296 window_min_width = 10;
6299 void specifier_vars_of_window(void)
6301 DEFVAR_SPECIFIER("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6302 *How thick to draw 3D shadows around modelines.
6303 If this is set to 0, modelines will be the traditional 2D. Sizes above
6304 10 will be accepted but the maximum thickness that will be drawn is 10.
6305 This is a specifier; use `set-specifier' to change it.
6307 Vmodeline_shadow_thickness = Fmake_specifier(Qinteger);
6308 /* The initial value for modeline-shadow-thickness is 2, but if the
6309 user removes all specifications we provide a fallback value of 0,
6310 which is probably what was expected. */
6311 set_specifier_fallback(Vmodeline_shadow_thickness,
6312 list1(Fcons(Qnil, Qzero)));
6313 Fadd_spec_to_specifier(Vmodeline_shadow_thickness, make_int(2),
6315 set_specifier_caching(Vmodeline_shadow_thickness,
6316 offsetof(struct window,
6317 modeline_shadow_thickness),
6318 modeline_shadow_thickness_changed, 0, 0, 0);
6320 DEFVAR_SPECIFIER("has-modeline-p", &Vhas_modeline_p /*
6321 *Whether the modeline should be displayed.
6322 This is a specifier; use `set-specifier' to change it.
6324 Vhas_modeline_p = Fmake_specifier(Qboolean);
6325 set_specifier_fallback(Vhas_modeline_p, list1(Fcons(Qnil, Qt)));
6326 set_specifier_caching(Vhas_modeline_p,
6327 offsetof(struct window, has_modeline_p),
6328 /* #### It's strange that we need a special
6329 flag to indicate that the shadow-thickness
6330 has changed, but not one to indicate that
6331 the modeline has been turned off or on. */
6332 some_window_value_changed, 0, 0, 0);
6334 DEFVAR_SPECIFIER("vertical-divider-always-visible-p", &Vvertical_divider_always_visible_p /*
6335 *Should SXEmacs always display vertical dividers between windows.
6337 When this is non-nil, vertical dividers are always shown, and are
6338 draggable. When it is nil, vertical dividers are shown only when
6339 there are no scrollbars in between windows, and are not draggable.
6341 This is a specifier; use `set-specifier' to change it.
6343 Vvertical_divider_always_visible_p = Fmake_specifier(Qboolean);
6344 set_specifier_fallback(Vvertical_divider_always_visible_p,
6345 list1(Fcons(Qnil, Qt)));
6346 set_specifier_caching(Vvertical_divider_always_visible_p,
6347 offsetof(struct window,
6348 vertical_divider_always_visible_p),
6349 vertical_divider_changed_in_window, 0, 0, 0);
6351 DEFVAR_SPECIFIER("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6352 *How thick to draw 3D shadows around vertical dividers.
6353 This is a specifier; use `set-specifier' to change it.
6355 Vvertical_divider_shadow_thickness = Fmake_specifier(Qinteger);
6356 set_specifier_fallback(Vvertical_divider_shadow_thickness,
6357 list1(Fcons(Qnil, Qzero)));
6358 Fadd_spec_to_specifier(Vvertical_divider_shadow_thickness, make_int(2),
6360 set_specifier_caching(Vvertical_divider_shadow_thickness,
6361 offsetof(struct window,
6362 vertical_divider_shadow_thickness),
6363 vertical_divider_changed_in_window, 0, 0, 0);
6364 DEFVAR_SPECIFIER("vertical-divider-line-width", &Vvertical_divider_line_width /*
6365 *The width of the vertical dividers, not including shadows.
6367 For TTY windows, divider line is always one character wide. When
6368 instance of this specifier is zero in a TTY window, no divider is
6369 drawn at all between windows. When non-zero, a one character wide
6370 divider is displayed.
6372 This is a specifier; use `set-specifier' to change it.
6375 Vvertical_divider_line_width = Fmake_specifier(Qnatnum);
6377 Lisp_Object fb = Qnil;
6379 fb = Fcons(Fcons(list1(Qtty), make_int(1)), fb);
6382 fb = Fcons(Fcons(list1(Qgtk), make_int(3)), fb);
6384 #ifdef HAVE_X_WINDOWS
6385 fb = Fcons(Fcons(list1(Qx), make_int(3)), fb);
6387 set_specifier_fallback(Vvertical_divider_line_width, fb);
6389 set_specifier_caching(Vvertical_divider_line_width,
6390 offsetof(struct window,
6391 vertical_divider_line_width),
6392 vertical_divider_changed_in_window, 0, 0, 0);
6394 DEFVAR_SPECIFIER("vertical-divider-spacing", &Vvertical_divider_spacing /*
6395 *How much space to leave around the vertical dividers.
6397 In TTY windows, spacing is always zero, and the value of this
6398 specifier is ignored.
6400 This is a specifier; use `set-specifier' to change it.
6402 Vvertical_divider_spacing = Fmake_specifier(Qnatnum);
6404 Lisp_Object fb = Qnil;
6406 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
6408 #ifdef HAVE_X_WINDOWS
6409 /* #### 3D dividers look great on MS Windows with spacing = 0.
6410 Should not the same value be the fallback under X? - kkm */
6411 fb = Fcons(Fcons(list1(Qx), make_int(2)), fb);
6414 fb = Fcons(Fcons(list1(Qgtk), Qzero), fb);
6416 set_specifier_fallback(Vvertical_divider_spacing, fb);
6418 set_specifier_caching(Vvertical_divider_spacing,
6419 offsetof(struct window, vertical_divider_spacing),
6420 vertical_divider_changed_in_window, 0, 0, 0);