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)
216 error("printing unreadable object #<window 0x%x>",
217 XWINDOW(obj)->header.uid);
219 write_c_string("#<window", printcharfun);
220 if (!NILP(XWINDOW(obj)->buffer)) {
221 Lisp_Object name = XBUFFER(XWINDOW(obj)->buffer)->name;
222 write_c_string(" on ", printcharfun);
223 print_internal(name, printcharfun, 1);
225 write_fmt_str(printcharfun, " 0x%x>", XWINDOW(obj)->header.uid);
228 static void finalize_window(void *header, int for_disksave)
230 struct window *w = (struct window *)header;
232 if (w->line_start_cache) {
233 Dynarr_free(w->line_start_cache);
234 w->line_start_cache = 0;
237 if (w->face_cachels) {
240 for (i = 0; i < Dynarr_length(w->face_cachels); i++) {
241 struct face_cachel *cachel =
242 Dynarr_atp(w->face_cachels, i);
243 if (cachel->merged_faces) {
244 Dynarr_free(cachel->merged_faces);
245 cachel->merged_faces = 0;
248 Dynarr_free(w->face_cachels);
252 if (w->glyph_cachels) {
253 Dynarr_free(w->glyph_cachels);
254 w->glyph_cachels = 0;
258 DEFINE_LRECORD_IMPLEMENTATION("window", window,
259 mark_window, print_window, finalize_window,
260 0, 0, 0, struct window);
262 #define INIT_DISP_VARIABLE(field, initialization) \
263 p->field[CURRENT_DISP] = initialization; \
264 p->field[DESIRED_DISP] = initialization; \
265 p->field[CMOTION_DISP] = initialization;
267 /* We have an implicit assertion that the first two elements (default
268 and modeline faces) are always present in the face_element_cache.
269 Normally redisplay ensures this. However, it is possible for a
270 window to get created and functions which reference these values
271 called before redisplay works with the window for the first time.
272 All callers of allocate_window should therefore call
273 reset_face_cachels on the created window. We can't do it
274 here because the window must have its frame pointer set or
275 reset_face_cachels will fail. */
276 Lisp_Object allocate_window(void)
279 struct window *p = alloc_lcrecord_type(struct window, &lrecord_window);
293 INIT_DISP_VARIABLE(start, Fmake_marker());
294 INIT_DISP_VARIABLE(pointm, Fmake_marker());
295 p->sb_point = Fmake_marker();
297 INIT_DISP_VARIABLE(last_modified, Qzero);
298 INIT_DISP_VARIABLE(last_point, Fmake_marker());
299 INIT_DISP_VARIABLE(last_start, Fmake_marker());
300 INIT_DISP_VARIABLE(last_facechange, Qzero);
301 p->face_cachels = Dynarr_new(face_cachel);
302 p->glyph_cachels = Dynarr_new(glyph_cachel);
303 p->line_start_cache = Dynarr_new(line_start_cache);
304 p->subwindow_instance_cache = make_image_instance_cache_hash_table();
306 p->line_cache_last_updated = Qzero;
307 INIT_DISP_VARIABLE(last_point_x, 0);
308 INIT_DISP_VARIABLE(last_point_y, 0);
309 INIT_DISP_VARIABLE(window_end_pos, 0);
310 p->redisplay_end_trigger = Qnil;
312 p->gutter_extent_modiff[0] = 0;
313 p->gutter_extent_modiff[1] = 0;
314 p->gutter_extent_modiff[2] = 0;
315 p->gutter_extent_modiff[3] = 0;
317 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
318 #include "winslots.h"
320 p->windows_changed = 1;
321 p->shadow_thickness_changed = 1;
326 #undef INIT_DISP_VARIABLE
329 * The redisplay structures used to be stored with each window. While
330 * they are logically something associated with frames they can't be
331 * stored there with a redisplay which handles variable height lines.
332 * Lines in horizontally split windows might not line up. So they get
333 * stored with the windows.
335 * The problem with this is window configurations. When restoring a
336 * window configuration it now becomes problematic to do an
337 * incremental redisplay. The solution is to store the redisplay
338 * structures with the frame as they should be but laid out in the
339 * same manner as the window structure. Thus is born the window
342 * It also becomes a convenient place to stick scrollbar instances
343 * since they extrapolate out to having the same problem described for
344 * the display structures.
347 /* Create a new window mirror structure and associated redisplay
349 static struct window_mirror *new_window_mirror(struct frame *f)
351 struct window_mirror *t = xnew_and_zero(struct window_mirror);
355 t->current_display_lines = Dynarr_new(display_line);
356 t->desired_display_lines = Dynarr_new(display_line);
359 #ifdef HAVE_SCROLLBARS
360 t->scrollbar_vertical_instance = NULL;
361 t->scrollbar_horizontal_instance = NULL;
367 /* Synchronize the mirror structure with a given window structure.
368 This is normally called from update_frame_window_mirror with a
369 starting window of f->root_window. */
370 static struct window_mirror *update_mirror_internal(Lisp_Object win,
371 struct window_mirror *mir)
375 free_window_mirror(mir);
380 mir = new_window_mirror(XFRAME(XWINDOW(win)->frame));
382 mir->next = update_mirror_internal(XWINDOW(win)->next, mir->next);
383 mir->hchild = update_mirror_internal(XWINDOW(win)->hchild, mir->hchild);
384 mir->vchild = update_mirror_internal(XWINDOW(win)->vchild, mir->vchild);
387 * If the redisplay structs are not empty and the mirror has
388 * children, then this mirror structure was formerly being used for
389 * display but is no longer. Reset its current display structs so
390 * that redisplay doesn't accidentally think they are accurate if it
391 * is later used for display purposes once again. Also, mark the
392 * scrollbar instance as not active.
394 if (mir->vchild || mir->hchild) {
395 /* The redisplay structures are big. Leaving them around in
396 non-leaf windows can add up to a lot of wasted space. So
398 free_display_structs(mir);
399 mir->current_display_lines = Dynarr_new(display_line);
400 mir->desired_display_lines = Dynarr_new(display_line);
402 #ifdef HAVE_SCROLLBARS
403 update_window_scrollbars(XWINDOW(win), mir, 0, 0);
411 /* Given a window mirror, determine which real window it contains the
412 redisplay structures for. */
414 real_window_internal(Lisp_Object win, struct window_mirror *rmir,
415 struct window_mirror *mir)
417 for (; !NILP(win) && rmir; win = XWINDOW(win)->next, rmir = rmir->next) {
420 if (!NILP(XWINDOW(win)->vchild)) {
422 real_window_internal(XWINDOW(win)->vchild,
427 if (!NILP(XWINDOW(win)->hchild)) {
429 real_window_internal(XWINDOW(win)->hchild,
439 /* Given a real window, find the mirror structure which contains its
440 redisplay structures. */
441 static struct window_mirror *find_window_mirror_internal(Lisp_Object win,
446 for (; !NILP(win); win = XWINDOW(win)->next, rmir = rmir->next) {
447 if (w == XWINDOW(win))
450 if (!NILP(XWINDOW(win)->vchild)) {
451 struct window_mirror *retval =
452 find_window_mirror_internal(XWINDOW(win)->vchild,
458 if (!NILP(XWINDOW(win)->hchild)) {
459 struct window_mirror *retval =
460 find_window_mirror_internal(XWINDOW(win)->hchild,
470 /* Update the mirror structure for the given frame. */
471 void update_frame_window_mirror(struct frame *f)
473 f->root_mirror = update_mirror_internal(f->root_window, f->root_mirror);
477 /* Free a given mirror structure along with all of its children as
478 well as their associated display structures. */
479 void free_window_mirror(struct window_mirror *mir)
482 struct window_mirror *free_me = mir;
484 free_window_mirror(mir->hchild);
486 free_window_mirror(mir->vchild);
487 #ifdef HAVE_SCROLLBARS
488 release_window_mirror_scrollbars(mir);
490 free_display_structs(mir);
496 /* Given a mirror structure, return the window it mirrors. Calls
497 real_window_internal to do most of the work. */
498 Lisp_Object real_window(struct window_mirror *mir, int no_abort)
500 Lisp_Object retval = real_window_internal(mir->frame->root_window,
501 mir->frame->root_mirror, mir);
502 if (NILP(retval) && !no_abort)
508 /* Given a real window, return its mirror structure. Calls
509 find_window_mirror_internal to do all of the work. */
510 struct window_mirror *find_window_mirror(struct window *w)
512 struct frame *f = XFRAME(w->frame);
514 update_frame_window_mirror(f);
515 return find_window_mirror_internal(f->root_window, f->root_mirror, w);
518 /*****************************************************************************
519 find_window_by_pixel_pos
521 Given a pixel position relative to a frame, find the window at that
523 ****************************************************************************/
524 struct window *find_window_by_pixel_pos(int pix_x, int pix_y, Lisp_Object win)
529 for (; !NILP(win); win = XWINDOW(win)->next) {
532 if (!NILP(XWINDOW(win)->vchild)) {
533 w = find_window_by_pixel_pos(pix_x, pix_y,
534 XWINDOW(win)->vchild);
538 if (!NILP(XWINDOW(win)->hchild)) {
539 w = find_window_by_pixel_pos(pix_x, pix_y,
540 XWINDOW(win)->hchild);
545 if (pix_x >= WINDOW_LEFT(w)
546 && pix_x <= WINDOW_RIGHT(w)
547 && pix_y >= WINDOW_TOP(w)
548 && pix_y <= WINDOW_BOTTOM(w))
554 /* Return a pointer to the display structures for the given window. */
555 display_line_dynarr *window_display_lines(struct window * w, int which)
557 struct window_mirror *t;
559 if (XFRAME(w->frame)->mirror_dirty)
560 update_frame_window_mirror(XFRAME(w->frame));
561 t = find_window_mirror(w);
564 else if (which == CURRENT_DISP)
565 return t->current_display_lines;
566 else if (which == DESIRED_DISP)
567 return t->desired_display_lines;
568 else if (which == CMOTION_DISP)
569 /* The CMOTION_DISP display lines are global. */
570 return cmotion_display_lines;
574 return 0; /* shut up compiler */
577 struct buffer *window_display_buffer(struct window *w)
579 struct window_mirror *t;
581 if (XFRAME(w->frame)->mirror_dirty)
582 update_frame_window_mirror(XFRAME(w->frame));
583 t = find_window_mirror(w);
592 void set_window_display_buffer(struct window *w, struct buffer *b)
594 struct window_mirror *t;
596 if (XFRAME(w->frame)->mirror_dirty)
597 update_frame_window_mirror(XFRAME(w->frame));
598 t = find_window_mirror(w);
605 /* Determining a window's position based solely on its pixel
606 positioning doesn't work. Instead, we do it the intelligent way,
607 by checking its positioning in the window hierarchy. */
608 int window_is_leftmost(struct window *w)
610 Lisp_Object parent, current_ancestor, window;
612 XSETWINDOW(window, w);
614 parent = XWINDOW(window)->parent;
615 current_ancestor = window;
617 while (!NILP(parent)) {
618 if (!NILP(XWINDOW(parent)->hchild) &&
619 !EQ(XWINDOW(parent)->hchild, current_ancestor))
622 current_ancestor = parent;
623 parent = XWINDOW(parent)->parent;
629 int window_is_rightmost(struct window *w)
631 Lisp_Object parent, current_ancestor, window;
633 XSETWINDOW(window, w);
635 parent = XWINDOW(window)->parent;
636 current_ancestor = window;
638 while (!NILP(parent)) {
639 if (!NILP(XWINDOW(parent)->hchild)
640 && !NILP(XWINDOW(current_ancestor)->next))
643 current_ancestor = parent;
644 parent = XWINDOW(parent)->parent;
650 static int window_full_width_p(struct window *w)
652 return window_is_leftmost(w) && window_is_rightmost(w);
655 int window_is_highest(struct window *w)
657 Lisp_Object parent, current_ancestor, window;
659 XSETWINDOW(window, w);
661 parent = XWINDOW(window)->parent;
662 current_ancestor = window;
664 while (!NILP(parent)) {
665 if (!NILP(XWINDOW(parent)->vchild) &&
666 !EQ(XWINDOW(parent)->vchild, current_ancestor))
669 current_ancestor = parent;
670 parent = XWINDOW(parent)->parent;
673 /* This is really to catch the minibuffer but we make it generic in
674 case we ever change things around to let the minibuffer be on top. */
675 if (NILP(XWINDOW(current_ancestor)->prev))
681 int window_is_lowest(struct window *w)
683 Lisp_Object parent, current_ancestor, window;
685 XSETWINDOW(window, w);
687 parent = XWINDOW(window)->parent;
688 current_ancestor = window;
690 while (!NILP(parent)) {
691 if (!NILP(XWINDOW(parent)->vchild)
692 && !NILP(XWINDOW(current_ancestor)->next))
695 current_ancestor = parent;
696 parent = XWINDOW(parent)->parent;
702 #if 0 /* not currently used */
704 static int window_full_height_p(struct window *w)
706 return window_is_highest(w) && window_is_lowest(w);
711 int window_truncation_on(struct window *w)
713 /* Minibuffer windows are never truncated.
714 #### is this the right way ? */
715 if (MINI_WINDOW_P(w))
718 /* Horizontally scrolled windows are truncated. */
722 /* If truncate_partial_width_windows is true and the window is not
723 the full width of the frame it is truncated. */
724 if (!NILP(symbol_value_in_buffer(Qtruncate_partial_width_windows,
726 && !(window_is_leftmost(w) && window_is_rightmost(w)))
729 /* If the window's buffer's value of truncate_lines is non-nil, then
730 the window is truncated. */
731 if (!NILP(XBUFFER(w->buffer)->truncate_lines))
737 DEFUN("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
738 Returns non-nil if text in the window is truncated.
742 struct window *w = decode_window(window);
744 return window_truncation_on(w) ? Qt : Qnil;
747 static int have_undivided_common_edge(struct window *w_right, void *closure)
749 struct window *w_left = (struct window *)closure;
750 return (WINDOW_RIGHT(w_left) == WINDOW_LEFT(w_right)
751 && WINDOW_TOP(w_left) < WINDOW_BOTTOM(w_right)
752 && WINDOW_TOP(w_right) < WINDOW_BOTTOM(w_left)
753 #ifdef HAVE_SCROLLBARS
754 && (NILP(w_right->scrollbar_on_left_p)
755 || NILP(w_right->vertical_scrollbar_visible_p)
756 || ZEROP(w_right->scrollbar_width))
761 static int window_needs_vertical_divider_1(struct window *w)
763 /* Never if we're on the right */
764 if (window_is_rightmost(w))
767 /* Always if draggable */
768 if (!NILP(w->vertical_divider_always_visible_p))
771 #ifdef HAVE_SCROLLBARS
772 /* Our right scrollbar is enough to separate us at the right */
773 if (NILP(w->scrollbar_on_left_p)
774 && !NILP(w->vertical_scrollbar_visible_p)
775 && !ZEROP(w->scrollbar_width))
779 /* Ok. to determine whether we need a divider on the left, we must
780 check that our right neighbor windows have scrollbars on their
781 left sides. We must check all such windows which have common
782 left edge with our window's right edge. */
783 return map_windows(XFRAME(WINDOW_FRAME(w)),
784 have_undivided_common_edge, (void *)w);
787 int window_needs_vertical_divider(struct window *w)
789 if (!w->need_vertical_divider_valid_p) {
790 w->need_vertical_divider_p = window_needs_vertical_divider_1(w);
791 w->need_vertical_divider_valid_p = 1;
793 return w->need_vertical_divider_p;
796 /* Called from invalidate_vertical_divider_cache_in_frame */
798 invalidate_vertical_divider_cache_in_window(struct window *w, void *u_n_u_s_e_d)
800 w->need_vertical_divider_valid_p = 0;
804 /* Calculate width of vertical divider, including its shadows
805 and spacing. The returned value is effectively the distance
806 between adjacent window edges. This function does not check
807 whether a window needs a vertical divider, so the returned
808 value is a "theoretical" one */
809 int window_divider_width(struct window *w)
811 /* the shadow thickness can be negative. This means that the divider
812 will have a depressed look */
814 if (FRAME_WIN_P(XFRAME(WINDOW_FRAME(w))))
815 return XINT(w->vertical_divider_line_width)
816 + 2 * XINT(w->vertical_divider_spacing)
817 + 2 * abs(XINT(w->vertical_divider_shadow_thickness));
819 return XINT(w->vertical_divider_line_width) == 0 ? 0 : 1;
822 int window_scrollbar_width(struct window *w)
824 #ifdef HAVE_SCROLLBARS
828 || NILP(w->vertical_scrollbar_visible_p))
829 /* #### when does NILP (w->buffer) happen? */
832 return XINT(w->scrollbar_width);
835 #endif /* HAVE_SCROLLBARS */
838 /* Horizontal scrollbars are only active on windows with truncation
840 int window_scrollbar_height(struct window *w)
842 #ifdef HAVE_SCROLLBARS
846 || NILP(w->horizontal_scrollbar_visible_p)
847 || !window_truncation_on(w))
850 return XINT(w->scrollbar_height);
853 #endif /* HAVE_SCROLLBARS */
856 int window_modeline_height(struct window *w)
858 struct frame *f = XFRAME(w->frame);
861 if (MINI_WINDOW_P(w) || NILP(w->buffer)) {
863 } else if (!WINDOW_HAS_MODELINE_P(w)) {
864 if (window_scrollbar_height(w))
867 modeline_height = FRAMEMETH(f, divider_height, ());
869 if (!EQ(Qzero, w->modeline_shadow_thickness)
872 (2 * MODELINE_SHADOW_THICKNESS(w));
878 display_line_dynarr *dla;
880 /* We don't force a regeneration of the modeline here.
881 Instead it is now a precondition that any function calling
882 this should make sure that one of these structures is
883 up-to-date. In practice this only affects two internal
884 redisplay functions, regenerate_window and
885 regenerate_window_point_center. */
886 /* We check DESIRED_DISP because if it is valid it is more
887 up-to-date than CURRENT_DISP. For calls to this outside
888 of redisplay it doesn't matter which structure we check
889 since there is a redisplay condition that these
890 structures be identical outside of redisplay. */
891 dla = window_display_lines(w, DESIRED_DISP);
892 if (dla && Dynarr_length(dla)
893 && Dynarr_atp(dla, 0)->modeline)
895 (Dynarr_atp(dla, 0)->ascent +
896 Dynarr_atp(dla, 0)->descent);
898 dla = window_display_lines(w, CURRENT_DISP);
899 if (dla && Dynarr_length(dla)
900 && Dynarr_atp(dla, 0)->modeline)
902 (Dynarr_atp(dla, 0)->ascent +
903 Dynarr_atp(dla, 0)->descent);
905 /* This should be an abort except I'm not yet 100%
906 confident that it won't ever get hit (though I
907 haven't been able to trigger it). It is extremely
908 unlikely to cause any noticeable problem and even if
909 it does it will be a minor display glitch. */
910 /* #### Bullshit alert. It does get hit and it causes
911 noticeable glitches. real_current_modeline_height
912 is a kludge to fix this for 19.14. */
914 real_current_modeline_height(w);
917 if (!EQ(Qzero, w->modeline_shadow_thickness)
920 (2 * MODELINE_SHADOW_THICKNESS(w));
924 return modeline_height;
927 /*****************************************************************************
928 margin_width_internal
930 For a given window, return the width in pixels of the specified margin.
931 ****************************************************************************/
932 static int margin_width_internal(struct window *w, int left_margin)
934 int window_cwidth = window_char_width(w, 1);
939 /* We might be getting called on a non-leaf. */
943 /* The minibuffer never has margins. */
944 if (MINI_WINDOW_P(w))
947 XSETWINDOW(window, w);
948 (void)XBUFFER(w->buffer);
949 margin_cwidth = (left_margin ? XINT(w->left_margin_width) :
950 XINT(w->right_margin_width));
952 default_face_height_and_width(window, 0, &font_width);
954 /* The left margin takes precedence over the right margin so we
955 subtract its width from the space available for the right
958 window_cwidth -= XINT(w->left_margin_width);
960 /* The margin cannot be wider than the window is. We allow the
961 value to be bigger since it is possible for the user to enlarge
962 the window such that the left margin value would no longer be too
963 big, but we won't return a value that is larger. */
964 if (margin_cwidth > window_cwidth)
965 margin_cwidth = window_cwidth;
967 /* At the user level the margin is always specified in characters.
968 Internally however it is manipulated in terms of pixels. */
969 return margin_cwidth * font_width;
972 int window_left_margin_width(struct window *w)
974 return margin_width_internal(w, 1);
977 int window_right_margin_width(struct window *w)
979 return margin_width_internal(w, 0);
982 /*****************************************************************************
985 The gutters of a window are those areas in the boundary defined by
986 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
987 do not contain text. Items which may be in the gutters include
988 scrollbars, toolbars and modelines. The margin areas are not
989 included. This is an exception made because redisplay special cases
990 the handling of those areas in many places in such a way that
991 including them in the gutter area would make life difficult.
993 The size functions refer to height for the bottom and top gutters and
994 width for the left and right gutters. The starting position
995 functions refer to the Y coord for bottom and top gutters and the X
996 coord for left and right gutters. All starting positions are
997 relative to the frame, not the window.
998 ****************************************************************************/
1000 static int window_top_window_gutter_height(struct window *w)
1002 if (!NILP(w->hchild) || !NILP(w->vchild))
1005 #ifdef HAVE_SCROLLBARS
1006 if (!NILP(w->scrollbar_on_top_p))
1007 return window_scrollbar_height(w);
1013 int window_top_gutter_height(struct window *w)
1015 return window_top_window_gutter_height(w);
1018 static int window_bottom_window_gutter_height(struct window *w)
1022 if (!NILP(w->hchild) || !NILP(w->vchild))
1025 gutter = window_modeline_height(w);
1027 #ifdef HAVE_SCROLLBARS
1028 if (NILP(w->scrollbar_on_top_p))
1029 return window_scrollbar_height(w) + gutter;
1035 int window_bottom_gutter_height(struct window *w)
1037 return window_bottom_window_gutter_height(w);
1040 static int window_left_window_gutter_width(struct window *w, int modeline)
1042 if (!NILP(w->hchild) || !NILP(w->vchild))
1045 #ifdef HAVE_SCROLLBARS
1046 if (!modeline && !NILP(w->scrollbar_on_left_p))
1047 return window_scrollbar_width(w);
1053 int window_left_gutter_width(struct window *w, int modeline)
1055 return window_left_window_gutter_width(w, modeline);
1058 static int window_right_window_gutter_width(struct window *w, int modeline)
1062 if (!NILP(w->hchild) || !NILP(w->vchild))
1065 #ifdef HAVE_SCROLLBARS
1066 if (!modeline && NILP(w->scrollbar_on_left_p))
1067 gutter += window_scrollbar_width(w);
1070 if (window_needs_vertical_divider(w))
1071 gutter += window_divider_width(w);
1076 int window_right_gutter_width(struct window *w, int modeline)
1078 return window_right_window_gutter_width(w, modeline);
1081 static int window_pixel_height(struct window *w)
1083 return WINDOW_HEIGHT(w);
1086 DEFUN("windowp", Fwindowp, 1, 1, 0, /*
1087 Return t if OBJECT is a window.
1091 return WINDOWP(object) ? Qt : Qnil;
1094 DEFUN("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1095 Return t if OBJECT is a window which is currently visible.
1099 return WINDOWP(object) && WINDOW_LIVE_P(XWINDOW(object))
1103 DEFUN("selected-window", Fselected_window, 0, 1, 0, /*
1104 Return the window that the cursor now appears in and commands apply
1105 to. If the optional argument CON-DEV-OR-FRAME is specified and is a
1106 frame, return the selected window used by that frame. If
1107 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1108 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1109 that console's selected device will be used. Otherwise, the selected
1114 if (NILP(con_dev_or_frame) && NILP(Fselected_device(Qnil)))
1115 return Qnil; /* happens at startup */
1118 struct frame *f = decode_frame_or_selected(con_dev_or_frame);
1119 return FRAME_SELECTED_WINDOW(f);
1123 DEFUN("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1124 Return the last selected window that is not a minibuffer window.
1125 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1126 return the last non-minibuffer window used by that frame. If
1127 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1128 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1129 that console's selected device will be used. Otherwise, the selected
1134 if (NILP(con_dev_or_frame) && NILP(Fselected_device(Qnil)))
1135 return Qnil; /* happens at startup */
1138 struct frame *f = decode_frame_or_selected(con_dev_or_frame);
1139 return FRAME_LAST_NONMINIBUF_WINDOW(f);
1143 DEFUN("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1144 Return the window used now for minibuffers.
1145 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1146 return the minibuffer window used by that frame. If CON-DEV-OR-FRAME
1147 is a device, then the selected frame on that device will be used. If
1148 CON-DEV-OR-FRAME is a console, the selected frame on that console's
1149 selected device will be used. Otherwise, the selected frame is used.
1153 return FRAME_MINIBUF_WINDOW(decode_frame_or_selected(con_dev_or_frame));
1156 DEFUN("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1157 Return non-nil if WINDOW is a minibuffer window.
1161 return MINI_WINDOW_P(decode_window(window)) ? Qt : Qnil;
1164 DEFUN("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1165 Return the first horizontal child of WINDOW, or nil.
1169 return decode_window(window)->hchild;
1172 DEFUN("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1173 Return the first vertical child of WINDOW, or nil.
1177 return decode_window(window)->vchild;
1180 DEFUN("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1181 Return the next window on the same level as WINDOW, or nil.
1185 return decode_window(window)->next;
1188 DEFUN("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1189 Return the previous window on the same level as WINDOW, or nil.
1193 return decode_window(window)->prev;
1196 DEFUN("window-parent", Fwindow_parent, 1, 1, 0, /*
1197 Return the parent of WINDOW, or nil.
1201 return decode_window(window)->parent;
1204 DEFUN("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1205 Return non-nil if WINDOW is along the bottom of its frame.
1209 return window_is_lowest(decode_window(window)) ? Qt : Qnil;
1212 DEFUN("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1213 Return non-nil if WINDOW is along the top of its frame.
1217 return window_is_highest(decode_window(window)) ? Qt : Qnil;
1220 DEFUN("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1221 Return non-nil if WINDOW is along the left edge of its frame.
1225 return window_is_leftmost(decode_window(window)) ? Qt : Qnil;
1228 DEFUN("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1229 Return non-nil if WINDOW is along the right edge of its frame.
1233 return window_is_rightmost(decode_window(window)) ? Qt : Qnil;
1236 DEFUN("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1237 Return t if position POS is currently on the frame in WINDOW.
1238 Returns nil if that position is scrolled vertically out of view. POS
1239 defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1243 struct window *w = decode_window(window);
1244 Bufpos top = marker_position(w->start[CURRENT_DISP]);
1246 struct buffer *buf = XBUFFER(w->buffer);
1249 posint = BUF_PT(buf);
1251 CHECK_INT_COERCE_MARKER(pos);
1255 if (posint < top || posint > BUF_ZV(buf))
1258 /* w->start can be out of range. If it is, do something reasonable. */
1259 if (top < BUF_BEGV(buf) || top > BUF_ZV(buf))
1262 return point_would_be_visible(w, top, posint) ? Qt : Qnil;
1265 struct window *decode_window(Lisp_Object window)
1268 Lisp_Object tmp = Fselected_window(Qnil);
1269 return XWINDOW(tmp);
1271 CHECK_LIVE_WINDOW(window);
1272 return XWINDOW(window);
1275 DEFUN("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1276 Return the buffer that WINDOW is displaying.
1280 return decode_window(window)->buffer;
1283 DEFUN("window-frame", Fwindow_frame, 0, 1, 0, /*
1284 Return the frame that window WINDOW is on.
1288 return decode_window(window)->frame;
1291 DEFUN("window-height", Fwindow_height, 0, 1, 0, /*
1292 Return the number of default lines in WINDOW.
1293 This actually works by dividing the window's pixel height (including
1294 the modeline and horizontal scrollbar, if any) by the height of the
1295 default font; therefore, the number of displayed lines will probably
1298 Use `window-height' to get consistent results in geometry calculations.
1299 Use `window-displayed-height' to get the actual number of lines
1300 currently displayed in a window.
1302 The names are somewhat confusing; here's a table to help out:
1305 ---------------------------------------------------------------------
1307 (rows/columns) window-width window-text-area-height
1308 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1311 (rows/columns) window-full-width window-height
1312 (pixels) window-pixel-width window-pixel-height
1315 (rows/columns) ---- window-displayed-height
1316 (pixels) ---- window-displayed-text-pixel-height
1320 return make_int(window_char_height(decode_window(window), 1));
1323 DEFUN("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1324 Return the number of lines currently displayed in WINDOW.
1325 This counts the actual number of lines displayed in WINDOW
1326 \(as opposed to `window-height'). The modeline and horizontal
1327 scrollbar do not count as lines. If there is some blank space
1328 between the end of the buffer and the end of the window, this
1329 function pretends that there are lines of text in the default
1334 return make_int(window_displayed_height(decode_window(window)));
1337 DEFUN("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1338 Return the height of WINDOW in pixels. Defaults to current window.
1339 This includes the window's modeline and horizontal scrollbar (if any).
1343 return make_int(window_pixel_height(decode_window(window)));
1346 DEFUN("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1347 Return the number of default lines in the text area of WINDOW.
1348 This actually works by dividing the window's text area pixel height
1349 (i.e. excluding the modeline and horizontal scrollbar, if any) by the
1350 height of the default font; therefore, the number of displayed lines
1351 will probably be different.
1353 See also `window-height' and `window-displayed-height'.
1357 return make_int(window_char_height(decode_window(window), 0));
1360 DEFUN("window-text-area-pixel-height", Fwindow_text_area_pixel_height, 0, 1, 0, /*
1361 Return the height in pixels of the text-displaying portion of WINDOW.
1362 Unlike `window-pixel-height', the space occupied by the modeline and
1363 horizontal scrollbar, if any, is not counted.
1367 struct window *w = decode_window(window);
1369 return make_int(WINDOW_TEXT_HEIGHT(w));
1372 DEFUN("window-displayed-text-pixel-height", Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1373 Return the height in pixels of the text displayed in WINDOW.
1374 Unlike `window-text-area-pixel-height', any blank space below the
1375 end of the buffer is not included. If optional argument NOCLIPPED
1376 is non-nil, do not include space occupied by clipped lines.
1378 (window, noclipped))
1381 Bufpos start, eobuf;
1383 int hlimit, height, prev_height = -1;
1387 line_start_cache_dynarr *cache;
1390 window = Fselected_window(Qnil);
1392 CHECK_LIVE_WINDOW(window);
1393 w = XWINDOW(window);
1395 start = marker_position(w->start[CURRENT_DISP]);
1396 hlimit = WINDOW_TEXT_HEIGHT(w);
1397 eobuf = BUF_ZV(XBUFFER(w->buffer));
1399 default_face_height_and_width(window, &defheight, NULL);
1401 /* guess lines needed in line start cache + a few extra */
1402 needed = (hlimit + defheight - 1) / defheight + 3;
1405 elt = point_in_line_start_cache(w, start, needed);
1406 assert(elt >= 0); /* in the cache */
1408 cache = w->line_start_cache;
1409 nelt = Dynarr_length(cache);
1412 for (i = elt; i < nelt; i++) {
1413 line = Dynarr_atp(cache, i)->height;
1415 if (height + line > hlimit)
1416 return make_int(!NILP(noclipped) ? height :
1421 if (height == hlimit
1422 || Dynarr_atp(cache, i)->end >= eobuf)
1423 return make_int(height);
1426 /* get here => need more cache lines. try again. */
1427 assert(height > prev_height); /* progress? */
1428 prev_height = height;
1432 needed += ((hlimit - height) *
1434 height - 1) / height;
1437 RETURN_NOT_REACHED(make_int(0)) /* shut up compiler */
1440 DEFUN("window-width", Fwindow_width, 0, 1, 0, /*
1441 Return the number of display columns in WINDOW.
1442 This is the width that is usable columns available for text in WINDOW,
1443 and does not include vertical scrollbars, dividers, or the like. See also
1444 `window-full-width' and `window-height'.
1448 return make_int(window_char_width(decode_window(window), 0));
1451 DEFUN("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1452 Return the total number of columns in WINDOW.
1453 This is like `window-width' but includes vertical scrollbars, dividers,
1458 return make_int(window_char_width(decode_window(window), 1));
1461 DEFUN("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1462 Return the width of WINDOW in pixels. Defaults to current window.
1466 return make_int(decode_window(window)->pixel_width);
1469 DEFUN("window-text-area-pixel-width", Fwindow_text_area_pixel_width, 0, 1, 0, /*
1470 Return the width in pixels of the text-displaying portion of WINDOW.
1471 Unlike `window-pixel-width', the space occupied by the vertical
1472 scrollbar or divider, if any, is not counted.
1476 struct window *w = decode_window(window);
1478 return make_int(WINDOW_TEXT_WIDTH(w));
1481 DEFUN("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1482 Return the number of columns by which WINDOW is scrolled from left margin.
1486 return make_int(decode_window(window)->hscroll);
1489 DEFUN("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1490 Return the horizontal scrolling amount of WINDOW's modeline.
1491 If the window has no modeline, return nil.
1495 struct window *w = decode_window(window);
1497 return (WINDOW_HAS_MODELINE_P(w)) ? make_int((int)w->modeline_hscroll) :
1501 DEFUN("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1502 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1503 If NCOL is negative, it will silently be forced to 0.
1504 If the window has no modeline, return nil. Otherwise, return the actual
1509 struct window *w = decode_window(window);
1511 if (WINDOW_HAS_MODELINE_P(w)) {
1515 ncols = (XINT(ncol) <= 0) ? 0 : (Charcount) XINT(ncol);
1516 if (ncols != w->modeline_hscroll) {
1517 MARK_MODELINE_CHANGED;
1518 w->modeline_hscroll = ncols;
1520 return make_int((int)ncols);
1526 DEFUN("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1527 Set number of columns WINDOW is scrolled from left margin to NCOL.
1528 NCOL should be zero or positive.
1539 w = decode_window(window);
1540 if (w->hscroll != ncols)
1541 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1546 #if 0 /* bogus FSF crock */
1548 xxDEFUN("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1549 Return WINDOW's redisplay end trigger value.
1550 See `set-window-redisplay-end-trigger' for more information.
1554 return decode_window(window)->redisplay_end_trigger;
1557 xxDEFUN("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1558 Set WINDOW's redisplay end trigger value to VALUE.
1559 VALUE should be a buffer position (typically a marker) or nil.
1560 If it is a buffer position, then if redisplay in WINDOW reaches a position
1561 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1562 with two arguments: WINDOW, and the end trigger value.
1563 Afterwards the end-trigger value is reset to nil.
1567 return (decode_window(window)->redisplay_end_trigger = value);
1572 DEFUN("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1573 Return a list of the pixel edge coordinates of WINDOW.
1574 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1575 all relative to 0, 0 at the top left corner of WINDOW's frame.
1576 The frame toolbars, menubars and gutters are considered to be outside
1577 of this area, while the scrollbars are considered to be inside.
1581 struct window *w = decode_window(window);
1582 struct frame *f = XFRAME(w->frame);
1585 w->pixel_left - FRAME_LEFT_BORDER_END(f) -
1586 FRAME_LEFT_GUTTER_BOUNDS(f);
1588 w->pixel_top - FRAME_TOP_BORDER_END(f) - FRAME_TOP_GUTTER_BOUNDS(f);
1590 return list4(make_int(left),
1592 make_int(left + w->pixel_width),
1593 make_int(top + w->pixel_height));
1596 DEFUN("window-text-area-pixel-edges", Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1597 Return a list of the pixel edge coordinates of the text area of WINDOW.
1598 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1599 all relative to 0, 0 at the top left corner of the total area allocated
1600 to the window, which includes the scrollbars.
1604 struct window *w = decode_window(window);
1606 int left = window_left_gutter_width(w, /* modeline = */ 0);
1607 int top = window_top_gutter_height(w);
1608 int right = WINDOW_WIDTH(w) - window_right_gutter_width(w, 0);
1609 int bottom = WINDOW_HEIGHT(w) - window_bottom_gutter_height(w);
1611 return list4(make_int(left),
1612 make_int(top), make_int(right), make_int(bottom));
1615 DEFUN("window-point", Fwindow_point, 0, 1, 0, /*
1616 Return current value of point in WINDOW.
1617 For a non-selected window, this is the value point would have
1618 if that window were selected.
1620 Note that, when WINDOW is the selected window and its buffer
1621 is also currently selected, the value returned is the same as (point).
1622 It would be more strictly correct to return the `top-level' value
1623 of point, outside of any save-excursion forms.
1624 But that value is hard to find.
1628 struct window *w = decode_window(window);
1629 Lisp_Object tmp_win = Fselected_window(XFRAME(w->frame)->device);
1631 /* The special check for current buffer is necessary for this
1632 function to work as defined when called within an excursion. */
1633 if (w == XWINDOW(tmp_win)
1634 && current_buffer == XBUFFER(w->buffer)) {
1635 return Fpoint(Qnil);
1637 return Fmarker_position(w->pointm[CURRENT_DISP]);
1640 DEFUN("window-start", Fwindow_start, 0, 1, 0, /*
1641 Return position at which display currently starts in WINDOW.
1642 This is updated by redisplay or by calling `set-window-start'.
1646 return Fmarker_position(decode_window(window)->start[CURRENT_DISP]);
1649 DEFUN("window-end", Fwindow_end, 0, 2, 0, /*
1650 Return position at which display currently ends in WINDOW.
1651 This is updated by redisplay, when it runs to completion.
1652 Simply changing the buffer text or setting `window-start' does not
1653 update this value. WINDOW defaults to the selected window.
1655 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1656 to be the same value as this function would return at the end of the
1657 next full redisplay assuming nothing else changes in the meantime.
1658 This function is potentially much slower with this flag set.
1660 (window, guarantee))
1662 struct window *w = decode_window(window);
1664 if (NILP(guarantee)) {
1668 return make_int(BUF_Z(XBUFFER(buf)) -
1669 w->window_end_pos[CURRENT_DISP]);
1671 Bufpos startp = marker_position(w->start[CURRENT_DISP]);
1672 return make_int(end_of_last_line(w, startp));
1676 DEFUN("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1677 Return pixel height of visible part of last window line if it is clipped.
1678 If the last line is not clipped, return nil.
1682 struct window *w = decode_window(window);
1683 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
1684 int num_lines = Dynarr_length(dla);
1685 struct display_line *dl;
1687 /* No lines - no clipped lines */
1688 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp(dla, 0)->modeline))
1691 dl = Dynarr_atp(dla, num_lines - 1);
1695 return make_int(dl->ascent + dl->descent - dl->clip);
1698 DEFUN("set-window-point", Fset_window_point, 2, 2, 0, /*
1699 Make point value in WINDOW be at position POS in WINDOW's buffer.
1703 struct window *w = decode_window(window);
1704 Lisp_Object tmp_win;
1706 CHECK_INT_COERCE_MARKER(pos);
1708 tmp_win = Fselected_window(Qnil);
1709 if (w == XWINDOW(tmp_win)) {
1710 Fgoto_char(pos, Qnil);
1712 set_marker_restricted(w->pointm[CURRENT_DISP], pos, w->buffer);
1718 DEFUN("set-window-start", Fset_window_start, 2, 3, 0, /*
1719 Make display in WINDOW start at position POS in WINDOW's buffer.
1720 Optional third arg NOFORCE non-nil inhibits next redisplay
1721 from overriding motion of point in order to display at this exact start.
1723 (window, pos, noforce))
1725 struct window *w = decode_window(window);
1727 CHECK_INT_COERCE_MARKER(pos);
1728 set_marker_restricted(w->start[CURRENT_DISP], pos, w->buffer);
1729 /* this is not right, but much easier than doing what is right. */
1730 /* w->start_at_line_beg = 0; */
1731 /* WTF is the above supposed to mean? GE */
1732 w->start_at_line_beg = beginning_of_line_p(XBUFFER(w->buffer),
1738 w->redo_modeline = 1;
1739 SET_LAST_MODIFIED(w, 0);
1740 SET_LAST_FACECHANGE(w);
1742 MARK_WINDOWS_CHANGED(w);
1747 DEFUN("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1748 Return WINDOW's dedicated object, usually t or nil.
1749 See also `set-window-dedicated-p'.
1753 return decode_window(window)->dedicated;
1756 DEFUN("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1757 Control whether WINDOW is dedicated to the buffer it displays.
1758 If it is dedicated, Emacs will not automatically change
1759 which buffer appears in it.
1760 The second argument is the new value for the dedication flag;
1765 struct window *w = decode_window(window);
1767 w->dedicated = NILP(arg) ? Qnil : Qt;
1769 return w->dedicated;
1772 /* FSFmacs has window-display-table here. We have display table as a
1775 /* Record info on buffer window w is displaying
1776 when it is about to cease to display that buffer. */
1777 static void unshow_buffer(struct window *w)
1779 Lisp_Object buf = w->buffer;
1781 if (XBUFFER(buf) != XMARKER(w->pointm[CURRENT_DISP])->buffer)
1784 /* FSF disables this check, so I'll do it too. I hope it won't
1785 break things. --ben */
1787 if (w == XWINDOW(Fselected_window(Qnil))
1788 || !EQ(buf, XWINDOW(Fselected_window(Qnil))->buffer))
1789 /* Do this except when the selected window's buffer
1790 is being removed from some other window. */
1792 /* last_window_start records the start position that this buffer
1793 had in the last window to be disconnected from it. Now that
1794 this statement is unconditional, it is possible for the
1795 buffer to be displayed in the selected window, while
1796 last_window_start reflects another window which was recently
1797 showing the same buffer. Some people might say that might be
1798 a good thing. Let's see. */
1799 XBUFFER(buf)->last_window_start =
1800 marker_position(w->start[CURRENT_DISP]);
1802 /* Point in the selected window's buffer is actually stored in that
1803 buffer, and the window's pointm isn't used. So don't clobber point
1806 Lisp_Object tmp = Fselected_window(Qnil);
1807 if (!EQ(buf, XWINDOW(tmp)->buffer)) {
1808 struct buffer *b = XBUFFER(buf);
1809 BUF_SET_PT(b, bufpos_clip_to_bounds(
1812 w->pointm[CURRENT_DISP]),
1818 /* Put REPLACEMENT into the window structure in place of OLD. */
1819 static void replace_window(Lisp_Object old, Lisp_Object replacement)
1822 struct window *o = XWINDOW(old), *p = XWINDOW(replacement);
1824 /* If OLD is its frame's root_window, then replacement is the new
1825 root_window for that frame. */
1827 if (EQ(old, FRAME_ROOT_WINDOW(XFRAME(o->frame))))
1828 FRAME_ROOT_WINDOW(XFRAME(o->frame)) = replacement;
1830 WINDOW_LEFT(p) = WINDOW_LEFT(o);
1831 WINDOW_TOP(p) = WINDOW_TOP(o);
1832 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
1833 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
1835 p->next = tem = o->next;
1837 XWINDOW(tem)->prev = replacement;
1839 p->prev = tem = o->prev;
1841 XWINDOW(tem)->next = replacement;
1843 p->parent = tem = o->parent;
1845 if (EQ(XWINDOW(tem)->vchild, old))
1846 XWINDOW(tem)->vchild = replacement;
1847 if (EQ(XWINDOW(tem)->hchild, old))
1848 XWINDOW(tem)->hchild = replacement;
1851 /* #### Here, if replacement is a vertical combination
1852 and so is its new parent, we should make replacement's
1853 children be children of that parent instead. */
1855 ERROR_CHECK_SUBWINDOW_CACHE(p);
1858 static void window_unmap_subwindows(struct window *w)
1860 assert(!NILP(w->subwindow_instance_cache));
1861 elisp_maphash(unmap_subwindow_instance_cache_mapper,
1862 w->subwindow_instance_cache, (void *)1);
1865 /* we're deleting W; set the structure of W to indicate this. */
1867 static void mark_window_as_deleted(struct window *w)
1869 /* The window instance cache is going away now, so need to get the
1870 cachels reset by redisplay. */
1871 MARK_FRAME_SUBWINDOWS_CHANGED(XFRAME(WINDOW_FRAME(w)));
1873 /* The cache is going away. If we leave unmapping to
1874 reset_subwindow_cachels then we get in a situation where the
1875 domain (the window) has been deleted but we still need access to
1876 its attributes in order to unmap windows properly. Since the
1877 subwindows are going to get GC'd anyway as a result of the domain
1878 going away, it is safer to just unmap them all while we know the
1879 domain is still valid. */
1880 ERROR_CHECK_SUBWINDOW_CACHE(w);
1881 window_unmap_subwindows(w);
1884 (while t (split-window) (delete-window))
1885 we end up with a tree of deleted windows which are all connected
1886 through the `next' slot. This might not seem so bad, as they're
1887 deleted, and will presumably be GCed - but if even *one* of those
1888 windows is still being pointed to, by the user, or by a window
1889 configuration, then *all* of those windows stick around.
1891 Since the window-configuration code doesn't need any of the
1892 pointers to other windows (they are all recreated from the
1893 window-config data), we set them all to nil so that we
1894 are able to collect more actual garbage. */
1900 w->subwindow_instance_cache = Qnil;
1904 /* Free the extra data structures attached to windows immediately so
1905 they don't sit around consuming excess space. They will be
1906 reinitialized by the window-configuration code as necessary. */
1907 finalize_window((void *)w, 0);
1910 DEFUN("delete-window", Fdelete_window, 0, 2, "", /*
1911 Remove WINDOW from the display. Default is selected window.
1912 If window is the only one on its frame, the frame is deleted as well.
1913 Normally, you cannot delete the last non-minibuffer-only frame (you
1914 must use `save-buffers-kill-emacs' or `kill-emacs'). However, if
1915 optional second argument FORCE is non-nil, you can delete the last
1916 frame. (This will automatically call `save-buffers-kill-emacs'.)
1921 /* This function can GC if this is the only window in the frame */
1929 /* Note: this function is called by other C code on non-leaf
1932 /* Do the equivalent of decode_window() but don't error out on
1933 deleted window; it's OK to delete an already-deleted window. */
1935 window = Fselected_window(Qnil);
1937 CHECK_WINDOW(window);
1939 w = XWINDOW(window);
1941 /* It's okay to delete an already-deleted window. */
1942 if (!WINDOW_LIVE_P(w))
1945 frame = WINDOW_FRAME(w);
1947 d = XDEVICE(FRAME_DEVICE(f));
1949 if (TOP_LEVEL_WINDOW_P(w)) {
1950 if (NILP(memq_no_quit(frame, DEVICE_FRAME_LIST(d))))
1951 /* this frame isn't fully initialized yet; don't blow up. */
1954 if (MINI_WINDOW_P(XWINDOW(window)))
1955 error("Attempt to delete the minibuffer window");
1957 /* It has been suggested that it's a good thing for C-x 0 to have this
1958 behavior, but not such a good idea for #'delete-window to have it.
1959 Maybe C-x 0 should be bound to something else, or maybe frame
1960 deletion should only happen when this is called interactively.
1962 delete_frame_internal(f, !NILP(force), 0, 0);
1966 /* At this point, we know the window has a parent. */
1968 par = XWINDOW(parent);
1970 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1971 /* It's quite likely that deleting a window will result in
1972 subwindows needing to be deleted also (since they are cached
1973 per-window). So we mark them as changed, so that the cachels will
1974 get reset by redisplay and thus deleted subwindows can get
1976 MARK_FRAME_SUBWINDOWS_CHANGED(f);
1978 /* Are we trying to delete any frame's selected window?
1979 Note that we could be dealing with a non-leaf window
1980 where the selected window is one of our children.
1981 So, we check by scanning all the ancestors of the
1982 frame's selected window and comparing each one with
1985 Lisp_Object pwindow;
1987 pwindow = FRAME_SELECTED_WINDOW(f);
1989 while (!NILP(pwindow)) {
1990 if (EQ(window, pwindow))
1992 pwindow = XWINDOW(pwindow)->parent;
1995 if (EQ(window, pwindow)) {
1996 /* OK, we found it. */
1997 Lisp_Object alternative;
1998 alternative = Fnext_window(window, Qlambda, Qnil, Qnil);
2000 /* If we're about to delete the selected window on the
2001 selected frame, then we should use Fselect_window to select
2002 the new window. On the other hand, if we're about to
2003 delete the selected window on any other frame, we shouldn't do
2004 anything but set the frame's selected_window slot. */
2005 if (EQ(frame, Fselected_frame(Qnil)))
2006 Fselect_window(alternative, Qnil);
2008 set_frame_selected_window(f, alternative);
2012 /* w->buffer is nil in a non-leaf window; in this case,
2013 get rid of the markers we maintain that point into that buffer. */
2014 if (!NILP(w->buffer)) {
2016 unchain_marker(w->pointm[CURRENT_DISP]);
2017 unchain_marker(w->pointm[DESIRED_DISP]);
2018 unchain_marker(w->pointm[CMOTION_DISP]);
2019 unchain_marker(w->start[CURRENT_DISP]);
2020 unchain_marker(w->start[DESIRED_DISP]);
2021 unchain_marker(w->start[CMOTION_DISP]);
2022 unchain_marker(w->sb_point);
2023 /* This breaks set-window-configuration if windows in the saved
2024 configuration get deleted and multiple frames are in use. */
2025 /* w->buffer = Qnil; */
2028 /* close up the hole in the sibling list */
2030 XWINDOW(w->next)->prev = w->prev;
2032 XWINDOW(w->prev)->next = w->next;
2033 if (EQ(window, par->hchild))
2034 par->hchild = w->next;
2035 if (EQ(window, par->vchild))
2036 par->vchild = w->next;
2038 /* Find one of our siblings to give our space to. */
2040 Lisp_Object sib = w->prev;
2042 /* If w gives its space to its next sibling, that sibling needs
2043 to have its top/left side pulled back to where w's is.
2044 set_window_{height,width} will re-position the sibling's
2047 WINDOW_TOP(XWINDOW(sib)) = WINDOW_TOP(w);
2048 WINDOW_LEFT(XWINDOW(sib)) = WINDOW_LEFT(w);
2051 /* Stretch that sibling. */
2052 if (!NILP(par->vchild))
2053 set_window_pixheight
2055 (WINDOW_HEIGHT(XWINDOW(sib)) + WINDOW_HEIGHT(w)),
2057 if (!NILP(par->hchild))
2060 (WINDOW_WIDTH(XWINDOW(sib)) + WINDOW_WIDTH(w)), 1);
2063 run_window_configuration_hook( sib );
2067 /* If parent now has only one child,
2068 put the child into the parent's place. */
2070 Lisp_Object parchild = par->hchild;
2072 parchild = par->vchild;
2073 if (NILP(XWINDOW(parchild)->next)) {
2074 replace_window(parent, parchild);
2075 mark_window_as_deleted(XWINDOW(parent));
2079 /* Since we may be deleting combination windows, we must make sure that
2080 not only W but all its children have been marked as deleted. */
2081 if (!NILP(w->hchild))
2082 delete_all_subwindows(XWINDOW(w->hchild));
2083 else if (!NILP(w->vchild))
2084 delete_all_subwindows(XWINDOW(w->vchild));
2086 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and
2087 therefore redisplay, so it requires the mirror structure to be
2088 correct. We must dirty the mirror before it is called. */
2089 f->mirror_dirty = 1;
2091 mark_window_as_deleted(w);
2096 DEFUN("next-window", Fnext_window, 0, 4, 0, /*
2097 Return the next window after WINDOW in the canonical ordering of windows.
2098 If omitted, WINDOW defaults to the selected window.
2100 Optional second arg MINIBUF t means count the minibuffer window even
2101 if not active. MINIBUF nil or omitted means count the minibuffer iff
2102 it is active. MINIBUF neither t nor nil means not to count the
2103 minibuffer even if it is active.
2105 Several frames may share a single minibuffer; if the minibuffer
2106 counts, all windows on all frames that share that minibuffer count
2107 too. Therefore, `next-window' can be used to iterate through the
2108 set of windows even when the minibuffer is on another frame. If the
2109 minibuffer does not count, only windows from WINDOW's frame count.
2111 By default, only the windows in the selected frame are considered.
2112 The optional argument WHICH-FRAMES changes this behavior:
2113 WHICH-FRAMES = `visible' means search windows on all visible frames.
2114 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2115 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2116 WHICH-FRAMES = a frame means search only windows on that frame.
2117 Anything else means restrict to the selected frame.
2119 The optional fourth argument WHICH-DEVICES further clarifies on which
2120 devices to search for frames as specified by WHICH-FRAMES. This value
2121 is only meaningful if WHICH-FRAMES is non-nil.
2122 If nil or omitted, search all devices on the selected console.
2123 If a device, only search that device.
2124 If a console, search all devices on that console.
2125 If a device type, search all devices of that type.
2126 If `window-system', search all window-system devices.
2127 Any other non-nil value means search all devices.
2129 If you use consistent values for MINIBUF, WHICH-FRAMES, and
2130 WHICH-DEVICES, you can use `next-window' to iterate through the entire
2131 cycle of acceptable windows, eventually ending up back at the window
2132 you started with. `previous-window' traverses the same cycle, in the
2135 (window, minibuf, which_frames, which_devices))
2138 Lisp_Object start_window;
2141 window = Fselected_window(Qnil);
2143 CHECK_LIVE_WINDOW(window);
2145 start_window = window;
2147 /* minibuf == nil may or may not include minibuffers.
2148 Decide if it does. */
2150 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2151 else if (!EQ(minibuf, Qt))
2153 /* Now `minibuf' is one of:
2154 t => count all minibuffer windows
2155 lambda => count none of them
2156 or a specific minibuffer window (the active one) to count. */
2158 /* which_frames == nil doesn't specify which frames to include. */
2159 if (NILP(which_frames))
2160 which_frames = (!EQ(minibuf, Qlambda)
2161 ? (FRAME_MINIBUF_WINDOW
2162 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2164 else if (EQ(which_frames, Qvisible)) ;
2165 else if (ZEROP(which_frames)) ;
2166 else if (FRAMEP(which_frames)
2167 && !EQ(which_frames, Fwindow_frame(window)))
2168 /* If which_frames is a frame and window arg isn't on that frame, just
2169 return the first window on the frame. */
2170 return frame_first_window(XFRAME(which_frames));
2171 else if (!EQ(which_frames, Qt))
2172 which_frames = Qnil;
2173 /* Now `which_frames' is one of:
2174 t => search all frames
2175 nil => search just the current frame
2176 visible => search just visible frames
2177 0 => search visible and iconified frames
2178 a window => search the frame that window belongs to. */
2180 /* Do this loop at least once, to get the next window, and perhaps
2181 again, if we hit the minibuffer and that is not acceptable. */
2183 /* Find a window that actually has a next one. This loop
2184 climbs up the tree. */
2185 while (tem = XWINDOW(window)->next, NILP(tem))
2186 if (tem = XWINDOW(window)->parent, !NILP(tem))
2188 else { /* window must be minibuffer window now */
2190 /* We've reached the end of this frame.
2191 Which other frames are acceptable? */
2192 tem = WINDOW_FRAME(XWINDOW(window));
2194 if (!NILP(which_frames)) {
2195 Lisp_Object tem1 = tem;
2197 next_frame(tem, which_frames,
2200 /* In the case where the minibuffer is active,
2201 and we include its frame as well as the selected one,
2202 next_frame may get stuck in that frame.
2203 If that happens, go back to the selected frame
2204 so we can complete the cycle. */
2210 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2216 /* If we're in a combination window, find its first child and
2217 recurse on that. Otherwise, we've found the window we want. */
2219 if (!NILP(XWINDOW(window)->hchild))
2220 window = XWINDOW(window)->hchild;
2221 else if (!NILP(XWINDOW(window)->vchild))
2222 window = XWINDOW(window)->vchild;
2227 /* Which windows are acceptable?
2228 Exit the loop and accept this window if
2229 this isn't a minibuffer window,
2230 or we're accepting all minibuffer windows,
2231 or this is the active minibuffer and we are accepting that one, or
2232 we've come all the way around and we're back at the original window. */
2233 while (MINI_WINDOW_P(XWINDOW(window))
2235 && !EQ(minibuf, window)
2236 && !EQ(window, start_window));
2241 DEFUN("previous-window", Fprevious_window, 0, 4, 0, /*
2242 Return the window preceding WINDOW in the canonical ordering of windows.
2243 If omitted, WINDOW defaults to the selected window.
2245 Optional second arg MINIBUF t means count the minibuffer window even
2246 if not active. MINIBUF nil or omitted means count the minibuffer iff
2247 it is active. MINIBUF neither t nor nil means not to count the
2248 minibuffer even if it is active.
2250 Several frames may share a single minibuffer; if the minibuffer
2251 counts, all windows on all frames that share that minibuffer count
2252 too. Therefore, `previous-window' can be used to iterate through
2253 the set of windows even when the minibuffer is on another frame. If
2254 the minibuffer does not count, only windows from WINDOW's frame count.
2256 By default, only the windows in the selected frame are considered.
2257 The optional argument WHICH-FRAMES changes this behavior:
2258 WHICH-FRAMES = `visible' means search windows on all visible frames.
2259 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2260 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2261 WHICH-FRAMES = a frame means search only windows on that frame.
2262 Anything else means restrict to the selected frame.
2264 The optional fourth argument WHICH-DEVICES further clarifies on which
2265 devices to search for frames as specified by WHICH-FRAMES. This value
2266 is only meaningful if WHICH-FRAMES is non-nil.
2267 If nil or omitted, search all devices on the selected console.
2268 If a device, only search that device.
2269 If a console, search all devices on that console.
2270 If a device type, search all devices of that type.
2271 If `window-system', search all window-system devices.
2272 Any other non-nil value means search all devices.
2274 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2275 you can use `previous-window' to iterate through the entire cycle of
2276 acceptable windows, eventually ending up back at the window you started with.
2277 `next-window' traverses the same cycle, in the reverse order.
2279 (window, minibuf, which_frames, devices))
2282 Lisp_Object start_window;
2285 window = Fselected_window(Qnil);
2287 CHECK_LIVE_WINDOW(window);
2289 start_window = window;
2291 /* minibuf == nil may or may not include minibuffers.
2292 Decide if it does. */
2294 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2295 else if (!EQ(minibuf, Qt))
2297 /* Now `minibuf' is one of:
2298 t => count all minibuffer windows
2299 lambda => count none of them
2300 or a specific minibuffer window (the active one) to count. */
2302 /* which_frames == nil doesn't specify which frames to include.
2303 Decide which frames it includes. */
2304 if (NILP(which_frames))
2305 which_frames = (!EQ(minibuf, Qlambda)
2306 ? (FRAME_MINIBUF_WINDOW
2307 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2309 else if (EQ(which_frames, Qvisible)) ;
2310 else if (ZEROP(which_frames)) ;
2311 else if (FRAMEP(which_frames)
2312 && !EQ(which_frames, Fwindow_frame(window)))
2313 /* If which_frames is a frame and window arg isn't on that frame, just
2314 return the first window on the frame. */
2315 return frame_first_window(XFRAME(which_frames));
2316 else if (!EQ(which_frames, Qt))
2317 which_frames = Qnil;
2318 /* Now `which_frames' is one of:
2319 t => search all frames
2320 nil => search just the current frame
2321 visible => search just visible frames
2322 0 => search visible and iconified frames
2323 a window => search the frame that window belongs to. */
2325 /* Do this loop at least once, to get the next window, and perhaps
2326 again, if we hit the minibuffer and that is not acceptable. */
2328 /* Find a window that actually has a next one. This loop
2329 climbs up the tree. */
2330 while (tem = XWINDOW(window)->prev, NILP(tem))
2331 if (tem = XWINDOW(window)->parent, !NILP(tem))
2333 else { /* window must be minibuffer window now */
2335 /* We have found the top window on the frame.
2336 Which frames are acceptable? */
2337 tem = WINDOW_FRAME(XWINDOW(window));
2339 if (!NILP(which_frames))
2340 /* It's actually important that we use previous_frame here,
2341 rather than next_frame. All the windows acceptable
2342 according to the given parameters should form a ring;
2343 Fnext_window and Fprevious_window should go back and
2344 forth around the ring. If we use next_frame here,
2345 then Fnext_window and Fprevious_window take different
2346 paths through the set of acceptable windows.
2347 window_loop assumes that these `ring' requirement are
2350 Lisp_Object tem1 = tem;
2352 previous_frame(tem, which_frames,
2354 /* In the case where the minibuffer is active,
2355 and we include its frame as well as the selected one,
2356 next_frame may get stuck in that frame.
2357 If that happens, go back to the selected frame
2358 so we can complete the cycle. */
2364 /* If this frame has a minibuffer, find that window first,
2365 because it is conceptually the last window in that frame. */
2366 if (FRAME_HAS_MINIBUF_P(XFRAME(tem)))
2367 tem = FRAME_MINIBUF_WINDOW(XFRAME(tem));
2369 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2376 /* If we're in a combination window, find its first child and
2377 recurse on that. Otherwise, we've found the window we want. */
2379 if (!NILP(XWINDOW(window)->hchild))
2380 window = XWINDOW(window)->hchild;
2381 else if (!NILP(XWINDOW(window)->vchild))
2382 window = XWINDOW(window)->vchild;
2385 while (tem = XWINDOW(window)->next, !NILP(tem))
2389 /* Which windows are acceptable?
2390 Exit the loop and accept this window if
2391 this isn't a minibuffer window,
2392 or we're accepting all minibuffer windows,
2393 or this is the active minibuffer and we are accepting that one, or
2394 we've come all the way around and we're back at the original window. */
2395 while (MINI_WINDOW_P(XWINDOW(window))
2397 && !EQ(minibuf, window)
2398 && !EQ(window, start_window));
2403 DEFUN("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2404 Return the next window which is vertically after WINDOW.
2409 struct window *w = decode_window(window);
2410 XSETWINDOW(window, w);
2412 if (MINI_WINDOW_P(XWINDOW(window)))
2415 root = FRAME_ROOT_WINDOW(XFRAME(WINDOW_FRAME(XWINDOW(window))));
2417 if (EQ(window, root)) {
2419 if (!NILP(XWINDOW(window)->hchild))
2420 window = XWINDOW(window)->hchild;
2421 else if (!NILP(XWINDOW(window)->vchild))
2422 window = XWINDOW(window)->vchild;
2428 if (!NILP(XWINDOW(window)->parent) &&
2429 !NILP(XWINDOW(XWINDOW(window)->parent)->vchild)) {
2430 if (!NILP(XWINDOW(window)->next))
2431 return XWINDOW(window)->next;
2433 window = XWINDOW(window)->parent;
2435 window = XWINDOW(window)->parent;
2437 while (!EQ(window, root));
2440 if (!NILP(XWINDOW(window)->hchild))
2441 window = XWINDOW(window)->hchild;
2442 else if (!NILP(XWINDOW(window)->vchild))
2443 window = XWINDOW(window)->vchild;
2448 DEFUN("other-window", Fother_window, 1, 3, "p", /*
2449 Select the COUNT'th different window on this frame.
2450 All windows on current frame are arranged in a cyclic order.
2451 This command selects the window COUNT steps away in that order.
2452 A negative COUNT moves in the opposite order.
2454 By default, only the windows in the selected frame are considered.
2455 The optional argument WHICH-FRAMES changes this behavior:
2456 WHICH-FRAMES = `visible' means search windows on all visible frames.
2457 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2458 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2459 WHICH-FRAMES = a frame means search only windows on that frame.
2460 Anything else means restrict to the selected frame.
2462 The optional argument WHICH-DEVICES further clarifies on which devices
2463 to search for frames as specified by WHICH-FRAMES. This value is only
2464 meaningful if WHICH-FRAMES is non-nil.
2465 If nil or omitted, search all devices on the selected console.
2466 If a device, only search that device.
2467 If a console, search all devices on that console.
2468 If a device type, search all devices of that type.
2469 If `window-system', search all window-system devices.
2470 Any other non-nil value means search all devices.
2472 (count, which_frames, which_devices))
2478 w = Fselected_window(Qnil);
2482 w = Fnext_window(w, Qnil, which_frames, which_devices);
2486 w = Fprevious_window(w, Qnil, which_frames, which_devices);
2489 Fselect_window(w, Qnil);
2493 /* Look at all windows, performing an operation specified by TYPE
2496 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2497 frame. If FRAMES is a frame, just look at windows on that frame.
2498 If MINI is non-zero, perform the operation on minibuffer windows too.
2503 GET_BUFFER_WINDOW, /* Arg is buffer */
2504 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2505 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2506 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2507 UNDEDICATE_BUFFER, /* Arg is buffer */
2509 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2510 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2514 window_loop(enum window_loop type,
2517 Lisp_Object which_frames,
2518 int dedicated_too, Lisp_Object which_devices)
2520 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2522 Lisp_Object best_window = Qnil;
2523 Lisp_Object next_window;
2524 Lisp_Object last_window;
2525 struct frame *frame;
2526 Lisp_Object frame_arg = Qt;
2527 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2528 /* #### I think the change of "precomputing" last_window and next_window
2529 * #### catch the lossage this is meant(?) to punt on...
2532 Lisp_Object devcons, concons;
2534 /* If we're only looping through windows on a particular frame,
2535 FRAME points to that frame. If we're looping through windows
2536 on all frames, FRAME is 0. */
2537 if (FRAMEP(which_frames))
2538 frame = XFRAME(which_frames);
2539 else if (NILP(which_frames))
2540 frame = selected_frame();
2544 /* FRAME_ARG is Qlambda to stick to one frame,
2545 Qvisible to consider all visible frames,
2548 frame_arg = Qlambda;
2549 } else if (ZEROP(which_frames)) {
2550 frame_arg = which_frames;
2551 } else if (EQ(which_frames, Qvisible)) {
2552 frame_arg = which_frames;
2555 DEVICE_LOOP_NO_BREAK(devcons, concons) {
2556 Lisp_Object device = XCAR(devcons);
2557 Lisp_Object the_frame;
2560 XSETFRAME(the_frame, frame);
2562 the_frame = DEVICE_SELECTED_FRAME(XDEVICE(device));
2564 if (NILP(the_frame))
2567 if (!device_matches_device_spec(device,
2568 NILP(which_devices) ?
2569 FRAME_CONSOLE(XFRAME(the_frame))
2573 /* Pick a window to start with. */
2577 w = FRAME_SELECTED_WINDOW(XFRAME(the_frame));
2579 /* Figure out the last window we're going to mess with. Since
2580 Fnext_window, given the same options, is guaranteed to go in a
2581 ring, we can just use Fprevious_window to find the last one.
2583 We can't just wait until we hit the first window again,
2584 because it might be deleted. */
2587 Fprevious_window(w, mini ? Qt : Qnil, frame_arg, device);
2591 struct window *p = XWINDOW(w);
2593 /* Pick the next window now, since some operations will delete
2594 the current window. */
2596 Fnext_window(w, mini ? Qt : Qnil, frame_arg,
2599 /* #### Still needed ?? */
2600 /* Given the outstanding quality of the rest of this code,
2601 I feel no shame about putting this piece of shit in. */
2602 if (++lose_lose >= 500) {
2603 /* Call to abort() added by Darryl Okahata (16 Nov. 2001),
2604 at Ben's request, to catch any remaining bugs.
2606 If you find that SXEmacs is aborting here, and you
2607 need to be up and running ASAP, it should be safe to
2608 comment out the following abort(), as long as you
2609 leave the "break;" alone. */
2611 break; /* <--- KEEP THIS HERE! Do not delete! */
2614 /* Note that we do not pay attention here to whether
2615 the frame is visible, since Fnext_window skips non-visible frames
2616 if that is desired, under the control of frame_arg. */
2617 if (!MINI_WINDOW_P(p)
2618 || (mini && minibuf_level > 0))
2620 case GET_BUFFER_WINDOW: {
2621 if (XBUFFER(p->buffer) ==
2627 case GET_BUFFER_WINDOW_COUNT: {
2628 if (XBUFFER(p->buffer) ==
2634 case GET_LRU_WINDOW: {
2635 /* t as arg means consider only
2636 full-width windows */
2638 && !window_full_width_p(p))
2640 /* Ignore dedicated windows and
2642 if (MINI_WINDOW_P(p)
2643 || (dedicated_too ? 0 :
2644 !NILP(p->dedicated)))
2646 if (NILP(best_window) ||
2647 (XINT(XWINDOW(best_window)->
2649 > XINT(p->use_time)))
2654 case GET_BUFFER_MRU_WINDOW: {
2655 /* #### what about the first check in
2657 /* Ignore dedicated windows and
2659 if (MINI_WINDOW_P(p)
2660 || (dedicated_too ? 0 :
2661 !NILP(p->dedicated)))
2664 if (XBUFFER(p->buffer) ==
2666 if (NILP(best_window)
2679 case UNDEDICATE_BUFFER: {
2680 if ((XBUFFER(p->buffer) ==
2682 p->dedicated = Qnil;
2687 case DELETE_OTHER_WINDOWS: {
2688 /* Don't delete the last window on a
2689 frame; this can happen when the
2690 minibuffer is selected, and would
2691 cause the frame to be deleted. */
2692 if (p != XWINDOW(obj) &&
2693 !TOP_LEVEL_WINDOW_P(XWINDOW (w))) {
2694 Fdelete_window(w, Qnil);
2699 case DELETE_BUFFER_WINDOWS: {
2700 if (EQ(p->buffer, obj)) {
2702 XFRAME(WINDOW_FRAME(p));
2704 /* If this window is dedicated,
2705 and in a frame of its own,
2707 if (EQ (w, FRAME_ROOT_WINDOW (f))
2708 && !NILP(p->dedicated)
2709 && (allow_deletion_of_last_visible_frame
2710 || other_visible_frames (f)))
2727 /* As we go, check for the end of the
2728 loop. We mustn't start going
2729 around a second time. */
2730 if (EQ(next_window, last_window)) {
2748 /* Now we can safely delete the frame. */
2753 /* If we're deleting the
2756 the frame, find a new
2759 if (NILP(p->parent)) {
2792 case GET_LARGEST_WINDOW: {
2793 /* Ignore dedicated windows and
2795 if (MINI_WINDOW_P(p)
2796 || (dedicated_too ? 0 :
2797 !NILP(p->dedicated)))
2800 /* write the check as follows to
2802 error_check_window() --ben */
2806 XWINDOW(best_window);
2807 if (NILP(best_window) ||
2808 ((WINDOW_HEIGHT(p) *
2810 > (WINDOW_HEIGHT(b) *
2811 WINDOW_WIDTH(b)))) {
2818 case WINDOW_LOOP_UNUSED:
2823 if (EQ(w, last_window)) {
2831 return type == GET_BUFFER_WINDOW_COUNT ? make_int(count) : best_window;
2834 #if 0 /* not currently used */
2836 int buffer_window_count(struct buffer *b, struct frame *f)
2838 Lisp_Object buffer, frame;
2840 XSETFRAME(frame, f);
2841 XSETBUFFER(buffer, b);
2843 return XINT(window_loop(GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2847 int buffer_window_mru(struct window *w)
2849 Lisp_Object window =
2850 window_loop(GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2854 else if (XWINDOW(window) == w)
2862 void undedicate_windows(Lisp_Object buffer, Lisp_Object frame)
2864 window_loop(UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2867 DEFUN("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2868 Return the window least recently selected or used for display.
2870 By default, only the windows in the selected frame are considered.
2871 The optional argument WHICH-FRAMES changes this behavior:
2872 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2873 If WHICH-FRAMES is 0, search all visible and iconified frames.
2874 If WHICH-FRAMES is t, search all frames.
2875 If WHICH-FRAMES is nil, search only the selected frame.
2876 If WHICH-FRAMES is a frame, search only that frame.
2878 The optional argument WHICH-DEVICES further clarifies on which devices
2879 to search for frames as specified by WHICH-FRAMES. This value is only
2880 meaningful if WHICH-FRAMES is non-nil.
2881 If nil or omitted, search all devices on the selected console.
2882 If a device, only search that device.
2883 If a console, search all devices on that console.
2884 If a device type, search all devices of that type.
2885 If `window-system', search all devices on window-system consoles.
2886 Any other non-nil value means search all devices.
2888 (which_frames, which_devices))
2891 /* First try for a non-dedicated window that is full-width */
2892 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2893 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2896 /* Then try for any non-dedicated window */
2897 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 0,
2899 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2903 /* FSFmacs never returns a dedicated window here. If we do,
2904 it makes `display-buffer' not work right. #### All of this
2905 shit is so disgusting and awful that it needs to be rethought
2907 /* then try for a dedicated window that is full-width */
2908 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2909 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2912 /* If none of them, then all windows, dedicated or not. */
2913 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 1,
2916 /* At this point we damn well better have found something. */
2924 DEFUN("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2925 Return the window largest in area.
2927 By default, only the windows in the selected frame are considered.
2928 The optional argument WHICH-FRAMES changes this behavior:
2929 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2930 If WHICH-FRAMES is 0, search all visible and iconified frames.
2931 If WHICH-FRAMES is t, search all frames.
2932 If WHICH-FRAMES is nil, search only the selected frame.
2933 If WHICH-FRAMES is a frame, search only that frame.
2935 The optional argument WHICH-DEVICES further clarifies on which devices
2936 to search for frames as specified by WHICH-FRAMES. This value is only
2937 meaningful if WHICH-FRAMES is non-nil.
2938 If nil or omitted, search all devices on the selected console.
2939 If a device, only search that device.
2940 If a console, search all devices on that console.
2941 If a device type, search all devices of that type.
2942 If `window-system', search all devices on window-system consoles.
2943 Any other non-nil value means search all devices.
2945 (which_frames, which_devices))
2947 /* Don't search dedicated windows because FSFmacs doesn't.
2948 This stuff is all black magic so don't try to apply common
2950 return window_loop(GET_LARGEST_WINDOW, Qnil, 0,
2951 which_frames, 0, which_devices);
2954 DEFUN("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2955 Return a window currently displaying BUFFER, or nil if none.
2957 By default, only the windows in the selected frame are considered.
2958 The optional argument WHICH-FRAMES changes this behavior:
2959 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2960 If WHICH-FRAMES is 0, search all visible and iconified frames.
2961 If WHICH-FRAMES is t, search all frames.
2962 If WHICH-FRAMES is nil, search only the selected frame.
2963 If WHICH-FRAMES is a frame, search only that frame.
2965 The optional argument WHICH-DEVICES further clarifies on which devices
2966 to search for frames as specified by WHICH-FRAMES. This value is only
2967 meaningful if WHICH-FRAMES is non-nil.
2968 If nil or omitted, search all devices on the selected console.
2969 If a device, only search that device.
2970 If a console, search all devices on that console.
2971 If a device type, search all devices of that type.
2972 If `window-system', search all devices on window-system consoles.
2973 Any other non-nil value means search all devices.
2975 (buffer, which_frames, which_devices))
2977 buffer = Fget_buffer(buffer);
2978 if (BUFFERP(buffer))
2979 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2980 return window_loop(GET_BUFFER_WINDOW, buffer, 1,
2981 which_frames, 1, which_devices);
2986 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2987 but there is no sensible way to implement those functions, since
2988 you can't in general derive a window from a buffer. */
2990 DEFUN("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width, 0, 1, 0, /*
2991 Return the width in pixels of the left outside margin of window WINDOW.
2992 If WINDOW is nil, the selected window is assumed.
2996 return make_int(window_left_margin_width(decode_window(window)));
2999 DEFUN("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width, 0, 1, 0, /*
3000 Return the width in pixels of the right outside margin of window WINDOW.
3001 If WINDOW is nil, the selected window is assumed.
3005 return make_int(window_right_margin_width(decode_window(window)));
3008 DEFUN("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
3009 Make WINDOW (or the selected window) fill its frame.
3010 Only the frame WINDOW is on is affected.
3011 This function tries to reduce display jumps
3012 by keeping the text previously visible in WINDOW
3013 in the same place on the frame. Doing this depends on
3014 the value of (window-start WINDOW), so if calling this function
3015 in a program gives strange scrolling, make sure the window-start
3016 value is reasonable when this function is called.
3021 struct window *w = decode_window(window);
3022 struct buffer *b = XBUFFER(w->buffer);
3024 int old_top = WINDOW_TOP(w);
3026 XSETWINDOW(window, w);
3028 if (MINI_WINDOW_P(w) && old_top > 0)
3029 error("Can't expand minibuffer to full frame");
3031 /* Ignore dedicated windows. */
3032 window_loop(DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3034 start_pos = marker_position(w->start[CURRENT_DISP]);
3036 /* Try to minimize scrolling, by setting the window start to the
3037 point which will cause the text at the old window start to be at
3038 the same place on the frame. But don't try to do this if the
3039 window start is outside the visible portion (as might happen when
3040 the display is not current, due to typeahead). */
3041 if (start_pos >= BUF_BEGV(b) && start_pos <= BUF_ZV(b)
3042 && !MINI_WINDOW_P(w)) {
3044 start_with_line_at_pixpos(w, start_pos, old_top);
3046 if (new_start >= BUF_BEGV(b) && new_start <= BUF_ZV(b)) {
3047 Fset_marker(w->start[CURRENT_DISP], make_int(new_start),
3049 w->start_at_line_beg =
3050 beginning_of_line_p(b, new_start);
3052 /* We need to do this, so that the window-scroll-functions
3057 run_window_configuration_hook( window );
3062 DEFUN("delete-windows-on", Fdelete_windows_on, 1, 3, "bDelete windows on (buffer): ", /*
3063 Delete all windows showing BUFFER.
3065 Optional second argument WHICH-FRAMES controls which frames are affected.
3066 If nil or omitted, delete all windows showing BUFFER in any frame.
3067 If t, delete only windows showing BUFFER in the selected frame.
3068 If `visible', delete all windows showing BUFFER in any visible frame.
3069 If a frame, delete only windows showing BUFFER in that frame.
3070 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3071 except that the meanings of nil and t are reversed.
3073 The optional third argument WHICH-DEVICES further clarifies on which
3074 devices to search for frames as specified by WHICH-FRAMES. This value
3075 is only meaningful if WHICH-FRAMES is not t.
3076 If nil or omitted, search only the selected console.
3077 If a device, only search that device.
3078 If a console, search all devices on that console.
3079 If a device type, search all devices of that type.
3080 If `window-system', search all devices on a window system.
3081 Any other non-nil value means search all devices.
3083 (buffer, which_frames, which_devices))
3085 /* This function can GC */
3086 buffer = Fget_buffer(buffer);
3087 CHECK_BUFFER(buffer);
3089 /* WHICH-FRAMES values t and nil mean the opposite of what
3090 window_loop expects. */
3091 if (EQ(which_frames, Qnil))
3093 else if (EQ(which_frames, Qt))
3094 which_frames = Qnil;
3096 /* Ignore dedicated windows. */
3097 window_loop(DELETE_BUFFER_WINDOWS, buffer, 0,
3098 which_frames, 0, which_devices);
3102 static Lisp_Object list_windows(struct window *w, Lisp_Object value)
3105 if (!NILP(w->hchild))
3106 value = list_windows(XWINDOW(w->hchild), value);
3107 else if (!NILP(w->vchild))
3108 value = list_windows(XWINDOW(w->vchild), value);
3111 XSETWINDOW(window, w);
3112 value = Fcons(window, value);
3116 w = XWINDOW(w->next);
3122 list_all_windows(Lisp_Object frame_spec, Lisp_Object device_spec)
3124 Lisp_Object devcons, concons;
3125 Lisp_Object retval = Qnil;
3127 DEVICE_LOOP_NO_BREAK(devcons, concons) {
3128 Lisp_Object frame_list, the_window;
3129 Lisp_Object device, tail;
3131 device = XCAR(devcons);
3132 frame_list = DEVICE_FRAME_LIST(XDEVICE(device));
3134 LIST_LOOP(tail, frame_list) {
3135 if ((NILP(frame_spec)
3137 DEVICE_SELECTED_FRAME(XDEVICE(device))))
3138 || (EQ(frame_spec, Qvisible)
3139 && !FRAME_VISIBLE_P(XFRAME(XCAR(tail))))
3140 || (FRAMEP(frame_spec)
3141 && !EQ(frame_spec, XCAR(tail)))
3142 || (!NILP(frame_spec)
3143 && !device_matches_device_spec(device,
3149 the_window = FRAME_ROOT_WINDOW(XFRAME(XCAR(tail)));
3150 retval = list_windows(XWINDOW(the_window), retval);
3153 return Fnreverse(retval);
3156 DEFUN("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3, "bReplace buffer in windows: ", /*
3157 Replace BUFFER with some other buffer in all windows showing it.
3159 Optional second argument WHICH-FRAMES controls which frames are affected.
3160 If nil or omitted, all frames are affected.
3161 If t, only the selected frame is affected.
3162 If `visible', all visible frames are affected.
3163 If a frame, only that frame is affected.
3164 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3165 except that the meanings of nil and t are reversed.
3167 The optional third argument WHICH-DEVICES further clarifies on which
3168 devices to search for frames as specified by WHICH-FRAMES. This value
3169 is only meaningful if WHICH-FRAMES is not t.
3170 If nil or omitted, search only the selected console.
3171 If a device, only search that device.
3172 If a console, search all devices on that console.
3173 If a device type, search all devices of that type.
3174 If `window-system', search all devices on a window system.
3175 Any other non-nil value means search all devices.
3177 (buffer, which_frames, which_devices))
3179 /* This function can GC */
3180 Lisp_Object window_list;
3182 struct gcpro gcpro1, gcpro2;
3184 if (EQ(which_frames, Qnil))
3186 else if (EQ(which_frames, Qt))
3187 which_frames = Qnil;
3188 window_list = list_all_windows(which_frames, which_devices);
3190 buffer = Fget_buffer(buffer);
3191 CHECK_BUFFER(buffer);
3193 GCPRO2(window_list, buffer);
3194 LIST_LOOP(tail, window_list) {
3195 Lisp_Object window = XCAR(tail);
3196 if (!MINI_WINDOW_P(XWINDOW(window))
3197 && EQ(XWINDOW(window)->buffer, buffer)) {
3198 Lisp_Object another_buffer =
3199 Fother_buffer(buffer, Qnil, Qnil);
3200 Lisp_Object frame = WINDOW_FRAME(XWINDOW(window));
3201 if (NILP(another_buffer))
3202 another_buffer = Fget_buffer_create(QSscratch);
3203 if (!NILP(XWINDOW(window)->dedicated)
3204 && EQ(window, FRAME_ROOT_WINDOW(XFRAME(frame)))
3205 && (allow_deletion_of_last_visible_frame
3206 || other_visible_frames (XFRAME (frame))))
3208 delete_frame_internal(XFRAME(frame), 0, 0, 0); /* GC */
3210 Fset_window_buffer(window, another_buffer,
3212 if (EQ(window, Fselected_window(Qnil)))
3213 Fset_buffer(XWINDOW(window)->buffer);
3221 /* The smallest acceptable dimensions for a window. Anything smaller
3222 might crash Emacs. */
3223 #define MIN_SAFE_WINDOW_WIDTH (2)
3224 #define MIN_SAFE_WINDOW_HEIGHT (2)
3226 /* Make sure that window_min_height and window_min_width are
3227 not too small; if they are, set them to safe minima. */
3229 static void check_min_window_sizes(void)
3231 /* Smaller values might permit a crash. */
3232 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3233 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3234 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3235 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3238 static int frame_min_height(struct frame *frame)
3240 /* For height, we have to see whether the frame has a minibuffer, and
3241 whether it wants a modeline. */
3242 return (FRAME_MINIBUF_ONLY_P(frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3243 : (!FRAME_HAS_MINIBUF_P(frame)) ? MIN_SAFE_WINDOW_HEIGHT
3244 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3247 /* Return non-zero if both frame sizes are less than or equal to
3248 minimal allowed values. ROWS and COLS are in characters */
3249 int frame_size_valid_p(struct frame *frame, int rows, int cols)
3251 return (rows >= frame_min_height(frame)
3252 && cols >= MIN_SAFE_WINDOW_WIDTH);
3255 /* Return non-zero if both frame sizes are less than or equal to
3256 minimal allowed values. WIDTH and HEIGHT are in pixels */
3257 int frame_pixsize_valid_p(struct frame *frame, int width, int height)
3260 pixel_to_real_char_size(frame, width, height, &cols, &rows);
3261 return frame_size_valid_p(frame, rows, cols);
3264 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3265 minimum allowable size. */
3266 void check_frame_size(struct frame *frame, int *rows, int *cols)
3268 int min_height = frame_min_height(frame);
3270 if (*rows < min_height)
3272 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3273 *cols = MIN_SAFE_WINDOW_WIDTH;
3276 /* Normally the window is deleted if it gets too small.
3277 nodelete nonzero means do not do this.
3278 (The caller should check later and do so if appropriate) */
3280 set_window_pixsize(Lisp_Object window, int new_pixsize, int nodelete,
3283 struct window *w = XWINDOW(window);
3284 struct frame *f = XFRAME(w->frame);
3286 int old_pixsize = (set_height ? WINDOW_HEIGHT(w) : WINDOW_WIDTH(w));
3287 Lisp_Object child, minor_kid, major_kid;
3290 int defheight, defwidth;
3292 /* #### This is very likely incorrect and instead the char_to_pixel_
3293 functions should be called. */
3294 default_face_height_and_width(window, &defheight, &defwidth);
3295 line_size = (set_height ? defheight : defwidth);
3297 check_min_window_sizes();
3299 minsize = (set_height ? window_min_height : window_min_width);
3300 minsize *= line_size;
3302 if (!nodelete && !TOP_LEVEL_WINDOW_P(w)
3303 && new_pixsize < minsize) {
3304 Fdelete_window(window, Qnil);
3308 SET_LAST_MODIFIED(w, 0);
3309 SET_LAST_FACECHANGE(w);
3310 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f); /* multiple windows affected */
3312 WINDOW_HEIGHT(w) = new_pixsize;
3313 major_kid = w->vchild;
3314 minor_kid = w->hchild;
3316 WINDOW_WIDTH(w) = new_pixsize;
3317 major_kid = w->hchild;
3318 minor_kid = w->vchild;
3321 if (!NILP(minor_kid)) {
3322 for (child = minor_kid; !NILP(child);
3323 child = XWINDOW(child)->next) {
3325 WINDOW_TOP(XWINDOW(child)) = WINDOW_TOP(w);
3327 WINDOW_LEFT(XWINDOW(child)) = WINDOW_LEFT(w);
3329 set_window_pixsize(child, new_pixsize, nodelete,
3332 } else if (!NILP(major_kid)) {
3333 int last_pos, last_old_pos, pos, old_pos, first;
3334 int pixel_adj_left = new_pixsize - old_pixsize;
3335 int div_val = old_pixsize << 1;
3338 * Previously we bailed out here if there was no size change.
3339 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3340 * toolbar appears or disappears, windows may not change size,
3341 * but their top and left coordinates need to be updated.
3343 * So we don't bail until after the loop below.
3347 (set_height ? WINDOW_TOP(w) : WINDOW_LEFT(w));
3350 for (child = major_kid; !NILP(child); child = c->next) {
3354 old_pos = last_old_pos + WINDOW_HEIGHT(c);
3355 WINDOW_TOP(c) = last_pos;
3357 old_pos = last_old_pos + WINDOW_WIDTH(c);
3358 WINDOW_LEFT(c) = last_pos;
3362 (((old_pos * new_pixsize) << 1) +
3363 old_pixsize) / div_val;
3364 /* All but the last window should have a height which is
3365 a multiple of the default line height. */
3367 pos = (pos / line_size) * line_size;
3369 /* Avoid confusion: don't delete child if it becomes too small */
3370 set_window_pixsize(child, pos + first - last_pos, 1,
3373 last_pos = pos + first;
3374 last_old_pos = old_pos;
3377 /* Sometimes we may get called with our old size. In that case
3378 we don't need to do anything else. */
3379 if (!pixel_adj_left)
3382 /* Now delete any children that became too small. */
3384 for (child = major_kid; !NILP(child);
3385 child = XWINDOW(child)->next) {
3387 set_window_pixheight(child,
3392 set_window_pixwidth(child,
3393 WINDOW_WIDTH(XWINDOW
3400 /* Set the height of WINDOW and all its inferiors. */
3401 void set_window_pixheight(Lisp_Object window, int new_pixheight, int nodelete)
3403 set_window_pixsize(window, new_pixheight, nodelete, 1);
3406 /* Recursively set width of WINDOW and its inferiors. */
3407 void set_window_pixwidth(Lisp_Object window, int new_pixwidth, int nodelete)
3409 set_window_pixsize(window, new_pixwidth, nodelete, 0);
3412 static int window_select_count;
3414 DEFUN("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3415 Make WINDOW display BUFFER as its contents.
3416 When WINDOW is nil, the `selected-window' is used.
3417 BUFFER can be a buffer or buffer name.
3419 With non-nil optional argument NORECORD, do not modify the
3420 global or per-frame buffer ordering.
3423 (window, buffer, norecord))
3426 struct window *w = decode_window(window);
3427 int old_buffer_local_face_property = 0;
3429 buffer = Fget_buffer(buffer);
3430 CHECK_BUFFER(buffer);
3432 if (!BUFFER_LIVE_P(XBUFFER(buffer)))
3433 error("Attempt to display deleted buffer");
3437 error("Window is deleted");
3439 /* While this seems like a logical thing to do, it causes problems
3440 because of saved window configurations. It is possible for a
3441 buffer to get restored into a window in which it is already being
3442 displayed, but start and point are actually at completely
3443 different locations. So we let this function complete fully and
3444 it will then make sure redisplay correctly updates things.
3446 #### This is a kludge. The correct approach is not to do this
3447 but to fix set-window-configuration. */
3449 else if (EQ(tem, buffer))
3452 else if (!EQ(tem, Qt)) { /* w->buffer is t when the window
3453 is first being set up. */
3454 if (!NILP(w->dedicated) && !EQ(tem, buffer))
3455 error("Window is dedicated to buffer %s",
3456 XSTRING_DATA(XBUFFER(tem)->name));
3458 old_buffer_local_face_property =
3459 XBUFFER(w->buffer)->buffer_local_face_property;
3464 w->window_end_pos[CURRENT_DISP] = 0;
3466 w->modeline_hscroll = 0;
3467 Fset_marker(w->pointm[CURRENT_DISP],
3468 make_int(BUF_PT(XBUFFER(buffer))), buffer);
3469 set_marker_restricted(w->start[CURRENT_DISP],
3470 make_int(XBUFFER(buffer)->last_window_start),
3472 Fset_marker(w->sb_point, w->start[CURRENT_DISP], buffer);
3473 /* set start_at_line_beg correctly. GE */
3474 w->start_at_line_beg = beginning_of_line_p(XBUFFER(buffer),
3478 w->force_start = 0; /* Lucid fix */
3479 SET_LAST_MODIFIED(w, 1);
3480 SET_LAST_FACECHANGE(w);
3481 MARK_WINDOWS_CHANGED(w);
3483 int new_buffer_local_face_property =
3484 XBUFFER(w->buffer)->buffer_local_face_property;
3486 if (new_buffer_local_face_property
3487 || new_buffer_local_face_property !=
3488 old_buffer_local_face_property)
3489 MARK_WINDOW_FACES_CHANGED(w);
3491 recompute_all_cached_specifiers_in_window(w);
3492 if (EQ(window, Fselected_window(Qnil))) {
3494 Frecord_buffer(buffer);
3496 Fset_buffer(buffer);
3499 run_window_configuration_hook( window );
3504 DEFUN("select-window", Fselect_window, 1, 2, 0, /*
3505 Select WINDOW. Most editing will apply to WINDOW's buffer.
3506 The main editor command loop selects the buffer of the selected window
3507 before each command.
3509 With non-nil optional argument NORECORD, do not modify the
3510 global or per-frame buffer ordering.
3515 Lisp_Object old_selected_window = Fselected_window(Qnil);
3517 CHECK_LIVE_WINDOW(window);
3518 w = XWINDOW(window);
3520 /* we have already caught dead-window errors */
3521 if (!NILP(w->hchild) || !NILP(w->vchild))
3522 error("Trying to select non-leaf window");
3524 w->use_time = make_int(++window_select_count);
3526 if (EQ(window, old_selected_window))
3529 /* deselect the old window, if it exists (it might not exist if
3530 the selected device has no frames, which occurs at startup) */
3531 if (!NILP(old_selected_window)) {
3532 struct window *ow = XWINDOW(old_selected_window);
3534 Fset_marker(ow->pointm[CURRENT_DISP],
3535 make_int(BUF_PT(XBUFFER(ow->buffer))), ow->buffer);
3537 MARK_WINDOWS_CHANGED(ow);
3540 /* now select the window's frame */
3541 set_frame_selected_window(XFRAME(WINDOW_FRAME(w)), window);
3543 select_frame_1(WINDOW_FRAME(w));
3545 /* also select the window's buffer */
3547 Frecord_buffer(w->buffer);
3548 Fset_buffer(w->buffer);
3550 /* Go to the point recorded in the window.
3551 This is important when the buffer is in more
3552 than one window. It also matters when
3553 redisplay_window has altered point after scrolling,
3554 because it makes the change only in the window. */
3556 Bufpos new_point = marker_position(w->pointm[CURRENT_DISP]);
3557 if (new_point < BUF_BEGV(current_buffer))
3558 new_point = BUF_BEGV(current_buffer);
3559 else if (new_point > BUF_ZV(current_buffer))
3560 new_point = BUF_ZV(current_buffer);
3562 BUF_SET_PT(current_buffer, new_point);
3565 MARK_WINDOWS_CHANGED(w);
3571 display_buffer(Lisp_Object buffer, Lisp_Object not_this_window_p,
3572 Lisp_Object override_frame)
3574 return call3(Qdisplay_buffer, buffer, not_this_window_p,
3578 void temp_output_buffer_show(Lisp_Object buf, Lisp_Object same_frame)
3580 /* This function can GC */
3583 struct buffer *b = XBUFFER(buf);
3585 BUF_SAVE_MODIFF(XBUFFER(buf)) = BUF_MODIFF(b);
3587 BUF_SET_PT(b, BUF_BEG(b));
3589 if (!NILP(Vtemp_buffer_show_function))
3590 call1(Vtemp_buffer_show_function, buf);
3592 window = display_buffer(buf, Qnil, same_frame);
3594 if (!EQ(XWINDOW(window)->frame, Fselected_frame(Qnil)))
3595 Fmake_frame_visible(WINDOW_FRAME(XWINDOW(window)));
3597 Vminibuffer_scroll_window = window;
3598 w = XWINDOW(window);
3600 w->modeline_hscroll = 0;
3601 set_marker_restricted(w->start[CURRENT_DISP], make_int(1), buf);
3602 set_marker_restricted(w->pointm[CURRENT_DISP], make_int(1),
3604 set_marker_restricted(w->sb_point, make_int(1), buf);
3606 /* Run temp-buffer-show-hook, with the chosen window selected. */
3607 if (!preparing_for_armageddon) {
3609 tem = Fboundp(Qtemp_buffer_show_hook);
3611 tem = Fsymbol_value(Qtemp_buffer_show_hook);
3613 int count = specpdl_depth();
3615 /* Select the window that was chosen, for running
3617 record_unwind_protect
3618 (save_window_excursion_unwind,
3619 Fcurrent_window_configuration
3622 Fselect_window(window, Qnil);
3623 run_hook(Qtemp_buffer_show_hook);
3624 unbind_to(count, Qnil);
3631 static void make_dummy_parent(Lisp_Object window)
3634 struct window *o = XWINDOW(window);
3635 struct window *p = alloc_lcrecord_type(struct window, &lrecord_window);
3638 copy_lcrecord(p, o);
3640 /* Don't copy the pointers to the line start cache or the face
3642 p->line_start_cache = Dynarr_new(line_start_cache);
3643 p->face_cachels = Dynarr_new(face_cachel);
3644 p->glyph_cachels = Dynarr_new(glyph_cachel);
3645 p->subwindow_instance_cache = make_image_instance_cache_hash_table();
3647 /* Put new into window structure in place of window */
3648 replace_window(window, new);
3656 p->start[CURRENT_DISP] = Qnil;
3657 p->start[DESIRED_DISP] = Qnil;
3658 p->start[CMOTION_DISP] = Qnil;
3659 p->pointm[CURRENT_DISP] = Qnil;
3660 p->pointm[DESIRED_DISP] = Qnil;
3661 p->pointm[CMOTION_DISP] = Qnil;
3666 DEFUN("split-window", Fsplit_window, 0, 3, "", /*
3667 Split WINDOW, putting SIZE lines in the first of the pair.
3668 WINDOW defaults to the selected one and SIZE to half its size.
3669 If optional third arg HORFLAG is non-nil, split side by side and put
3670 SIZE columns in the first of the pair. The newly created window is
3674 (window, size, horflag))
3677 struct window *o, *p;
3683 window = Fselected_window(Qnil);
3685 CHECK_LIVE_WINDOW(window);
3687 o = XWINDOW(window);
3688 f = XFRAME(WINDOW_FRAME(o));
3692 /* In the new scheme, we are symmetric with respect to separators
3693 so there is no need to do weird things here. */
3696 (WINDOW_WIDTH(o) + window_divider_width(o)) >> 1;
3697 csize = window_pixel_width_to_char_width(o, psize, 0);
3699 psize = WINDOW_HEIGHT(o) >> 1;
3700 csize = window_pixel_height_to_char_height(o, psize, 1);
3706 psize = window_char_width_to_pixel_width(o, csize, 0);
3708 psize = window_char_height_to_pixel_height(o, csize, 1);
3711 if (MINI_WINDOW_P(o))
3712 error("Attempt to split minibuffer window");
3713 else if (FRAME_NO_SPLIT_P(XFRAME(WINDOW_FRAME(o))))
3714 error("Attempt to split unsplittable frame");
3716 check_min_window_sizes();
3718 if (NILP(horflag)) {
3719 if (csize < window_min_height)
3720 error("Window height %d too small (after splitting)",
3722 if (csize + window_min_height > window_char_height(o, 1))
3723 error("Window height %d too small (after splitting)",
3724 window_char_height(o, 1) - csize);
3726 || NILP(XWINDOW(o->parent)->vchild)) {
3727 make_dummy_parent(window);
3729 /* #### I can't understand why you have to reset face
3730 cachels here. This can cause crash so let's disable it
3731 and see the difference. See redisplay-tests.el --yh */
3732 reset_face_cachels(XWINDOW(window));
3735 XWINDOW(new)->vchild = window;
3736 XFRAME(o->frame)->mirror_dirty = 1;
3739 if (csize < window_min_width)
3740 error("Window width %d too small (after splitting)",
3742 if (csize + window_min_width > window_char_width(o, 0))
3743 error("Window width %d too small (after splitting)",
3744 window_char_width(o, 0) - csize);
3746 || NILP(XWINDOW(o->parent)->hchild)) {
3747 make_dummy_parent(window);
3749 /* #### See above. */
3750 reset_face_cachels(XWINDOW(window));
3753 XWINDOW(new)->hchild = window;
3754 XFRAME(o->frame)->mirror_dirty = 1;
3758 /* Now we know that window's parent is a vertical combination
3759 if we are dividing vertically, or a horizontal combination
3760 if we are making side-by-side windows */
3762 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
3763 new = allocate_window();
3766 p->frame = o->frame;
3769 XWINDOW(p->next)->prev = new;
3772 p->parent = o->parent;
3775 reset_face_cachels(p);
3776 reset_glyph_cachels(p);
3778 /* Apportion the available frame space among the two new windows */
3780 if (!NILP(horflag)) {
3781 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
3782 WINDOW_TOP(p) = WINDOW_TOP(o);
3783 WINDOW_WIDTH(p) = WINDOW_WIDTH(o) - psize;
3784 WINDOW_WIDTH(o) = psize;
3785 WINDOW_LEFT(p) = WINDOW_LEFT(o) + psize;
3787 WINDOW_LEFT(p) = WINDOW_LEFT(o);
3788 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
3789 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o) - psize;
3790 WINDOW_HEIGHT(o) = psize;
3791 WINDOW_TOP(p) = WINDOW_TOP(o) + psize;
3794 XFRAME(p->frame)->mirror_dirty = 1;
3795 /* do this last (after the window is completely initialized and
3796 the mirror-dirty flag is set) so that specifier recomputation
3797 caused as a result of this will work properly and not abort. */
3798 Fset_window_buffer(new, o->buffer, Qt);
3800 /* window-configuration-hook is called indirectly, in
3801 set-window-buffer. */
3806 DEFUN("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3807 Make the selected window COUNT lines taller.
3808 From program, optional second arg HORIZONTALP non-nil means grow
3809 sideways COUNT columns, and optional third arg WINDOW specifies the
3810 window to change instead of the selected window.
3813 (count, horizontalp, window))
3816 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3821 DEFUN("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3822 Make the selected window COUNT pixels taller.
3823 From program, optional second arg HORIZONTALP non-nil means grow
3824 sideways COUNT pixels, and optional third arg WINDOW specifies the
3825 window to change instead of the selected window.
3828 (count, horizontalp, window))
3831 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3836 DEFUN("shrink-window", Fshrink_window, 1, 3, "_p", /*
3837 Make the selected window COUNT lines shorter.
3838 From program, optional second arg HORIZONTALP non-nil means shrink
3839 sideways COUNT columns, and optional third arg WINDOW specifies the
3840 window to change instead of the selected window.
3843 (count, horizontalp, window))
3846 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3851 DEFUN("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3852 Make the selected window COUNT pixels smaller.
3853 From program, optional second arg HORIZONTALP non-nil means shrink
3854 sideways COUNT pixels, and optional third arg WINDOW specifies the
3855 window to change instead of the selected window.
3858 (count, horizontalp, window))
3861 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3867 window_pixel_height_to_char_height(struct window *w, int pixel_height,
3868 int include_gutters_p)
3871 int defheight, defwidth;
3875 XSETWINDOW(window, w);
3877 avail_height = (pixel_height -
3878 (include_gutters_p ? 0 :
3879 window_top_window_gutter_height(w) +
3880 window_bottom_window_gutter_height(w)));
3882 default_face_height_and_width(window, &defheight, &defwidth);
3884 char_height = avail_height / defheight;
3886 /* It's the calling function's responsibility to check these values
3887 and make sure they're not out of range.
3889 #### We need to go through the calling functions and actually
3891 return max(0, char_height);
3895 window_char_height_to_pixel_height(struct window *w, int char_height,
3896 int include_gutters_p)
3899 int defheight, defwidth;
3904 XSETWINDOW(window, w);
3906 default_face_height_and_width(window, &defheight, &defwidth);
3908 avail_height = char_height * defheight;
3909 pixel_height = (avail_height +
3910 (include_gutters_p ? 0 :
3911 window_top_window_gutter_height(w) +
3912 window_bottom_window_gutter_height(w)));
3914 /* It's the calling function's responsibility to check these values
3915 and make sure they're not out of range.
3917 #### We need to go through the calling functions and actually
3919 return max(0, pixel_height);
3922 /* Return number of default lines of text can fit in the window W.
3923 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3924 horizontal scrollbar) in the space that is used for the calculation.
3925 This doesn't include space used by the frame gutters.
3927 int window_char_height(struct window *w, int include_gutters_p)
3929 return window_pixel_height_to_char_height(w, window_pixel_height(w),
3934 * Return number of lines currently displayed in window w. If
3935 * end-of-buffer is displayed then the area below end-of-buffer is assume
3936 * to be blank lines of default height.
3937 * Does not include the modeline.
3939 int window_displayed_height(struct window *w)
3941 struct buffer *b = XBUFFER(w->buffer);
3942 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
3945 (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV(b)
3946 ? -1 : w->window_end_pos[CURRENT_DISP]);
3948 if (!Dynarr_length(dla))
3949 return window_char_height(w, 0);
3951 num_lines = Dynarr_length(dla);
3953 /* #### Document and assert somewhere that w->window_end_pos == -1
3954 indicates that end-of-buffer is being displayed. */
3955 if (end_pos == -1) {
3956 struct display_line *dl = Dynarr_atp(dla, 0);
3957 int ypos1 = dl->ypos + dl->descent;
3958 int ypos2 = WINDOW_TEXT_BOTTOM(w);
3960 int defheight, defwidth;
3962 XSETWINDOW(window, w);
3967 if (Dynarr_length(dla) == 1)
3968 ypos1 = WINDOW_TEXT_TOP(w);
3970 dl = Dynarr_atp(dla, Dynarr_length(dla) - 1);
3971 /* If this line is clipped then we know that there is no
3972 blank room between eob and the modeline. If we are
3973 scrolling on clipped lines just know off the clipped
3974 line and return . */
3975 if (scroll_on_clipped_lines && dl->clip)
3976 return num_lines - 1;
3977 ypos1 = dl->ypos + dl->descent - dl->clip;
3981 default_face_height_and_width(window, &defheight, &defwidth);
3982 /* #### This probably needs to know about the clipping area once a
3983 final definition is decided on. */
3984 num_lines += ((ypos2 - ypos1) / defheight);
3986 if (num_lines > 1 && Dynarr_atp(dla, 0)->modeline)
3989 if (scroll_on_clipped_lines
3990 && Dynarr_atp(dla, Dynarr_length(dla) - 1)->clip)
3997 static int window_pixel_width(Lisp_Object window)
3999 return WINDOW_WIDTH(XWINDOW(window));
4002 /* Calculate the pixel of a window, optionally including margin space
4003 but no vertical gutters. */
4005 window_pixel_width_to_char_width(struct window *w, int pixel_width,
4006 int include_margins_p)
4010 int defheight, defwidth;
4013 XSETWINDOW(window, w);
4015 avail_width = (pixel_width -
4016 window_left_gutter_width(w, 0) -
4017 window_right_gutter_width(w, 0) -
4018 (include_margins_p ? 0 : window_left_margin_width(w)) -
4019 (include_margins_p ? 0 : window_right_margin_width(w)));
4021 default_face_height_and_width(window, &defheight, &defwidth);
4023 char_width = (avail_width / defwidth);
4025 /* It's the calling function's responsibility to check these values
4026 and make sure they're not out of range.
4028 #### We need to go through the calling functions and actually
4030 return max(0, char_width);
4034 window_char_width_to_pixel_width(struct window *w, int char_width,
4035 int include_margins_p)
4039 int defheight, defwidth;
4042 XSETWINDOW(window, w);
4044 default_face_height_and_width(window, &defheight, &defwidth);
4046 avail_width = char_width * defwidth;
4047 pixel_width = (avail_width +
4048 window_left_window_gutter_width(w, 0) +
4049 window_right_window_gutter_width(w, 0) +
4050 (include_margins_p ? 0 : window_left_margin_width(w)) +
4051 (include_margins_p ? 0 : window_right_margin_width(w)));
4053 /* It's the calling function's responsibility to check these values
4054 and make sure they're not out of range.
4056 #### We need to go through the calling functions and actually
4058 return max(0, pixel_width);
4061 /* This returns the usable space which doesn't include space needed by
4062 scrollbars or divider lines. */
4063 int window_char_width(struct window *w, int include_margins_p)
4065 return window_pixel_width_to_char_width(w, WINDOW_WIDTH(w),
4069 #define MINSIZE(w) \
4071 ? window_min_width * defwidth \
4072 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4075 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4077 #define CURSIZE(w) \
4078 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4080 #define CURCHARSIZE(w) \
4081 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4083 #define MINCHARSIZE(window) \
4084 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4085 ? 1 : window_min_height)
4087 static int window_pixheight(Lisp_Object w)
4089 return window_pixel_height(XWINDOW(w));
4092 /* Unlike set_window_pixheight, this function
4093 also changes the heights of the siblings so as to
4094 keep everything consistent. */
4097 change_window_height(Lisp_Object window, int delta, Lisp_Object horizontalp,
4100 struct window *win = decode_window(window);
4101 int widthflag = !NILP(horizontalp);
4106 int (*sizefun) (Lisp_Object) = (widthflag
4107 ? window_pixel_width
4108 : window_pixheight);
4109 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4110 ? set_window_pixwidth
4111 : set_window_pixheight);
4113 int defheight, defwidth;
4118 check_min_window_sizes();
4120 XSETWINDOW(window, win);
4121 f = XFRAME(win->frame);
4122 if (EQ(window, FRAME_ROOT_WINDOW(f)))
4123 error("Won't change only window");
4125 /* #### This is very likely incorrect and instead the char_to_pixel_
4126 functions should be called. */
4127 default_face_height_and_width(window, &defheight, &defwidth);
4130 w = XWINDOW(window);
4135 sizep = &CURSIZE (w);
4136 dim = CURCHARSIZE (w);
4137 new_pixsize = inpixels?(*sizep + delta):(dim+delta);
4138 set_window_pixsize (window, new_pixsize, 0, 0);
4143 if (widthflag ? !NILP(XWINDOW(parent)->hchild)
4144 : !NILP(XWINDOW(parent)->vchild))
4149 sizep = &CURSIZE(w);
4150 dim = CURCHARSIZE(w);
4152 if ((inpixels && (*sizep + delta) < MINSIZE(window)) ||
4153 (!inpixels && (dim + delta) < MINCHARSIZE(window))) {
4154 if (MINI_WINDOW_P(XWINDOW(window)))
4156 else if (!NILP(parent)) {
4157 Fdelete_window(window, Qnil);
4163 delta *= (widthflag ? defwidth : defheight);
4168 maxdelta = ((!NILP(parent))
4169 ? (*sizefun) (parent) - *sizep : ((!NILP(w->next))
4179 /* This is a frame with only one window,
4180 a minibuffer-only or a minibufferless frame. */
4184 if (delta > maxdelta)
4185 /* This case traps trying to make the minibuffer
4186 the full frame, or make the only window aside from the
4187 minibuffer the full frame. */
4194 /* #### Chuck: is this correct? */
4195 if (*sizep + delta < MINSIZE(window)) {
4196 Fdelete_window(window);
4202 if (!NILP(w->next) &&
4203 (*sizefun) (w->next) - delta >= (int)MINSIZE(w->next)) {
4204 CURBEG(XWINDOW(w->next)) += delta;
4205 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4206 (*setsizefun) (window, *sizep + delta, 0);
4207 } else if (!NILP(w->prev) &&
4208 (*sizefun) (w->prev) - delta >= (int)MINSIZE(w->prev)) {
4209 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4211 (*setsizefun) (window, *sizep + delta, 0);
4214 int opht = (*sizefun) (parent);
4216 /* If trying to grow this window to or beyond size of the parent,
4217 make delta1 so big that, on shrinking back down,
4218 all the siblings end up with less than one line and are deleted. */
4219 if (opht <= *sizep + delta)
4220 delta1 = opht * opht * 2;
4221 /* Otherwise, make delta1 just right so that if we add delta1
4222 lines to this window and to the parent, and then shrink
4223 the parent back to its original size, the new proportional
4224 size of this window will increase by delta. */
4227 (delta * opht * 100) / ((opht - *sizep - delta) *
4230 /* Add delta1 lines or columns to this window, and to the parent,
4231 keeping things consistent while not affecting siblings. */
4232 CURSIZE(XWINDOW(parent)) = opht + delta1;
4233 (*setsizefun) (window, *sizep + delta1, 0);
4235 /* Squeeze out delta1 lines or columns from our parent,
4236 shrinking this window and siblings proportionately.
4237 This brings parent back to correct size.
4238 Delta1 was calculated so this makes this window the desired size,
4239 taking it all out of the siblings. */
4240 (*setsizefun) (parent, opht, 0);
4243 SET_LAST_MODIFIED(w, 0);
4244 SET_LAST_FACECHANGE(w);
4245 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
4246 /* overkill maybe, but better to be correct */
4247 MARK_FRAME_GUTTERS_CHANGED(f);
4249 run_window_configuration_hook( window );
4258 /* Scroll contents of window WINDOW up COUNT lines.
4259 If COUNT < (top line height / average line height) then we just adjust
4262 window_scroll(Lisp_Object window, Lisp_Object count, int direction,
4263 Error_behavior errb)
4265 struct window *w = XWINDOW(window);
4266 struct buffer *b = XBUFFER(w->buffer);
4267 int selected = EQ(window, Fselected_window(Qnil));
4269 Lisp_Object point, tem;
4270 display_line_dynarr *dla;
4271 int fheight, fwidth, modeline = 0;
4272 struct display_line *dl;
4275 point = make_int(BUF_PT(b));
4277 Bufpos pos = marker_position(w->pointm[CURRENT_DISP]);
4279 if (pos < BUF_BEGV(b))
4281 else if (pos > BUF_ZV(b))
4284 point = make_int(pos);
4287 /* Always set force_start so that redisplay_window will run
4288 the window-scroll-functions. */
4291 /* #### When the fuck does this happen? I'm so glad that history has
4292 completely documented the behavior of the scrolling functions under
4293 all circumstances. */
4294 tem = Fpos_visible_in_window_p(point, window);
4296 Fvertical_motion(make_int(-window_char_height(w, 0) / 2),
4298 Fset_marker(w->start[CURRENT_DISP], point, w->buffer);
4299 w->start_at_line_beg = beginning_of_line_p(b, XINT(point));
4300 WINDOW_TEXT_TOP_CLIP(w) = 0;
4301 MARK_WINDOWS_CHANGED(w);
4305 if (EQ(count, Qminus))
4308 count = Fprefix_numeric_value(count);
4309 value = XINT(count) * direction;
4312 return; /* someone just made a pointless call */
4316 /* If the user didn't specify how far to scroll then we have to figure it
4317 out by ourselves. */
4318 if (NILP(count) || EQ(count, Qminus)) {
4319 /* Going forwards is easy. If that is what we are doing then just
4320 set value and the section which handles the user specifying a
4321 positive value will work. */
4322 if (direction == 1) {
4324 window_displayed_height(w) -
4325 next_screen_context_lines;
4326 value = (value < 1 ? 1 : value);
4329 /* Going backwards is hard. We can't use the same loop used if the
4330 user specified a negative value because we care about
4331 next_screen_context_lines. In a variable height world you don't
4332 know how many lines above you can actually be displayed and still
4333 have the context lines appear. So we leave value set to 0 and add
4334 a separate section to deal with this. */
4338 if (direction == 1 && !value) {
4342 /* Determine parameters to test for partial line scrolling with. */
4343 dla = window_display_lines(w, CURRENT_DISP);
4345 if (INTP(Vwindow_pixel_scroll_increment))
4346 fheight = XINT(Vwindow_pixel_scroll_increment);
4347 else if (!NILP(Vwindow_pixel_scroll_increment))
4348 default_face_height_and_width(window, &fheight, &fwidth);
4350 if (Dynarr_length(dla) >= 1)
4351 modeline = Dynarr_atp(dla, 0)->modeline;
4353 dl = Dynarr_atp(dla, modeline);
4356 /* Go for partial display line scrolling. This just means bumping
4357 the clip by a reasonable amount and redisplaying, everything else
4358 remains unchanged. */
4359 if (!NILP(Vwindow_pixel_scroll_increment)
4360 && Dynarr_length(dla) >= (1 + modeline)
4361 && (dl->ascent - dl->top_clip) > fheight * value) {
4362 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4363 MARK_WINDOWS_CHANGED(w);
4366 Bufpos startp, old_start;
4368 if (WINDOW_TEXT_TOP_CLIP(w)) {
4369 WINDOW_TEXT_TOP_CLIP(w) = 0;
4370 MARK_WINDOWS_CHANGED(w);
4373 old_start = marker_position(w->start[CURRENT_DISP]);
4374 startp = vmotion(w, old_start, value, &vtarget);
4376 if (vtarget < value &&
4377 (w->window_end_pos[CURRENT_DISP] == -1
4378 || (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] >
4380 maybe_signal_error(Qend_of_buffer, Qnil,
4384 set_marker_restricted(w->start[CURRENT_DISP],
4388 w->start_at_line_beg =
4389 beginning_of_line_p(b, startp);
4390 MARK_WINDOWS_CHANGED(w);
4392 if (!point_would_be_visible
4393 (w, startp, XINT(point))) {
4395 BUF_SET_PT(b, startp);
4397 set_marker_restricted(w->
4407 } else if (value < 0) {
4408 /* Go for partial display line scrolling. This just means bumping
4409 the clip by a reasonable amount and redisplaying, everything else
4410 remains unchanged. */
4411 if (!NILP(Vwindow_pixel_scroll_increment)
4412 && Dynarr_length(dla) >= (1 + modeline)
4414 (dl->ascent - dl->top_clip) - fheight * value <
4415 (dl->ascent + dl->descent - dl->clip)
4416 && WINDOW_TEXT_TOP_CLIP(w) + value * fheight > 0) {
4417 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4418 MARK_WINDOWS_CHANGED(w);
4421 Bufpos startp, old_start;
4423 if (WINDOW_TEXT_TOP_CLIP(w)) {
4424 WINDOW_TEXT_TOP_CLIP(w) = 0;
4425 MARK_WINDOWS_CHANGED(w);
4428 old_start = marker_position(w->start[CURRENT_DISP]);
4429 startp = vmotion(w, old_start, value, &vtarget);
4432 && marker_position(w->start[CURRENT_DISP]) ==
4434 maybe_signal_error(Qbeginning_of_buffer, Qnil,
4438 set_marker_restricted(w->start[CURRENT_DISP],
4442 w->start_at_line_beg =
4443 beginning_of_line_p(b, startp);
4444 MARK_WINDOWS_CHANGED(w);
4446 /* #### Scroll back by less than a line. This code was
4447 originally for scrolling over large pixmaps and it
4448 loses when a line being *exposed* at the top of the
4449 window is bigger than the current one. However, for
4450 pixel based scrolling in general we can guess that
4451 the line we are going to display is probably the same
4452 size as the one we are on. In that instance we can
4453 have a reasonable stab at a suitable top clip. Fixing
4454 this properly is hard (and probably slow) as we would
4455 have to call redisplay to figure out the exposed line
4457 if (!NILP(Vwindow_pixel_scroll_increment)
4458 && Dynarr_length(dla) >= (1 + modeline)
4459 && dl->ascent + fheight * value > 0) {
4460 WINDOW_TEXT_TOP_CLIP(w) =
4461 (dl->ascent + fheight * value);
4464 if (!point_would_be_visible
4465 (w, startp, XINT(point))) {
4468 if (MINI_WINDOW_P(w))
4472 start_of_last_line(w,
4476 BUF_SET_PT(b, new_point);
4478 set_marker_restricted(w->
4488 } else { /* value == 0 && direction == -1 */
4490 if (WINDOW_TEXT_TOP_CLIP(w)) {
4491 WINDOW_TEXT_TOP_CLIP(w) = 0;
4492 MARK_WINDOWS_CHANGED(w);
4494 if (marker_position(w->start[CURRENT_DISP]) == BUF_BEGV(b)) {
4495 maybe_signal_error(Qbeginning_of_buffer, Qnil, Qwindow,
4500 int movement = next_screen_context_lines - 1;
4502 marker_position(w->start[CURRENT_DISP]);
4504 vmotion(w, old_startp, movement, &vtarget);
4506 start_with_point_on_display_line(w, bottom,
4510 if (startp >= old_startp)
4511 startp = vmotion(w, old_startp, -1, NULL);
4513 set_marker_restricted(w->start[CURRENT_DISP],
4514 make_int(startp), w->buffer);
4516 w->start_at_line_beg = beginning_of_line_p(b, startp);
4517 MARK_WINDOWS_CHANGED(w);
4519 if (!point_would_be_visible(w, startp, XINT(point))) {
4521 start_of_last_line(w, startp);
4524 BUF_SET_PT(b, new_point);
4526 set_marker_restricted(w->
4537 DEFUN("scroll-up", Fscroll_up, 0, 1, "_P", /*
4538 Scroll text of current window up COUNT lines; or near full screen if no arg.
4539 A near full screen is `next-screen-context-lines' less than a full screen.
4540 Negative COUNT means scroll downward.
4541 When calling from a program, supply an integer as argument or nil.
4542 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4543 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4546 The characters that are moved over may be added to the current selection
4547 \(i.e. active region) if the Shift key is held down, a motion key is used
4548 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4549 the documentation for this variable for more details.
4553 window_scroll(Fselected_window(Qnil), count, 1, ERROR_ME);
4557 DEFUN("scroll-down", Fscroll_down, 0, 1, "_P", /*
4558 Scroll text of current window down COUNT lines; or near full screen if no arg.
4559 A near full screen is `next-screen-context-lines' less than a full screen.
4560 Negative COUNT means scroll upward.
4561 When calling from a program, supply a number as argument or nil.
4562 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4563 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4566 The characters that are moved over may be added to the current selection
4567 \(i.e. active region) if the Shift key is held down, a motion key is used
4568 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4569 the documentation for this variable for more details.
4573 window_scroll(Fselected_window(Qnil), count, -1, ERROR_ME);
4577 DEFUN("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4578 Return the other window for "other window scroll" commands.
4579 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4580 specifies the window.
4581 If `other-window-scroll-buffer' is non-nil, a window
4582 showing that buffer is used.
4587 Lisp_Object selected_window = Fselected_window(Qnil);
4589 if (MINI_WINDOW_P(XWINDOW(selected_window))
4590 && !NILP(Vminibuffer_scroll_window))
4591 window = Vminibuffer_scroll_window;
4592 /* If buffer is specified, scroll that buffer. */
4593 else if (!NILP(Vother_window_scroll_buffer)) {
4595 Fget_buffer_window(Vother_window_scroll_buffer, Qnil, Qnil);
4598 display_buffer(Vother_window_scroll_buffer, Qt,
4601 /* Nothing specified; look for a neighboring window on the same
4603 window = Fnext_window(selected_window, Qnil, Qnil, Qnil);
4605 if (EQ(window, selected_window))
4606 /* That didn't get us anywhere; look for a window on another
4609 window = Fnext_window(window, Qnil, Qt, Qnil);
4610 while (!FRAME_VISIBLE_P
4611 (XFRAME(WINDOW_FRAME(XWINDOW(window))))
4612 && !EQ(window, selected_window));
4615 CHECK_LIVE_WINDOW(window);
4617 if (EQ(window, selected_window))
4618 error("There is no other window");
4623 DEFUN("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4624 Scroll next window upward COUNT lines; or near full frame if no arg.
4625 The next window is the one below the current one; or the one at the top
4626 if the current one is at the bottom. Negative COUNT means scroll downward.
4627 When calling from a program, supply a number as argument or nil.
4629 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4630 specifies the window to scroll.
4631 If `other-window-scroll-buffer' is non-nil, scroll the window
4632 showing that buffer, popping the buffer up if necessary.
4636 window_scroll(Fother_window_for_scrolling(), count, 1, ERROR_ME);
4640 DEFUN("scroll-left", Fscroll_left, 0, 1, "_P", /*
4641 Scroll selected window display COUNT columns left.
4642 Default for COUNT is window width minus 2.
4644 The characters that are moved over may be added to the current selection
4645 \(i.e. active region) if the Shift key is held down, a motion key is used
4646 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4647 the documentation for this variable for more details.
4651 Lisp_Object window = Fselected_window(Qnil);
4652 struct window *w = XWINDOW(window);
4653 int n = (NILP(count) ?
4654 window_char_width(w, 0) - 2 :
4655 XINT(Fprefix_numeric_value(count)));
4657 return Fset_window_hscroll(window, make_int(w->hscroll + n));
4660 DEFUN("scroll-right", Fscroll_right, 0, 1, "_P", /*
4661 Scroll selected window display COUNT columns right.
4662 Default for COUNT is window width minus 2.
4664 The characters that are moved over may be added to the current selection
4665 \(i.e. active region) if the Shift key is held down, a motion key is used
4666 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4667 the documentation for this variable for more details.
4671 Lisp_Object window = Fselected_window(Qnil);
4672 struct window *w = XWINDOW(window);
4673 int n = (NILP(count) ?
4674 window_char_width(w, 0) - 2 :
4675 XINT(Fprefix_numeric_value(count)));
4677 return Fset_window_hscroll(window, make_int(w->hscroll - n));
4680 DEFUN("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4681 Center point in WINDOW. With N, put point on line N.
4682 The desired position of point is always relative to the window.
4683 If WINDOW is nil, the selected window is used.
4687 struct window *w = decode_window(window);
4688 struct buffer *b = XBUFFER(w->buffer);
4689 Bufpos opoint = BUF_PT(b);
4694 start_with_line_at_pixpos(w, opoint, window_half_pixpos(w));
4696 n = Fprefix_numeric_value(n);
4698 startp = start_with_point_on_display_line(w, opoint, XINT(n));
4701 Fset_marker(w->start[CURRENT_DISP], make_int(startp), w->buffer);
4703 w->start_at_line_beg = beginning_of_line_p(b, startp);
4705 MARK_WINDOWS_CHANGED(w);
4709 DEFUN("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4710 Position point relative to WINDOW.
4711 With no argument, position text at center of window.
4712 An argument specifies window line; zero means top of window,
4713 negative means relative to bottom of window.
4714 If WINDOW is nil, the selected window is used.
4721 Bufpos start, new_point;
4724 /* Don't use decode_window() because we need the new value of
4727 window = Fselected_window(Qnil);
4729 CHECK_LIVE_WINDOW(window);
4730 w = XWINDOW(window);
4731 b = XBUFFER(w->buffer);
4733 height = window_displayed_height(w);
4734 selected = EQ(window, Fselected_window(w->frame));
4739 if (XINT(w->last_modified[CURRENT_DISP]) >= BUF_MODIFF(b)
4740 && XINT(w->last_facechange[CURRENT_DISP]) >=
4741 BUF_FACECHANGE(b)) {
4742 new_point = point_at_center(w, CURRENT_DISP, 0, 0);
4745 BUF_SET_PT(b, new_point);
4747 Fset_window_point(window, make_int(new_point));
4749 retval = line_at_center(w, CURRENT_DISP, 0, 0);
4751 start = marker_position(w->start[CURRENT_DISP]);
4752 if (start < BUF_BEGV(b))
4753 start = BUF_BEGV(b);
4754 else if (start > BUF_ZV(b))
4758 new_point = BUF_PT(b);
4761 marker_position(w->pointm[CURRENT_DISP]);
4764 point_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4767 BUF_SET_PT(b, new_point);
4769 Fset_window_point(window, make_int(new_point));
4772 line_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4775 return make_int(retval);
4777 /* #### Is this going to work right when at eob? */
4778 arg = Fprefix_numeric_value(arg);
4780 XSETINT(arg, XINT(arg) + height);
4783 start = marker_position(w->start[CURRENT_DISP]);
4784 if (start < BUF_BEGV(b) || start > BUF_ZV(b)) {
4786 new_point = BUF_PT(b);
4788 new_point = marker_position(w->pointm[CURRENT_DISP]);
4790 new_point = vmotion(XWINDOW(window), new_point, -height / 2, 0);
4793 BUF_SET_PT(b, new_point);
4795 Fset_window_point(window, make_int(new_point));
4797 Fset_marker(w->start[CURRENT_DISP], make_int(new_point),
4799 w->start_at_line_beg = beginning_of_line_p(b, new_point);
4803 BUF_SET_PT(b, start);
4805 Fset_window_point(window, make_int(start));
4809 return Fvertical_motion(arg, window, Qnil);
4812 new_point = vmotion(XWINDOW(window),
4813 marker_position(w->pointm[CURRENT_DISP]),
4815 Fset_window_point(window, make_int(new_point));
4816 return make_int(vpos);
4821 map_windows_1(Lisp_Object window,
4822 int (*mapfun) (struct window * w, void *closure), void *closure)
4824 for (; !NILP(window); window = XWINDOW(window)->next) {
4826 struct window *w = XWINDOW(window);
4828 if (!NILP(w->vchild))
4829 retval = map_windows_1(w->vchild, mapfun, closure);
4830 else if (!NILP(w->hchild))
4831 retval = map_windows_1(w->hchild, mapfun, closure);
4833 retval = (mapfun) (w, closure);
4842 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4843 invocation of MAPFUN. If any invocation of MAPFUN returns
4844 non-zero, the mapping is halted. Otherwise, map_windows() maps
4845 over all windows in F.
4847 If MAPFUN creates or deletes windows, the behavior is undefined. */
4850 map_windows(struct frame *f, int (*mapfun) (struct window * w, void *closure),
4854 return map_windows_1(FRAME_ROOT_WINDOW(f), mapfun, closure);
4856 Lisp_Object frmcons, devcons, concons;
4858 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
4860 map_windows_1(FRAME_ROOT_WINDOW
4861 (XFRAME(XCAR(frmcons))),
4872 modeline_shadow_thickness_changed(Lisp_Object specifier, struct window *w,
4875 w->shadow_thickness_changed = 1;
4876 MARK_WINDOWS_CHANGED(w);
4880 vertical_divider_changed_in_window(Lisp_Object specifier,
4881 struct window *w, Lisp_Object oldval)
4883 MARK_WINDOWS_CHANGED(w);
4884 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(XFRAME(WINDOW_FRAME(w)));
4887 /* also used in scrollbar.c */
4889 some_window_value_changed(Lisp_Object specifier, struct window *w,
4892 MARK_WINDOWS_CHANGED(w);
4895 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
4897 struct window_stats {
4900 #ifdef HAVE_SCROLLBARS
4904 int other_redisplay;
4909 compute_window_mirror_usage(struct window_mirror *mir,
4910 struct window_stats *stats,
4911 struct overhead_stats *ovstats)
4915 stats->other += malloced_storage_size(mir, sizeof(struct window_mirror),
4917 #ifdef HAVE_SCROLLBARS
4919 struct device *d = XDEVICE(FRAME_DEVICE(mir->frame));
4922 compute_scrollbar_instance_usage(d,
4924 scrollbar_vertical_instance,
4927 compute_scrollbar_instance_usage(d,
4929 scrollbar_horizontal_instance,
4932 #endif /* HAVE_SCROLLBARS */
4933 stats->other_redisplay +=
4934 compute_display_line_dynarr_usage(mir->current_display_lines,
4936 stats->other_redisplay +=
4937 compute_display_line_dynarr_usage(mir->desired_display_lines,
4942 compute_window_usage(struct window *w, struct window_stats *stats,
4943 struct overhead_stats *ovstats)
4947 malloced_storage_size(w, sizeof(struct window), ovstats);
4948 stats->face += compute_face_cachel_usage(w->face_cachels, ovstats);
4949 stats->glyph += compute_glyph_cachel_usage(w->glyph_cachels, ovstats);
4950 stats->line_start +=
4951 compute_line_start_cache_dynarr_usage(w->line_start_cache, ovstats);
4952 compute_window_mirror_usage(find_window_mirror(w), stats, ovstats);
4955 DEFUN("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4956 Return stats about the memory usage of window WINDOW.
4957 The values returned are in the form of an alist of usage types and byte
4958 counts. The byte counts attempt to encompass all the memory used
4959 by the window (separate from the memory logically associated with a
4960 buffer or frame), including internal structures and any malloc()
4961 overhead associated with them. In practice, the byte counts are
4962 underestimated because certain memory usage is very hard to determine
4963 \(e.g. the amount of memory used inside the Xt library or inside the
4964 X server) and because there is other stuff that might logically
4965 be associated with a window, buffer, or frame (e.g. window configurations,
4966 glyphs) but should not obviously be included in the usage counts.
4968 Multiple slices of the total memory usage may be returned, separated
4969 by a nil. Each slice represents a particular view of the memory, a
4970 particular way of partitioning it into groups. Within a slice, there
4971 is no overlap between the groups of memory, and each slice collectively
4972 represents all the memory concerned.
4976 struct window_stats stats;
4977 struct overhead_stats ovstats;
4978 Lisp_Object val = Qnil;
4980 CHECK_WINDOW(window); /* dead windows should be allowed, no? */
4982 compute_window_usage(XWINDOW(window), &stats, &ovstats);
4984 val = acons(Qface_cache, make_int(stats.face), val);
4985 val = acons(Qglyph_cache, make_int(stats.glyph), val);
4986 #ifdef HAVE_SCROLLBARS
4987 val = acons(Qscrollbar_instances, make_int(stats.scrollbar), val);
4989 val = acons(Qline_start_cache, make_int(stats.line_start), val);
4990 val = acons(Qother_redisplay, make_int(stats.other_redisplay), val);
4991 val = acons(Qother, make_int(stats.other), val);
4992 val = Fcons(Qnil, val);
4993 val = acons(Qactually_requested, make_int(ovstats.was_requested), val);
4994 val = acons(Qmalloc_overhead, make_int(ovstats.malloc_overhead), val);
4995 val = acons(Qdynarr_overhead, make_int(ovstats.dynarr_overhead), val);
4997 return Fnreverse(val);
5000 #endif /* MEMORY_USAGE_STATS */
5002 /************************************************************************/
5003 /* Window configurations */
5004 /************************************************************************/
5006 /* #### This window configuration stuff has had serious bugs lurking in it
5007 for years; it would be a -huge- win if this was reimplemented in lisp.
5010 /* If you add anything to this structure make sure saved_window_equal
5012 struct saved_window {
5013 Lisp_Object window; /* window */
5014 Lisp_Object buffer; /* buffer */
5015 Lisp_Object start; /* copied marker */
5016 Lisp_Object pointm; /* copied marker */
5017 Lisp_Object sb_point; /* copied marker */
5018 Lisp_Object mark; /* copied marker */
5024 Charcount modeline_hscroll;
5025 int parent_index; /* index into saved_windows */
5026 int prev_index; /* index into saved_windows */
5027 char start_at_line_beg; /* boolean */
5029 #define WINDOW_SLOT_DECLARATION
5030 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5031 #include "winslots.h"
5034 /* If you add anything to this structure make sure window_config_equal
5036 struct window_config {
5037 struct lcrecord_header header;
5038 /* int frame_width; No longer needed, JV
5039 int frame_height; */
5041 Lisp_Object selected_frame;
5043 Lisp_Object current_window;
5044 Lisp_Object current_buffer;
5045 Lisp_Object minibuffer_scroll_window;
5046 Lisp_Object root_window;
5047 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5048 /* Record the values of window-min-width and window-min-height
5049 so that window sizes remain consistent with them. */
5050 int min_width, min_height;
5051 unsigned int saved_windows_count;
5052 /* Zero-sized arrays aren't ANSI C */
5053 struct saved_window saved_windows[1];
5056 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5057 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5058 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5059 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5060 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5062 static Lisp_Object mark_window_config(Lisp_Object obj)
5064 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5066 mark_object(config->current_window);
5067 mark_object(config->current_buffer);
5068 mark_object(config->minibuffer_scroll_window);
5069 mark_object(config->root_window);
5071 for (i = 0; i < config->saved_windows_count; i++) {
5072 struct saved_window *s = SAVED_WINDOW_N(config, i);
5073 mark_object(s->window);
5074 mark_object(s->buffer);
5075 mark_object(s->start);
5076 mark_object(s->pointm);
5077 mark_object(s->sb_point);
5078 mark_object(s->mark);
5080 /* #### This looked like this. I do not see why specifier cached
5081 values should not be marked, as such specifiers as toolbars
5082 might have GC-able instances. Freed configs are not marked,
5083 aren't they? -- kkm */
5084 mark_object(s->dedicated);
5086 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5087 #include "winslots.h"
5093 inline static size_t sizeof_window_config_for_n_windows(unsigned int n)
5095 return FLEXIBLE_ARRAY_STRUCT_SIZEOF(struct window_config,
5096 struct saved_window, saved_windows,
5100 static size_t sizeof_window_config(const void *h)
5102 const struct window_config *c = (const struct window_config *)h;
5103 return sizeof_window_config_for_n_windows(c->saved_windows_count);
5107 print_window_config(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5109 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5111 error("printing unreadable object #<window-configuration 0x%x>",
5112 config->header.uid);
5113 write_fmt_str(printcharfun, "#<window-configuration 0x%x>", config->header.uid);
5116 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("window-configuration",
5117 window_configuration,
5119 print_window_config,
5120 0, 0, 0, 0, sizeof_window_config,
5121 struct window_config);
5123 /* Returns a boolean indicating whether the two saved windows are
5126 saved_window_equal(struct saved_window *win1, struct saved_window *win2)
5128 #define WINDOW_SLOT(slot, compare) \
5129 if (!compare (win1->slot, win2->slot)) \
5131 #include "winslots.h"
5134 EQ(win1->window, win2->window) &&
5135 EQ(win1->buffer, win2->buffer) &&
5136 internal_equal(win1->start, win2->start, 0) &&
5137 internal_equal(win1->pointm, win2->pointm, 0) &&
5138 internal_equal(win1->sb_point, win2->sb_point, 0) &&
5139 internal_equal(win1->mark, win2->mark, 0) &&
5140 win1->pixel_left == win2->pixel_left &&
5141 win1->pixel_top == win2->pixel_top &&
5142 win1->pixel_width == win2->pixel_width &&
5143 win1->pixel_height == win2->pixel_height &&
5144 win1->hscroll == win2->hscroll &&
5145 win1->modeline_hscroll == win2->modeline_hscroll &&
5146 win1->parent_index == win2->parent_index &&
5147 win1->prev_index == win2->prev_index &&
5148 win1->start_at_line_beg == win2->start_at_line_beg;
5151 /* Returns a boolean indicating whether the two given configurations
5153 static int window_config_equal(Lisp_Object conf1, Lisp_Object conf2)
5155 struct window_config *fig1, *fig2;
5158 /* First check if they are truly the same. */
5159 if (EQ(conf1, conf2))
5162 fig1 = XWINDOW_CONFIGURATION(conf1);
5163 fig2 = XWINDOW_CONFIGURATION(conf2);
5165 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5166 EQ(fig1->current_window, fig2->current_window) &&
5167 EQ(fig1->current_buffer, fig2->current_buffer) &&
5168 EQ(fig1->root_window, fig2->root_window) &&
5169 EQ(fig1->minibuffer_scroll_window,
5170 fig2->minibuffer_scroll_window)))
5172 fig1->frame_width == fig2->frame_width &&
5173 fig1->frame_height == fig2->frame_height)) */
5176 for (i = 0; i < fig1->saved_windows_count; i++) {
5177 if (!saved_window_equal(SAVED_WINDOW_N(fig1, i),
5178 SAVED_WINDOW_N(fig2, i)))
5185 DEFUN("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5186 Return t if OBJECT is a window-configuration object.
5190 return WINDOW_CONFIGURATIONP(object) ? Qt : Qnil;
5193 static int mark_windows_in_use_closure(struct window *w, void *closure)
5195 int mark = *(int *)closure;
5196 w->config_mark = mark;
5200 static void mark_windows_in_use(struct frame *f, int mark)
5202 map_windows(f, mark_windows_in_use_closure, &mark);
5205 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5206 static Lisp_Object free_window_configuration(Lisp_Object window_config)
5209 struct window_config *config = XWINDOW_CONFIGURATION(window_config);
5211 /* Free all the markers. It's not completely necessary that
5212 we do this (window configs sitting in a free list aren't
5213 marked normally so the markers wouldn't be marked anyway)
5214 but it's more efficient. */
5215 for (i = 0; i < config->saved_windows_count; i++) {
5216 struct saved_window *p = SAVED_WINDOW_N(config, i);
5218 if (!NILP(p->pointm)) {
5219 free_marker(XMARKER(p->pointm));
5222 if (!NILP(p->start)) {
5223 free_marker(XMARKER(p->start));
5226 if (!NILP(p->sb_point)) {
5227 free_marker(XMARKER(p->sb_point));
5230 if (!NILP(p->mark)) {
5231 free_marker(XMARKER(p->mark));
5236 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5237 xfree(window_config);
5240 if (config->saved_windows_count <=
5241 countof(Vwindow_configuration_free_list)) {
5242 free_managed_lcrecord(Vwindow_configuration_free_list
5243 [config->saved_windows_count - 1],
5250 DEFUN("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5251 Set the configuration of windows and buffers as specified by CONFIGURATION.
5252 CONFIGURATION must be a value previously returned
5253 by `current-window-configuration' (which see).
5258 struct window_config *config;
5259 struct saved_window *p;
5260 Lisp_Object new_current_buffer;
5264 struct gcpro gcpro1;
5265 Lisp_Object old_window_config;
5266 /* int previous_frame_height;
5267 int previous_frame_width; */
5268 int previous_pixel_top;
5269 int previous_pixel_height;
5270 int previous_pixel_left;
5271 int previous_pixel_width;
5272 int previous_minibuf_height, previous_minibuf_top,
5273 previous_minibuf_width;
5274 int real_font_height;
5275 int converted_minibuf_height, target_minibuf_height;
5276 int specpdl_count = specpdl_depth();
5278 GCPRO1(configuration);
5280 CHECK_WINDOW_CONFIGURATION(configuration);
5281 config = XWINDOW_CONFIGURATION(configuration);
5283 frame = XWINDOW(SAVED_WINDOW_N(config, 0)->window)->frame;
5286 /* Do not signal an error here if the frame was deleted. There are
5287 reasonable cases where we could get here with a deleted frame and
5288 just want to do close to nothing instead. */
5290 if (FRAME_LIVE_P(f)) {
5291 /* restore the frame characteristics */
5293 new_current_buffer = config->current_buffer;
5294 if (!BUFFER_LIVE_P(XBUFFER(new_current_buffer)))
5295 new_current_buffer = Qnil;
5298 * Assumed precondition: w->config_mark = 0 for all w
5299 * This procedure should ensure this is true by the time it exits
5300 * to ensure the precondition for future calls.
5302 * We use w->config_mark to know whether we're modifying a
5303 * window that is currently visible on the frame (#### we
5304 * should just be able to check whether the window is dead
5305 * or not, but this way is safer?). As we process each
5306 * window, we set its config_mark to 0. At the end, we
5307 * go through all the windows that used to be on the frame,
5308 * set each one's config_mark to 0 (to maintain the
5309 * assumed precondition) and delete each one that's no
5312 * #### Using a window-configuration to keep track of
5313 * the current windows is wasteful. All we need is the
5314 * list of windows, so we could just use a dynarr.
5316 old_window_config = Fcurrent_window_configuration(frame);
5318 /* If the new configuration is already equal to the old, then stop
5319 right here. This saves the work below and it also saves
5320 triggering a full redisplay of this window. This is a huge win
5321 when using the mouse since the mode motion code uses
5322 save-window-excursion extensively but will rarely cause the
5323 configuration to actually change. */
5324 if (window_config_equal(configuration, old_window_config)) {
5325 free_window_configuration(old_window_config);
5330 /* We can't quit or even check for quit because that may cause
5331 investigation of the frame state, which may crash if the frame is
5332 in an inconsistent state. */
5333 begin_dont_check_for_quit();
5334 record_unwind_protect(free_window_configuration,
5337 mark_windows_in_use(f, 1);
5338 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5339 /* Force subwindows to be remapped. This is overkill but saves
5340 us having to rely on the redisplay code to unmap any extant
5343 #### It does cause some extra flashing though which we could
5344 possibly avoid. So consider trying to get redisplay to work
5347 Removing the instances from the frame cache is wrong because
5348 an instance is only put in the frame cache when it is
5349 instantiated. So if we do this there is a chance that stuff
5350 will never get put back in the frame cache. */
5351 reset_frame_subwindow_instance_cache(f);
5354 /* JV: This is bogus,
5355 First of all, the units are inconsistent. The frame sizes are measured
5356 in characters but the window sizes are stored in pixels. So if a
5357 font size change happened between saving and restoring, the
5358 frame "sizes" maybe equal but the windows still should be
5359 resized. This is tickled a lot by the new "character size
5360 stays constant" policy in 21.0. It leads to very weird
5361 glitches (and possibly crashes when asserts are tickled).
5363 Just changing the units doesn't help because changing the
5364 toolbar configuration can also change the pixel positions.
5365 Luckily there is a much simpler way of doing this, see below.
5367 previous_frame_width = FRAME_WIDTH(f);
5368 previous_frame_height = FRAME_HEIGHT(f);
5369 /* If the frame has been resized since this window configuration was
5370 made, we change the frame to the size specified in the
5371 configuration, restore the configuration, and then resize it
5372 back. We keep track of the prevailing height in these variables. */
5373 if (config->frame_height != FRAME_HEIGHT(f)
5374 || config->frame_width != FRAME_WIDTH(f))
5375 change_frame_size(f, config->frame_height,
5376 config->frame_width, 0);
5379 previous_pixel_top = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top;
5380 previous_pixel_height =
5381 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_height;
5382 previous_pixel_left = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left;
5383 previous_pixel_width =
5384 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_width;
5386 /* remember some properties of the minibuffer */
5388 default_face_height_and_width(frame, &real_font_height, 0);
5389 assert(real_font_height > 0);
5391 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f)) {
5392 previous_minibuf_height
5393 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5394 previous_minibuf_top
5395 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5396 previous_minibuf_width
5397 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5399 previous_minibuf_height = 0;
5400 previous_minibuf_top = 0;
5401 previous_minibuf_width = 0;
5403 converted_minibuf_height = (previous_minibuf_height % real_font_height) == 0 ? -(previous_minibuf_height / real_font_height) : /* lines */
5404 previous_minibuf_height; /* pixels */
5406 /* Temporarily avoid any problems with windows that are smaller
5407 than they are supposed to be. */
5408 window_min_height = 1;
5409 window_min_width = 1;
5411 /* OK, now restore all the windows in the window config.
5412 This may involve "undeleting" windows, since the
5413 windows in the window config may be deleted.
5415 for (k = 0; k < config->saved_windows_count; k++) {
5416 p = SAVED_WINDOW_N(config, k);
5417 w = XWINDOW(p->window);
5420 /* The window might be dead. In this case, its redisplay
5421 structures were freed, so we need to reallocate them. */
5422 if (!w->face_cachels) {
5423 w->face_cachels = Dynarr_new(face_cachel);
5424 reset_face_cachels(w);
5426 if (!w->glyph_cachels)
5427 w->glyph_cachels = Dynarr_new(glyph_cachel);
5428 if (!w->line_start_cache)
5429 w->line_start_cache =
5430 Dynarr_new(line_start_cache);
5431 w->gutter_extent_modiff[0] = 0;
5432 w->gutter_extent_modiff[1] = 0;
5433 w->gutter_extent_modiff[2] = 0;
5434 w->gutter_extent_modiff[3] = 0;
5437 if (p->parent_index >= 0)
5439 SAVED_WINDOW_N(config,
5440 p->parent_index)->window;
5444 if (p->prev_index >= 0) {
5446 SAVED_WINDOW_N(config,
5447 p->prev_index)->window;
5449 /* This is true for a minibuffer-only frame. */
5450 if (!NILP(w->mini_p) && EQ(w->prev, p->window))
5453 XWINDOW(w->prev)->next = p->window;
5456 if (!NILP(w->parent)) {
5457 if (WINDOW_WIDTH(p) ==
5458 WINDOW_WIDTH(XWINDOW(w->parent))) {
5459 XWINDOW(w->parent)->vchild =
5461 XWINDOW(w->parent)->hchild =
5464 XWINDOW(w->parent)->hchild =
5466 XWINDOW(w->parent)->vchild =
5471 if (!w->config_mark) {
5472 /* #### This should be equivalent to the window previously
5473 having been dead. If we're brave, we'll put in an
5474 assertion to this effect. */
5475 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
5476 } else { /* if (!EQ (w->buffer, p->buffer)) */
5478 /* With the new redisplay we let it know that a change has
5479 been made and it will take care of the rest. If we don't
5480 tell it something has possibly changed it could lead to
5481 incorrect display. */
5482 MARK_WINDOWS_CHANGED(w);
5485 WINDOW_LEFT(w) = WINDOW_LEFT(p);
5486 WINDOW_TOP(w) = WINDOW_TOP(p);
5487 WINDOW_WIDTH(w) = WINDOW_WIDTH(p);
5488 WINDOW_HEIGHT(w) = WINDOW_HEIGHT(p);
5489 w->hscroll = p->hscroll;
5490 w->modeline_hscroll = p->modeline_hscroll;
5491 w->line_cache_last_updated = Qzero;
5492 /* When we restore a window's configuration, the identity of
5493 the window hasn't actually changed - so there is no
5494 reason why we shouldn't preserve the instance cache for
5495 it - unless it was originally deleted. This will often
5496 buy us something as we will not have to re-instantiate
5497 all the instances. This is because this is an instance
5498 cache - not a display cache. Preserving the display cache
5499 would definitely be wrong.
5501 We specifically want to do this for tabs, since for some
5502 reason finding a file will cause the configuration to be
5504 if (NILP(w->subwindow_instance_cache))
5505 w->subwindow_instance_cache =
5506 make_image_instance_cache_hash_table();
5508 SET_LAST_MODIFIED(w, 1);
5509 SET_LAST_FACECHANGE(w);
5512 /* #### Consider making the instance cache a winslot. */
5513 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5514 #include "winslots.h"
5516 /* Reinstall the saved buffer and pointers into it. */
5517 if (NILP(p->buffer))
5518 w->buffer = p->buffer;
5520 if (BUFFER_LIVE_P(XBUFFER(p->buffer)))
5521 /* If saved buffer is alive, install it. */
5523 w->buffer = p->buffer;
5524 w->start_at_line_beg =
5525 p->start_at_line_beg;
5526 set_marker_restricted(w->
5532 set_marker_restricted(w->
5538 set_marker_restricted(w->sb_point,
5542 Fset_marker(XBUFFER(w->buffer)->mark,
5543 Fmarker_position(p->mark),
5546 /* As documented in Fcurrent_window_configuration, don't
5547 save the location of point in the buffer which was current
5548 when the window configuration was recorded. */
5549 if (!EQ(p->buffer, new_current_buffer)
5550 && XBUFFER(p->buffer) ==
5553 pointm[CURRENT_DISP],
5555 } else if (NILP(w->buffer)
5557 !BUFFER_LIVE_P(XBUFFER(w->buffer)))
5558 /* Else if window's old buffer is dead too, get a live one. */
5560 /* #### The following line makes me nervous... */
5561 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist)); */
5563 Fget_buffer_create(QSscratch);
5564 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5565 /* This will set the markers to beginning of visible
5567 set_marker_restricted(w->
5571 set_marker_restricted(w->
5575 set_marker_restricted(w->sb_point,
5577 w->start_at_line_beg = 1;
5579 /* Keeping window's old buffer; make sure the markers
5582 /* Set window markers at start of visible range. */
5583 if (XMARKER(w->start[CURRENT_DISP])->
5585 set_marker_restricted(w->
5591 if (XMARKER(w->sb_point)->buffer == 0)
5592 set_marker_restricted(w->
5597 if (XMARKER(w->pointm[CURRENT_DISP])->
5599 set_marker_restricted(w->
5609 w->start_at_line_beg = 1;
5614 FRAME_ROOT_WINDOW(f) = config->root_window;
5615 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5616 then calls do_switch_frame() below to select the frame that was
5617 recorded in the window config as being selected.
5619 Instead, we don't ever change the selected frame, and either
5620 call Fselect_window() below if the window config's frame is
5621 currently selected, or just set the selected window of the
5622 window config's frame. */
5625 /* Set the frame height to the value it had before this function. */
5626 if (previous_frame_height != FRAME_HEIGHT(f)
5627 || previous_frame_width != FRAME_WIDTH(f))
5628 change_frame_size(f, previous_frame_height,
5629 previous_frame_width, 0);
5631 /* We just reset the size and position of the minibuffer, to its old
5632 value, which needn't be valid. So we do some magic to see which value
5633 to actually take. Then we set it.
5636 We take the old value if is in the same units but differs from the
5639 #### Now we get more cases correct then ever before, but
5640 are we treating all? For instance what if the frames minibuf window
5641 is no longer the same one?
5643 target_minibuf_height = previous_minibuf_height;
5644 if (converted_minibuf_height &&
5645 (converted_minibuf_height * config->minibuf_height) > 0 &&
5646 (converted_minibuf_height != config->minibuf_height)) {
5647 target_minibuf_height = config->minibuf_height < 0 ?
5648 -(config->minibuf_height * real_font_height) :
5649 config->minibuf_height;
5650 target_minibuf_height =
5651 max(target_minibuf_height, real_font_height);
5653 if (previous_minibuf_height) {
5654 XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top
5655 = previous_minibuf_top -
5656 (target_minibuf_height - previous_minibuf_height);
5657 set_window_pixheight(FRAME_MINIBUF_WINDOW(f),
5658 target_minibuf_height, 0);
5659 set_window_pixwidth(FRAME_MINIBUF_WINDOW(f),
5660 previous_minibuf_width, 0);
5663 /* This is a better way to deal with frame resizing, etc.
5664 What we _actually_ want is for the old (just restored)
5666 into the place of the new one. So we just do that. Simple! */
5667 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top = previous_pixel_top;
5668 /* Note that this function also updates the subwindow
5670 set_window_pixheight(FRAME_ROOT_WINDOW(f),
5671 previous_pixel_height -
5672 (target_minibuf_height -
5673 previous_minibuf_height), 0);
5674 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left = previous_pixel_left;
5675 /* Note that this function also updates the subwindow
5677 set_window_pixwidth(FRAME_ROOT_WINDOW(f), previous_pixel_width,
5680 /* If restoring in the current frame make the window current,
5681 otherwise just update the frame selected_window slot to be
5682 the restored current_window. */
5683 if (f == selected_frame()) {
5685 /* When using `pop-window-configuration', often the minibuffer
5686 ends up as the selected window even though it's not active ...
5687 I really don't know the cause of this, but it should never
5688 happen. This kludge should fix it.
5690 #### Find out why this is really going wrong. */
5691 if (!minibuf_level &&
5692 MINI_WINDOW_P(XWINDOW(config->current_window)))
5694 Fnext_window(config->current_window, Qnil,
5697 window_to_select = config->current_window;
5699 /* Do this last so that buffer stacking is calculated
5701 Fselect_window(config->current_window, Qnil);
5703 if (!NILP(new_current_buffer)) {
5704 Fset_buffer(new_current_buffer);
5705 Frecord_buffer(new_current_buffer);
5707 Fset_buffer(XWINDOW(config->current_window)->
5709 Frecord_buffer(XWINDOW(config->current_window)->
5713 set_frame_selected_window(f, config->current_window);
5715 old_window_config = Qnil; /* Warning suppression */
5717 /* Restore the minimum heights recorded in the configuration. */
5718 window_min_height = config->min_height;
5719 window_min_width = config->min_width;
5722 /* see above comment */
5723 /* Fselect_window will have made f the selected frame, so we
5724 reselect the proper frame here. Fhandle_switch_frame will change the
5725 selected window too, but that doesn't make the call to
5726 Fselect_window above totally superfluous; it still sets f's
5728 if (FRAME_LIVE_P(XFRAME(config->selected_frame)))
5729 do_switch_frame(config->selected_frame, Qnil, 0);
5732 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5734 if (FRAME_LIVE_P(f)) {
5735 /* Do this before calling recompute_all_cached_specifiers_in_window()
5736 so that things like redisplay_redraw_cursor() won't abort due
5737 to no window mirror present. */
5738 f->mirror_dirty = 1;
5740 config = XWINDOW_CONFIGURATION(old_window_config);
5741 for (k = 0; k < config->saved_windows_count; k++) {
5742 p = SAVED_WINDOW_N(config, k);
5743 w = XWINDOW(p->window);
5744 /* Remember, we set w->config_mark on all currently visible
5745 windows, and reset it on all newly visible windows.
5746 Any windows still marked need to be deleted. */
5747 if (w->config_mark) {
5748 mark_window_as_deleted(w);
5751 /* We just potentially changed the window's buffer and
5752 potentially turned a dead window into a live one,
5753 so we need to recompute the cached specifier values. */
5754 recompute_all_cached_specifiers_in_window(w);
5759 /* Now restore things, when everything else if OK. */
5761 unbind_to(specpdl_count, Qnil);
5768 /* Mark all subwindows of a window as deleted. The argument
5769 W is actually the subwindow tree of the window in question. */
5771 void delete_all_subwindows(struct window *w)
5774 delete_all_subwindows(XWINDOW(w->next));
5775 if (!NILP(w->vchild))
5776 delete_all_subwindows(XWINDOW(w->vchild));
5777 if (!NILP(w->hchild))
5778 delete_all_subwindows(XWINDOW(w->hchild));
5780 mark_window_as_deleted(w);
5783 static unsigned int count_windows(struct window *window)
5786 (!NILP(window->next) ? count_windows(XWINDOW(window->next)) : 0) +
5787 (!NILP(window->vchild) ? count_windows(XWINDOW(window->vchild)) : 0)
5789 (!NILP(window->hchild) ? count_windows(XWINDOW(window->hchild)) :
5794 saved_window_index(Lisp_Object window, struct window_config *config, int lim)
5797 for (j = 0; j < lim; j++) {
5798 if (EQ(SAVED_WINDOW_N(config, j)->window, window))
5802 return 0; /* suppress compiler warning */
5806 save_window_save(Lisp_Object window, struct window_config *config, int i)
5810 for (; !NILP(window); window = w->next) {
5811 struct saved_window *p = SAVED_WINDOW_N(config, i);
5813 w = XWINDOW(window);
5816 p->buffer = w->buffer;
5817 WINDOW_LEFT(p) = WINDOW_LEFT(w);
5818 WINDOW_TOP(p) = WINDOW_TOP(w);
5819 WINDOW_WIDTH(p) = WINDOW_WIDTH(w);
5820 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(w);
5821 p->hscroll = w->hscroll;
5822 p->modeline_hscroll = w->modeline_hscroll;
5824 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5825 #include "winslots.h"
5827 if (!NILP(w->buffer)) {
5828 /* Save w's value of point in the window configuration.
5829 If w is the selected window, then get the value of point
5830 from the buffer; pointm is garbage in the selected window. */
5831 if (EQ(window, Fselected_window(Qnil))) {
5832 p->pointm = noseeum_make_marker();
5833 Fset_marker(p->pointm,
5835 (XBUFFER(w->buffer))),
5839 noseeum_copy_marker(w->pointm[CURRENT_DISP],
5843 noseeum_copy_marker(w->start[CURRENT_DISP], Qnil);
5844 p->sb_point = noseeum_copy_marker(w->sb_point, Qnil);
5845 p->start_at_line_beg = w->start_at_line_beg;
5848 noseeum_copy_marker(XBUFFER(w->buffer)->mark, Qnil);
5854 p->start_at_line_beg = 0;
5857 if (NILP(w->parent))
5858 p->parent_index = -1;
5861 saved_window_index(w->parent, config, i);
5865 p->prev_index = saved_window_index(w->prev, config, i);
5866 if (!NILP(w->vchild))
5867 i = save_window_save(w->vchild, config, i);
5868 if (!NILP(w->hchild))
5869 i = save_window_save(w->hchild, config, i);
5876 /* Added to doc string:
5878 This also records the currently selected frame, and FRAME's focus
5879 redirection (see `redirect-frame-focus').
5884 DEFUN("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5885 Return an object representing the current window configuration of FRAME.
5886 If FRAME is nil or omitted, use the selected frame.
5887 This describes the number of windows, their sizes and current buffers,
5888 and for each window on FRAME the displayed buffer, where display
5889 starts, and the positions of point and mark.
5890 An exception is made for point in the current buffer:
5891 its value is -not- saved.
5896 struct frame *f = decode_frame(frame);
5897 struct window_config *config;
5898 unsigned int n_windows = count_windows(XWINDOW(FRAME_ROOT_WINDOW(f)));
5900 int real_font_height;
5902 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5903 config = (struct window_config *)
5904 alloc_lcrecord(sizeof_window_config_for_n_windows(
5906 &lrecord_window_configuration);
5908 if (n_windows <= countof(Vwindow_configuration_free_list)) {
5910 allocate_managed_lcrecord(
5911 Vwindow_configuration_free_list[n_windows - 1]);
5912 config = XWINDOW_CONFIGURATION(tmp);
5914 /* More than ten windows; just allocate directly */
5915 config = (struct window_config *)
5916 alloc_lcrecord(sizeof_window_config_for_n_windows(
5918 &lrecord_window_configuration);
5921 XSETWINDOW_CONFIGURATION(result, config);
5923 config->frame_width = FRAME_WIDTH (f);
5924 config->frame_height = FRAME_HEIGHT (f); */
5925 /* #### When using `push-window-configuration', often the minibuffer
5926 ends up as the selected window because functions run as the result
5927 of user interaction e.g. hyper-apropos. It seems to me the sensible
5928 thing to do is not record the minibuffer here.
5930 #### Unfortunately this is a change to previous behaviour,
5931 however logical it may be, so revert for the moment. */
5933 if (FRAME_MINIBUF_ONLY_P(f) || minibuf_level)
5934 config->current_window = FRAME_SELECTED_WINDOW(f);
5936 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW(f);
5938 config->current_window = FRAME_SELECTED_WINDOW(f);
5939 XSETBUFFER(config->current_buffer, current_buffer);
5940 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5941 config->root_window = FRAME_ROOT_WINDOW(f);
5942 config->min_height = window_min_height;
5943 config->min_width = window_min_width;
5944 config->saved_windows_count = n_windows;
5945 save_window_save(FRAME_ROOT_WINDOW(f), config, 0);
5947 /* save the minibuffer height using the heuristics from
5948 change_frame_size_1 */
5950 XSETFRAME(frame, f); /* frame could have been nil ! */
5951 default_face_height_and_width(frame, &real_font_height, 0);
5952 assert(real_font_height > 0);
5954 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f))
5955 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5958 config->minibuf_height = (minibuf_height % real_font_height) == 0 ? -(minibuf_height / real_font_height) : /* lines */
5959 minibuf_height; /* pixels */
5964 Lisp_Object save_window_excursion_unwind(Lisp_Object window_config)
5966 Lisp_Object val = Fset_window_configuration(window_config);
5967 free_window_configuration(window_config);
5971 DEFUN("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5972 Execute body, preserving window sizes and contents.
5973 Restores which buffer appears in which window, where display starts,
5974 as well as the current buffer.
5975 Does not restore the value of point in current buffer.
5979 /* This function can GC */
5981 int speccount = specpdl_depth();
5983 record_unwind_protect(save_window_excursion_unwind,
5984 Fcurrent_window_configuration(Qnil));
5986 return unbind_to(speccount, val);
5989 DEFUN("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5990 Return the horizontal pixel position of POS in window.
5991 Beginning of line is column 0. This is calculated using the redisplay
5992 display tables. If WINDOW is nil, the current window is assumed.
5993 If POS is nil, point is assumed. Note that POS must be visible for
5994 a non-nil result to be returned.
5998 struct window *w = decode_window(window);
5999 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
6001 struct display_line *dl = 0;
6002 struct display_block *db = 0;
6003 struct rune *rb = 0;
6004 int y = w->last_point_y[CURRENT_DISP];
6005 int x = w->last_point_x[CURRENT_DISP];
6007 if (MINI_WINDOW_P(w))
6010 if (y < 0 || x < 0 || y >= Dynarr_length(dla) || !NILP(pos)) {
6015 pos = Fwindow_point(window);
6020 if (Dynarr_length(dla) && Dynarr_atp(dla, 0)->modeline)
6025 for (i = first_line; i < Dynarr_length(dla); i++) {
6026 dl = Dynarr_atp(dla, i);
6027 /* find the vertical location first */
6028 if (point >= dl->bufpos && point <= dl->end_bufpos) {
6029 db = get_display_block_from_line(dl, TEXT);
6030 for (i = 0; i < Dynarr_length(db->runes); i++) {
6031 rb = Dynarr_atp(db->runes, i);
6032 if (point <= rb->bufpos)
6042 /* optimized case */
6043 dl = Dynarr_atp(dla, y);
6044 db = get_display_block_from_line(dl, TEXT);
6046 if (x >= Dynarr_length(db->runes))
6049 rb = Dynarr_atp(db->runes, x);
6052 return make_int(rb->xpos - WINDOW_LEFT(w));
6055 #ifdef DEBUG_SXEMACS
6056 /* This is short and simple in elisp, but... it was written to debug
6057 problems purely on the C side. That is where we need to call it so
6059 static void debug_print_window(Lisp_Object window, int level)
6062 Lisp_Object child = Fwindow_first_vchild(window);
6065 child = Fwindow_first_hchild(window);
6067 for (i = level; i > 0; i--)
6070 stderr_out("#<window");
6072 Lisp_Object buffer = XWINDOW(window)->buffer;
6073 if (!NILP(buffer) && BUFFERP(buffer))
6074 stderr_out(" on %s",
6075 XSTRING_DATA(XBUFFER(buffer)->name));
6077 stderr_out(" 0x%x>", XWINDOW(window)->header.uid);
6079 while (!NILP(child)) {
6080 debug_print_window(child, level + 1);
6081 child = Fwindow_next_child(child);
6085 void debug_print_windows(struct frame *f);
6086 void debug_print_windows(struct frame *f)
6088 debug_print_window(f->root_window, 0);
6091 #endif /* DEBUG_SXEMACS */
6093 /************************************************************************/
6094 /* initialization */
6095 /************************************************************************/
6097 void syms_of_window(void)
6099 INIT_LRECORD_IMPLEMENTATION(window);
6100 INIT_LRECORD_IMPLEMENTATION(window_configuration);
6102 defsymbol(&Qwindowp, "windowp");
6103 defsymbol(&Qwindow_live_p, "window-live-p");
6104 defsymbol(&Qwindow_configurationp, "window-configuration-p");
6105 defsymbol(&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6106 defsymbol(&Qdisplay_buffer, "display-buffer");
6108 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6109 defsymbol(&Qface_cache, "face-cache");
6110 defsymbol(&Qglyph_cache, "glyph-cache");
6111 defsymbol(&Qline_start_cache, "line-start-cache");
6112 #ifdef HAVE_SCROLLBARS
6113 defsymbol(&Qscrollbar_instances, "scrollbar-instances");
6115 defsymbol(&Qother_redisplay, "other-redisplay");
6116 /* Qother in general.c */
6119 DEFSYMBOL(Qtruncate_partial_width_windows);
6120 DEFSYMBOL (Qwindow_configuration_hook);
6122 DEFSUBR(Fselected_window);
6123 DEFSUBR(Flast_nonminibuf_window);
6124 DEFSUBR(Fminibuffer_window);
6125 DEFSUBR(Fwindow_minibuffer_p);
6127 DEFSUBR(Fwindow_live_p);
6128 DEFSUBR(Fwindow_first_hchild);
6129 DEFSUBR(Fwindow_first_vchild);
6130 DEFSUBR(Fwindow_next_child);
6131 DEFSUBR(Fwindow_previous_child);
6132 DEFSUBR(Fwindow_parent);
6133 DEFSUBR(Fwindow_lowest_p);
6134 DEFSUBR(Fwindow_truncated_p);
6135 DEFSUBR(Fwindow_highest_p);
6136 DEFSUBR(Fwindow_leftmost_p);
6137 DEFSUBR(Fwindow_rightmost_p);
6138 DEFSUBR(Fpos_visible_in_window_p);
6139 DEFSUBR(Fwindow_buffer);
6140 DEFSUBR(Fwindow_frame);
6141 DEFSUBR(Fwindow_height);
6142 DEFSUBR(Fwindow_displayed_height);
6143 DEFSUBR(Fwindow_width);
6144 DEFSUBR(Fwindow_full_width);
6145 DEFSUBR(Fwindow_pixel_height);
6146 DEFSUBR(Fwindow_pixel_width);
6147 DEFSUBR(Fwindow_text_area_height);
6148 DEFSUBR(Fwindow_text_area_pixel_height);
6149 DEFSUBR(Fwindow_displayed_text_pixel_height);
6150 DEFSUBR(Fwindow_text_area_pixel_width);
6151 DEFSUBR(Fwindow_hscroll);
6152 DEFSUBR(Fset_window_hscroll);
6153 DEFSUBR(Fmodeline_hscroll);
6154 DEFSUBR(Fset_modeline_hscroll);
6155 #if 0 /* bogus FSF crock */
6156 DEFSUBR(Fwindow_redisplay_end_trigger);
6157 DEFSUBR(Fset_window_redisplay_end_trigger);
6159 DEFSUBR(Fwindow_pixel_edges);
6160 DEFSUBR(Fwindow_text_area_pixel_edges);
6161 DEFSUBR(Fwindow_point);
6162 DEFSUBR(Fwindow_start);
6163 DEFSUBR(Fwindow_end);
6164 DEFSUBR(Fwindow_last_line_visible_height);
6165 DEFSUBR(Fset_window_point);
6166 DEFSUBR(Fset_window_start);
6167 DEFSUBR(Fwindow_dedicated_p);
6168 DEFSUBR(Fset_window_dedicated_p);
6169 DEFSUBR(Fnext_window);
6170 DEFSUBR(Fprevious_window);
6171 DEFSUBR(Fnext_vertical_window);
6172 DEFSUBR(Fother_window);
6173 DEFSUBR(Fget_lru_window);
6174 DEFSUBR(Fget_largest_window);
6175 DEFSUBR(Fget_buffer_window);
6176 DEFSUBR(Fwindow_left_margin_pixel_width);
6177 DEFSUBR(Fwindow_right_margin_pixel_width);
6178 DEFSUBR(Fdelete_other_windows);
6179 DEFSUBR(Fdelete_windows_on);
6180 DEFSUBR(Freplace_buffer_in_windows);
6181 DEFSUBR(Fdelete_window);
6182 DEFSUBR(Fset_window_buffer);
6183 DEFSUBR(Fselect_window);
6184 DEFSUBR(Fsplit_window);
6185 DEFSUBR(Fenlarge_window);
6186 DEFSUBR(Fenlarge_window_pixels);
6187 DEFSUBR(Fshrink_window);
6188 DEFSUBR(Fshrink_window_pixels);
6189 DEFSUBR(Fscroll_up);
6190 DEFSUBR(Fscroll_down);
6191 DEFSUBR(Fscroll_left);
6192 DEFSUBR(Fscroll_right);
6193 DEFSUBR(Fother_window_for_scrolling);
6194 DEFSUBR(Fscroll_other_window);
6195 DEFSUBR(Fcenter_to_window_line);
6196 DEFSUBR(Fmove_to_window_line);
6197 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6198 DEFSUBR(Fwindow_memory_usage);
6200 DEFSUBR(Fwindow_configuration_p);
6201 DEFSUBR(Fset_window_configuration);
6202 DEFSUBR(Fcurrent_window_configuration);
6203 DEFSUBR(Fsave_window_excursion);
6204 DEFSUBR(Fcurrent_pixel_column);
6207 void reinit_vars_of_window(void)
6209 /* Make sure all windows get marked */
6210 minibuf_window = Qnil;
6211 staticpro_nodump(&minibuf_window);
6213 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
6214 for (unsigned int i = 0;
6215 i < countof(Vwindow_configuration_free_list); i++) {
6216 Vwindow_configuration_free_list[i] =
6217 make_lcrecord_list(sizeof_window_config_for_n_windows(
6219 &lrecord_window_configuration);
6220 staticpro_nodump(&Vwindow_configuration_free_list[i]);
6226 void vars_of_window(void)
6228 reinit_vars_of_window();
6230 DEFVAR_BOOL("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6231 *Non-nil means to scroll if point lands on a line which is clipped.
6233 scroll_on_clipped_lines = 1;
6235 DEFVAR_LISP("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6236 See `temp-buffer-show-function'.
6238 Vtemp_buffer_show_hook = Qnil;
6240 DEFVAR_LISP("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6241 Non-nil means call as function to display a help buffer.
6242 The function is called with one argument, the buffer to be displayed.
6243 Used by `with-output-to-temp-buffer'.
6244 If this function is used, then it must do the entire job of showing
6245 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6246 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6248 Vtemp_buffer_show_function = Qnil;
6250 DEFVAR_LISP("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6251 Non-nil means it is the window that
6252 \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should
6255 Vminibuffer_scroll_window = Qnil;
6257 DEFVAR_LISP("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6258 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6260 Vother_window_scroll_buffer = Qnil;
6262 DEFVAR_LISP("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6263 *Number of pixels to scroll by per requested line.
6264 If nil then normal line scrolling occurs regardless of line height.
6265 If t then scrolling is done in increments equal to the height of the default face.
6267 Vwindow_pixel_scroll_increment = Qt;
6269 DEFVAR_LISP ("window-configuration-hook", &Vwindow_configuration_hook /*
6270 Function(s) to call when a frame's window configuration has changed.
6272 Please see (Info-goto-node "(lispref)Window Configuration Hook") where all the
6273 details are documented.
6276 Vwindow_configuration_hook = Qnil;
6279 DEFVAR_INT("next-screen-context-lines", &next_screen_context_lines /*
6280 *Number of lines of continuity when scrolling by screenfuls.
6282 next_screen_context_lines = 2;
6284 DEFVAR_INT("window-min-height", &window_min_height /*
6285 *Delete any window less than this tall (including its modeline).
6287 window_min_height = 4;
6289 DEFVAR_INT("window-min-width", &window_min_width /*
6290 *Delete any window less than this wide.
6292 window_min_width = 10;
6295 void specifier_vars_of_window(void)
6297 DEFVAR_SPECIFIER("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6298 *How thick to draw 3D shadows around modelines.
6299 If this is set to 0, modelines will be the traditional 2D. Sizes above
6300 10 will be accepted but the maximum thickness that will be drawn is 10.
6301 This is a specifier; use `set-specifier' to change it.
6303 Vmodeline_shadow_thickness = Fmake_specifier(Qinteger);
6304 /* The initial value for modeline-shadow-thickness is 2, but if the
6305 user removes all specifications we provide a fallback value of 0,
6306 which is probably what was expected. */
6307 set_specifier_fallback(Vmodeline_shadow_thickness,
6308 list1(Fcons(Qnil, Qzero)));
6309 Fadd_spec_to_specifier(Vmodeline_shadow_thickness, make_int(2),
6311 set_specifier_caching(Vmodeline_shadow_thickness,
6312 offsetof(struct window,
6313 modeline_shadow_thickness),
6314 modeline_shadow_thickness_changed, 0, 0, 0);
6316 DEFVAR_SPECIFIER("has-modeline-p", &Vhas_modeline_p /*
6317 *Whether the modeline should be displayed.
6318 This is a specifier; use `set-specifier' to change it.
6320 Vhas_modeline_p = Fmake_specifier(Qboolean);
6321 set_specifier_fallback(Vhas_modeline_p, list1(Fcons(Qnil, Qt)));
6322 set_specifier_caching(Vhas_modeline_p,
6323 offsetof(struct window, has_modeline_p),
6324 /* #### It's strange that we need a special
6325 flag to indicate that the shadow-thickness
6326 has changed, but not one to indicate that
6327 the modeline has been turned off or on. */
6328 some_window_value_changed, 0, 0, 0);
6330 DEFVAR_SPECIFIER("vertical-divider-always-visible-p", &Vvertical_divider_always_visible_p /*
6331 *Should SXEmacs always display vertical dividers between windows.
6333 When this is non-nil, vertical dividers are always shown, and are
6334 draggable. When it is nil, vertical dividers are shown only when
6335 there are no scrollbars in between windows, and are not draggable.
6337 This is a specifier; use `set-specifier' to change it.
6339 Vvertical_divider_always_visible_p = Fmake_specifier(Qboolean);
6340 set_specifier_fallback(Vvertical_divider_always_visible_p,
6341 list1(Fcons(Qnil, Qt)));
6342 set_specifier_caching(Vvertical_divider_always_visible_p,
6343 offsetof(struct window,
6344 vertical_divider_always_visible_p),
6345 vertical_divider_changed_in_window, 0, 0, 0);
6347 DEFVAR_SPECIFIER("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6348 *How thick to draw 3D shadows around vertical dividers.
6349 This is a specifier; use `set-specifier' to change it.
6351 Vvertical_divider_shadow_thickness = Fmake_specifier(Qinteger);
6352 set_specifier_fallback(Vvertical_divider_shadow_thickness,
6353 list1(Fcons(Qnil, Qzero)));
6354 Fadd_spec_to_specifier(Vvertical_divider_shadow_thickness, make_int(2),
6356 set_specifier_caching(Vvertical_divider_shadow_thickness,
6357 offsetof(struct window,
6358 vertical_divider_shadow_thickness),
6359 vertical_divider_changed_in_window, 0, 0, 0);
6360 DEFVAR_SPECIFIER("vertical-divider-line-width", &Vvertical_divider_line_width /*
6361 *The width of the vertical dividers, not including shadows.
6363 For TTY windows, divider line is always one character wide. When
6364 instance of this specifier is zero in a TTY window, no divider is
6365 drawn at all between windows. When non-zero, a one character wide
6366 divider is displayed.
6368 This is a specifier; use `set-specifier' to change it.
6371 Vvertical_divider_line_width = Fmake_specifier(Qnatnum);
6373 Lisp_Object fb = Qnil;
6375 fb = Fcons(Fcons(list1(Qtty), make_int(1)), fb);
6377 #ifdef HAVE_X_WINDOWS
6378 fb = Fcons(Fcons(list1(Qx), make_int(3)), fb);
6380 set_specifier_fallback(Vvertical_divider_line_width, fb);
6382 set_specifier_caching(Vvertical_divider_line_width,
6383 offsetof(struct window,
6384 vertical_divider_line_width),
6385 vertical_divider_changed_in_window, 0, 0, 0);
6387 DEFVAR_SPECIFIER("vertical-divider-spacing", &Vvertical_divider_spacing /*
6388 *How much space to leave around the vertical dividers.
6390 In TTY windows, spacing is always zero, and the value of this
6391 specifier is ignored.
6393 This is a specifier; use `set-specifier' to change it.
6395 Vvertical_divider_spacing = Fmake_specifier(Qnatnum);
6397 Lisp_Object fb = Qnil;
6399 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
6401 #ifdef HAVE_X_WINDOWS
6402 /* #### 3D dividers look great on MS Windows with spacing = 0.
6403 Should not the same value be the fallback under X? - kkm */
6404 fb = Fcons(Fcons(list1(Qx), make_int(2)), fb);
6406 set_specifier_fallback(Vvertical_divider_spacing, fb);
6408 set_specifier_caching(Vvertical_divider_spacing,
6409 offsetof(struct window, vertical_divider_spacing),
6410 vertical_divider_changed_in_window, 0, 0, 0);