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;
1431 ((hlimit - height) * (nelt - elt) + height - 1) / height +
1435 RETURN_NOT_REACHED(make_int(0)) /* shut up compiler */
1438 DEFUN("window-width", Fwindow_width, 0, 1, 0, /*
1439 Return the number of display columns in WINDOW.
1440 This is the width that is usable columns available for text in WINDOW,
1441 and does not include vertical scrollbars, dividers, or the like. See also
1442 `window-full-width' and `window-height'.
1446 return make_int(window_char_width(decode_window(window), 0));
1449 DEFUN("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1450 Return the total number of columns in WINDOW.
1451 This is like `window-width' but includes vertical scrollbars, dividers,
1456 return make_int(window_char_width(decode_window(window), 1));
1459 DEFUN("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1460 Return the width of WINDOW in pixels. Defaults to current window.
1464 return make_int(decode_window(window)->pixel_width);
1467 DEFUN("window-text-area-pixel-width", Fwindow_text_area_pixel_width, 0, 1, 0, /*
1468 Return the width in pixels of the text-displaying portion of WINDOW.
1469 Unlike `window-pixel-width', the space occupied by the vertical
1470 scrollbar or divider, if any, is not counted.
1474 struct window *w = decode_window(window);
1476 return make_int(WINDOW_TEXT_WIDTH(w));
1479 DEFUN("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1480 Return the number of columns by which WINDOW is scrolled from left margin.
1484 return make_int(decode_window(window)->hscroll);
1487 DEFUN("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1488 Return the horizontal scrolling amount of WINDOW's modeline.
1489 If the window has no modeline, return nil.
1493 struct window *w = decode_window(window);
1495 return (WINDOW_HAS_MODELINE_P(w)) ? make_int((int)w->modeline_hscroll) :
1499 DEFUN("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1500 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1501 If NCOL is negative, it will silently be forced to 0.
1502 If the window has no modeline, return nil. Otherwise, return the actual
1507 struct window *w = decode_window(window);
1509 if (WINDOW_HAS_MODELINE_P(w)) {
1513 ncols = (XINT(ncol) <= 0) ? 0 : (Charcount) XINT(ncol);
1514 if (ncols != w->modeline_hscroll) {
1515 MARK_MODELINE_CHANGED;
1516 w->modeline_hscroll = ncols;
1518 return make_int((int)ncols);
1524 DEFUN("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1525 Set number of columns WINDOW is scrolled from left margin to NCOL.
1526 NCOL should be zero or positive.
1537 w = decode_window(window);
1538 if (w->hscroll != ncols)
1539 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1544 #if 0 /* bogus FSF crock */
1546 xxDEFUN("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1547 Return WINDOW's redisplay end trigger value.
1548 See `set-window-redisplay-end-trigger' for more information.
1552 return decode_window(window)->redisplay_end_trigger;
1555 xxDEFUN("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1556 Set WINDOW's redisplay end trigger value to VALUE.
1557 VALUE should be a buffer position (typically a marker) or nil.
1558 If it is a buffer position, then if redisplay in WINDOW reaches a position
1559 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1560 with two arguments: WINDOW, and the end trigger value.
1561 Afterwards the end-trigger value is reset to nil.
1565 return (decode_window(window)->redisplay_end_trigger = value);
1570 DEFUN("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1571 Return a list of the pixel edge coordinates of WINDOW.
1572 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1573 all relative to 0, 0 at the top left corner of WINDOW's frame.
1574 The frame toolbars, menubars and gutters are considered to be outside
1575 of this area, while the scrollbars are considered to be inside.
1579 struct window *w = decode_window(window);
1580 struct frame *f = XFRAME(w->frame);
1583 w->pixel_left - FRAME_LEFT_BORDER_END(f) -
1584 FRAME_LEFT_GUTTER_BOUNDS(f);
1586 w->pixel_top - FRAME_TOP_BORDER_END(f) - FRAME_TOP_GUTTER_BOUNDS(f);
1588 return list4(make_int(left),
1590 make_int(left + w->pixel_width),
1591 make_int(top + w->pixel_height));
1594 DEFUN("window-text-area-pixel-edges", Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1595 Return a list of the pixel edge coordinates of the text area of WINDOW.
1596 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1597 all relative to 0, 0 at the top left corner of the total area allocated
1598 to the window, which includes the scrollbars.
1602 struct window *w = decode_window(window);
1604 int left = window_left_gutter_width(w, /* modeline = */ 0);
1605 int top = window_top_gutter_height(w);
1606 int right = WINDOW_WIDTH(w) - window_right_gutter_width(w, 0);
1607 int bottom = WINDOW_HEIGHT(w) - window_bottom_gutter_height(w);
1609 return list4(make_int(left),
1610 make_int(top), make_int(right), make_int(bottom));
1613 DEFUN("window-point", Fwindow_point, 0, 1, 0, /*
1614 Return current value of point in WINDOW.
1615 For a non-selected window, this is the value point would have
1616 if that window were selected.
1618 Note that, when WINDOW is the selected window and its buffer
1619 is also currently selected, the value returned is the same as (point).
1620 It would be more strictly correct to return the `top-level' value
1621 of point, outside of any save-excursion forms.
1622 But that value is hard to find.
1626 struct window *w = decode_window(window);
1627 Lisp_Object tmp_win = Fselected_window(XFRAME(w->frame)->device);
1629 /* The special check for current buffer is necessary for this
1630 function to work as defined when called within an excursion. */
1631 if (w == XWINDOW(tmp_win)
1632 && current_buffer == XBUFFER(w->buffer)) {
1633 return Fpoint(Qnil);
1635 return Fmarker_position(w->pointm[CURRENT_DISP]);
1638 DEFUN("window-start", Fwindow_start, 0, 1, 0, /*
1639 Return position at which display currently starts in WINDOW.
1640 This is updated by redisplay or by calling `set-window-start'.
1644 return Fmarker_position(decode_window(window)->start[CURRENT_DISP]);
1647 DEFUN("window-end", Fwindow_end, 0, 2, 0, /*
1648 Return position at which display currently ends in WINDOW.
1649 This is updated by redisplay, when it runs to completion.
1650 Simply changing the buffer text or setting `window-start' does not
1651 update this value. WINDOW defaults to the selected window.
1653 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1654 to be the same value as this function would return at the end of the
1655 next full redisplay assuming nothing else changes in the meantime.
1656 This function is potentially much slower with this flag set.
1658 (window, guarantee))
1660 struct window *w = decode_window(window);
1662 if (NILP(guarantee)) {
1666 return make_int(BUF_Z(XBUFFER(buf)) -
1667 w->window_end_pos[CURRENT_DISP]);
1669 Bufpos startp = marker_position(w->start[CURRENT_DISP]);
1670 return make_int(end_of_last_line(w, startp));
1674 DEFUN("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1675 Return pixel height of visible part of last window line if it is clipped.
1676 If the last line is not clipped, return nil.
1680 struct window *w = decode_window(window);
1681 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
1682 int num_lines = Dynarr_length(dla);
1683 struct display_line *dl;
1685 /* No lines - no clipped lines */
1686 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp(dla, 0)->modeline))
1689 dl = Dynarr_atp(dla, num_lines - 1);
1693 return make_int(dl->ascent + dl->descent - dl->clip);
1696 DEFUN("set-window-point", Fset_window_point, 2, 2, 0, /*
1697 Make point value in WINDOW be at position POS in WINDOW's buffer.
1701 struct window *w = decode_window(window);
1702 Lisp_Object tmp_win;
1704 CHECK_INT_COERCE_MARKER(pos);
1706 tmp_win = Fselected_window(Qnil);
1707 if (w == XWINDOW(tmp_win)) {
1708 Fgoto_char(pos, Qnil);
1710 set_marker_restricted(w->pointm[CURRENT_DISP], pos, w->buffer);
1716 DEFUN("set-window-start", Fset_window_start, 2, 3, 0, /*
1717 Make display in WINDOW start at position POS in WINDOW's buffer.
1718 Optional third arg NOFORCE non-nil inhibits next redisplay
1719 from overriding motion of point in order to display at this exact start.
1721 (window, pos, noforce))
1723 struct window *w = decode_window(window);
1725 CHECK_INT_COERCE_MARKER(pos);
1726 set_marker_restricted(w->start[CURRENT_DISP], pos, w->buffer);
1727 /* this is not right, but much easier than doing what is right. */
1728 /* w->start_at_line_beg = 0; */
1729 /* WTF is the above supposed to mean? GE */
1730 w->start_at_line_beg = beginning_of_line_p(XBUFFER(w->buffer),
1736 w->redo_modeline = 1;
1737 SET_LAST_MODIFIED(w, 0);
1738 SET_LAST_FACECHANGE(w);
1740 MARK_WINDOWS_CHANGED(w);
1745 DEFUN("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1746 Return WINDOW's dedicated object, usually t or nil.
1747 See also `set-window-dedicated-p'.
1751 return decode_window(window)->dedicated;
1754 DEFUN("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1755 Control whether WINDOW is dedicated to the buffer it displays.
1756 If it is dedicated, Emacs will not automatically change
1757 which buffer appears in it.
1758 The second argument is the new value for the dedication flag;
1763 struct window *w = decode_window(window);
1765 w->dedicated = NILP(arg) ? Qnil : Qt;
1767 return w->dedicated;
1770 /* FSFmacs has window-display-table here. We have display table as a
1773 /* Record info on buffer window w is displaying
1774 when it is about to cease to display that buffer. */
1775 static void unshow_buffer(struct window *w)
1777 Lisp_Object buf = w->buffer;
1779 if (XBUFFER(buf) != XMARKER(w->pointm[CURRENT_DISP])->buffer)
1782 /* FSF disables this check, so I'll do it too. I hope it won't
1783 break things. --ben */
1785 if (w == XWINDOW(Fselected_window(Qnil))
1786 || !EQ(buf, XWINDOW(Fselected_window(Qnil))->buffer))
1787 /* Do this except when the selected window's buffer
1788 is being removed from some other window. */
1790 /* last_window_start records the start position that this buffer
1791 had in the last window to be disconnected from it. Now that
1792 this statement is unconditional, it is possible for the
1793 buffer to be displayed in the selected window, while
1794 last_window_start reflects another window which was recently
1795 showing the same buffer. Some people might say that might be
1796 a good thing. Let's see. */
1797 XBUFFER(buf)->last_window_start =
1798 marker_position(w->start[CURRENT_DISP]);
1800 /* Point in the selected window's buffer is actually stored in that
1801 buffer, and the window's pointm isn't used. So don't clobber point
1804 Lisp_Object tmp = Fselected_window(Qnil);
1805 if (!EQ(buf, XWINDOW(tmp)->buffer)) {
1806 struct buffer *b = XBUFFER(buf);
1807 BUF_SET_PT(b, bufpos_clip_to_bounds(
1810 w->pointm[CURRENT_DISP]),
1816 /* Put REPLACEMENT into the window structure in place of OLD. */
1817 static void replace_window(Lisp_Object old, Lisp_Object replacement)
1820 struct window *o = XWINDOW(old), *p = XWINDOW(replacement);
1822 /* If OLD is its frame's root_window, then replacement is the new
1823 root_window for that frame. */
1825 if (EQ(old, FRAME_ROOT_WINDOW(XFRAME(o->frame))))
1826 FRAME_ROOT_WINDOW(XFRAME(o->frame)) = replacement;
1828 WINDOW_LEFT(p) = WINDOW_LEFT(o);
1829 WINDOW_TOP(p) = WINDOW_TOP(o);
1830 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
1831 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
1833 p->next = tem = o->next;
1835 XWINDOW(tem)->prev = replacement;
1837 p->prev = tem = o->prev;
1839 XWINDOW(tem)->next = replacement;
1841 p->parent = tem = o->parent;
1843 if (EQ(XWINDOW(tem)->vchild, old))
1844 XWINDOW(tem)->vchild = replacement;
1845 if (EQ(XWINDOW(tem)->hchild, old))
1846 XWINDOW(tem)->hchild = replacement;
1849 /* #### Here, if replacement is a vertical combination
1850 and so is its new parent, we should make replacement's
1851 children be children of that parent instead. */
1853 ERROR_CHECK_SUBWINDOW_CACHE(p);
1856 static void window_unmap_subwindows(struct window *w)
1858 assert(!NILP(w->subwindow_instance_cache));
1859 elisp_maphash(unmap_subwindow_instance_cache_mapper,
1860 w->subwindow_instance_cache, (void *)1);
1863 /* we're deleting W; set the structure of W to indicate this. */
1865 static void mark_window_as_deleted(struct window *w)
1867 /* The window instance cache is going away now, so need to get the
1868 cachels reset by redisplay. */
1869 MARK_FRAME_SUBWINDOWS_CHANGED(XFRAME(WINDOW_FRAME(w)));
1871 /* The cache is going away. If we leave unmapping to
1872 reset_subwindow_cachels then we get in a situation where the
1873 domain (the window) has been deleted but we still need access to
1874 its attributes in order to unmap windows properly. Since the
1875 subwindows are going to get GC'd anyway as a result of the domain
1876 going away, it is safer to just unmap them all while we know the
1877 domain is still valid. */
1878 ERROR_CHECK_SUBWINDOW_CACHE(w);
1879 window_unmap_subwindows(w);
1882 (while t (split-window) (delete-window))
1883 we end up with a tree of deleted windows which are all connected
1884 through the `next' slot. This might not seem so bad, as they're
1885 deleted, and will presumably be GCed - but if even *one* of those
1886 windows is still being pointed to, by the user, or by a window
1887 configuration, then *all* of those windows stick around.
1889 Since the window-configuration code doesn't need any of the
1890 pointers to other windows (they are all recreated from the
1891 window-config data), we set them all to nil so that we
1892 are able to collect more actual garbage. */
1898 w->subwindow_instance_cache = Qnil;
1902 /* Free the extra data structures attached to windows immediately so
1903 they don't sit around consuming excess space. They will be
1904 reinitialized by the window-configuration code as necessary. */
1905 finalize_window((void *)w, 0);
1908 DEFUN("delete-window", Fdelete_window, 0, 2, "", /*
1909 Remove WINDOW from the display. Default is selected window.
1910 If window is the only one on its frame, the frame is deleted as well.
1911 Normally, you cannot delete the last non-minibuffer-only frame (you
1912 must use `save-buffers-kill-emacs' or `kill-emacs'). However, if
1913 optional second argument FORCE is non-nil, you can delete the last
1914 frame. (This will automatically call `save-buffers-kill-emacs'.)
1919 /* This function can GC if this is the only window in the frame */
1927 /* Note: this function is called by other C code on non-leaf
1930 /* Do the equivalent of decode_window() but don't error out on
1931 deleted window; it's OK to delete an already-deleted window. */
1933 window = Fselected_window(Qnil);
1935 CHECK_WINDOW(window);
1937 w = XWINDOW(window);
1939 /* It's okay to delete an already-deleted window. */
1940 if (!WINDOW_LIVE_P(w))
1943 frame = WINDOW_FRAME(w);
1945 d = XDEVICE(FRAME_DEVICE(f));
1947 if (TOP_LEVEL_WINDOW_P(w)) {
1948 if (NILP(memq_no_quit(frame, DEVICE_FRAME_LIST(d))))
1949 /* this frame isn't fully initialized yet; don't blow up. */
1952 if (MINI_WINDOW_P(XWINDOW(window)))
1953 error("Attempt to delete the minibuffer window");
1955 /* It has been suggested that it's a good thing for C-x 0 to have this
1956 behavior, but not such a good idea for #'delete-window to have it.
1957 Maybe C-x 0 should be bound to something else, or maybe frame
1958 deletion should only happen when this is called interactively.
1960 delete_frame_internal(f, !NILP(force), 0, 0);
1964 /* At this point, we know the window has a parent. */
1966 par = XWINDOW(parent);
1968 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1969 /* It's quite likely that deleting a window will result in
1970 subwindows needing to be deleted also (since they are cached
1971 per-window). So we mark them as changed, so that the cachels will
1972 get reset by redisplay and thus deleted subwindows can get
1974 MARK_FRAME_SUBWINDOWS_CHANGED(f);
1976 /* Are we trying to delete any frame's selected window?
1977 Note that we could be dealing with a non-leaf window
1978 where the selected window is one of our children.
1979 So, we check by scanning all the ancestors of the
1980 frame's selected window and comparing each one with
1983 Lisp_Object pwindow;
1985 pwindow = FRAME_SELECTED_WINDOW(f);
1987 while (!NILP(pwindow)) {
1988 if (EQ(window, pwindow))
1990 pwindow = XWINDOW(pwindow)->parent;
1993 if (EQ(window, pwindow)) {
1994 /* OK, we found it. */
1995 Lisp_Object alternative;
1996 alternative = Fnext_window(window, Qlambda, Qnil, Qnil);
1998 /* If we're about to delete the selected window on the
1999 selected frame, then we should use Fselect_window to select
2000 the new window. On the other hand, if we're about to
2001 delete the selected window on any other frame, we shouldn't do
2002 anything but set the frame's selected_window slot. */
2003 if (EQ(frame, Fselected_frame(Qnil)))
2004 Fselect_window(alternative, Qnil);
2006 set_frame_selected_window(f, alternative);
2010 /* w->buffer is nil in a non-leaf window; in this case,
2011 get rid of the markers we maintain that point into that buffer. */
2012 if (!NILP(w->buffer)) {
2014 unchain_marker(w->pointm[CURRENT_DISP]);
2015 unchain_marker(w->pointm[DESIRED_DISP]);
2016 unchain_marker(w->pointm[CMOTION_DISP]);
2017 unchain_marker(w->start[CURRENT_DISP]);
2018 unchain_marker(w->start[DESIRED_DISP]);
2019 unchain_marker(w->start[CMOTION_DISP]);
2020 unchain_marker(w->sb_point);
2021 /* This breaks set-window-configuration if windows in the saved
2022 configuration get deleted and multiple frames are in use. */
2023 /* w->buffer = Qnil; */
2026 /* close up the hole in the sibling list */
2028 XWINDOW(w->next)->prev = w->prev;
2030 XWINDOW(w->prev)->next = w->next;
2031 if (EQ(window, par->hchild))
2032 par->hchild = w->next;
2033 if (EQ(window, par->vchild))
2034 par->vchild = w->next;
2036 /* Find one of our siblings to give our space to. */
2038 Lisp_Object sib = w->prev;
2040 /* If w gives its space to its next sibling, that sibling needs
2041 to have its top/left side pulled back to where w's is.
2042 set_window_{height,width} will re-position the sibling's
2045 WINDOW_TOP(XWINDOW(sib)) = WINDOW_TOP(w);
2046 WINDOW_LEFT(XWINDOW(sib)) = WINDOW_LEFT(w);
2049 /* Stretch that sibling. */
2050 if (!NILP(par->vchild))
2051 set_window_pixheight
2053 (WINDOW_HEIGHT(XWINDOW(sib)) + WINDOW_HEIGHT(w)),
2055 if (!NILP(par->hchild))
2058 (WINDOW_WIDTH(XWINDOW(sib)) + WINDOW_WIDTH(w)), 1);
2061 run_window_configuration_hook( sib );
2065 /* If parent now has only one child,
2066 put the child into the parent's place. */
2068 Lisp_Object parchild = par->hchild;
2070 parchild = par->vchild;
2071 if (NILP(XWINDOW(parchild)->next)) {
2072 replace_window(parent, parchild);
2073 mark_window_as_deleted(XWINDOW(parent));
2077 /* Since we may be deleting combination windows, we must make sure that
2078 not only W but all its children have been marked as deleted. */
2079 if (!NILP(w->hchild))
2080 delete_all_subwindows(XWINDOW(w->hchild));
2081 else if (!NILP(w->vchild))
2082 delete_all_subwindows(XWINDOW(w->vchild));
2084 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and
2085 therefore redisplay, so it requires the mirror structure to be
2086 correct. We must dirty the mirror before it is called. */
2087 f->mirror_dirty = 1;
2089 mark_window_as_deleted(w);
2094 DEFUN("next-window", Fnext_window, 0, 4, 0, /*
2095 Return the next window after WINDOW in the canonical ordering of windows.
2096 If omitted, WINDOW defaults to the selected window.
2098 Optional second arg MINIBUF t means count the minibuffer window even
2099 if not active. MINIBUF nil or omitted means count the minibuffer iff
2100 it is active. MINIBUF neither t nor nil means not to count the
2101 minibuffer even if it is active.
2103 Several frames may share a single minibuffer; if the minibuffer
2104 counts, all windows on all frames that share that minibuffer count
2105 too. Therefore, `next-window' can be used to iterate through the
2106 set of windows even when the minibuffer is on another frame. If the
2107 minibuffer does not count, only windows from WINDOW's frame count.
2109 By default, only the windows in the selected frame are considered.
2110 The optional argument WHICH-FRAMES changes this behavior:
2111 WHICH-FRAMES = `visible' means search windows on all visible frames.
2112 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2113 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2114 WHICH-FRAMES = a frame means search only windows on that frame.
2115 Anything else means restrict to the selected frame.
2117 The optional fourth argument WHICH-DEVICES further clarifies on which
2118 devices to search for frames as specified by WHICH-FRAMES. This value
2119 is only meaningful if WHICH-FRAMES is non-nil.
2120 If nil or omitted, search all devices on the selected console.
2121 If a device, only search that device.
2122 If a console, search all devices on that console.
2123 If a device type, search all devices of that type.
2124 If `window-system', search all window-system devices.
2125 Any other non-nil value means search all devices.
2127 If you use consistent values for MINIBUF, WHICH-FRAMES, and
2128 WHICH-DEVICES, you can use `next-window' to iterate through the entire
2129 cycle of acceptable windows, eventually ending up back at the window
2130 you started with. `previous-window' traverses the same cycle, in the
2133 (window, minibuf, which_frames, which_devices))
2136 Lisp_Object start_window;
2139 window = Fselected_window(Qnil);
2141 CHECK_LIVE_WINDOW(window);
2143 start_window = window;
2145 /* minibuf == nil may or may not include minibuffers.
2146 Decide if it does. */
2148 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2149 else if (!EQ(minibuf, Qt))
2151 /* Now `minibuf' is one of:
2152 t => count all minibuffer windows
2153 lambda => count none of them
2154 or a specific minibuffer window (the active one) to count. */
2156 /* which_frames == nil doesn't specify which frames to include. */
2157 if (NILP(which_frames))
2158 which_frames = (!EQ(minibuf, Qlambda)
2159 ? (FRAME_MINIBUF_WINDOW
2160 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2162 else if (EQ(which_frames, Qvisible)) ;
2163 else if (ZEROP(which_frames)) ;
2164 else if (FRAMEP(which_frames)
2165 && !EQ(which_frames, Fwindow_frame(window)))
2166 /* If which_frames is a frame and window arg isn't on that frame, just
2167 return the first window on the frame. */
2168 return frame_first_window(XFRAME(which_frames));
2169 else if (!EQ(which_frames, Qt))
2170 which_frames = Qnil;
2171 /* Now `which_frames' is one of:
2172 t => search all frames
2173 nil => search just the current frame
2174 visible => search just visible frames
2175 0 => search visible and iconified frames
2176 a window => search the frame that window belongs to. */
2178 /* Do this loop at least once, to get the next window, and perhaps
2179 again, if we hit the minibuffer and that is not acceptable. */
2181 /* Find a window that actually has a next one. This loop
2182 climbs up the tree. */
2183 while (tem = XWINDOW(window)->next, NILP(tem))
2184 if (tem = XWINDOW(window)->parent, !NILP(tem))
2186 else { /* window must be minibuffer window now */
2188 /* We've reached the end of this frame.
2189 Which other frames are acceptable? */
2190 tem = WINDOW_FRAME(XWINDOW(window));
2192 if (!NILP(which_frames)) {
2193 Lisp_Object tem1 = tem;
2195 next_frame(tem, which_frames,
2198 /* In the case where the minibuffer is active,
2199 and we include its frame as well as the selected one,
2200 next_frame may get stuck in that frame.
2201 If that happens, go back to the selected frame
2202 so we can complete the cycle. */
2208 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2214 /* If we're in a combination window, find its first child and
2215 recurse on that. Otherwise, we've found the window we want. */
2217 if (!NILP(XWINDOW(window)->hchild))
2218 window = XWINDOW(window)->hchild;
2219 else if (!NILP(XWINDOW(window)->vchild))
2220 window = XWINDOW(window)->vchild;
2225 /* Which windows are acceptable?
2226 Exit the loop and accept this window if
2227 this isn't a minibuffer window,
2228 or we're accepting all minibuffer windows,
2229 or this is the active minibuffer and we are accepting that one, or
2230 we've come all the way around and we're back at the original window. */
2231 while (MINI_WINDOW_P(XWINDOW(window))
2233 && !EQ(minibuf, window)
2234 && !EQ(window, start_window));
2239 DEFUN("previous-window", Fprevious_window, 0, 4, 0, /*
2240 Return the window preceding WINDOW in the canonical ordering of windows.
2241 If omitted, WINDOW defaults to the selected window.
2243 Optional second arg MINIBUF t means count the minibuffer window even
2244 if not active. MINIBUF nil or omitted means count the minibuffer iff
2245 it is active. MINIBUF neither t nor nil means not to count the
2246 minibuffer even if it is active.
2248 Several frames may share a single minibuffer; if the minibuffer
2249 counts, all windows on all frames that share that minibuffer count
2250 too. Therefore, `previous-window' can be used to iterate through
2251 the set of windows even when the minibuffer is on another frame. If
2252 the minibuffer does not count, only windows from WINDOW's frame count.
2254 By default, only the windows in the selected frame are considered.
2255 The optional argument WHICH-FRAMES changes this behavior:
2256 WHICH-FRAMES = `visible' means search windows on all visible frames.
2257 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2258 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2259 WHICH-FRAMES = a frame means search only windows on that frame.
2260 Anything else means restrict to the selected frame.
2262 The optional fourth argument WHICH-DEVICES further clarifies on which
2263 devices to search for frames as specified by WHICH-FRAMES. This value
2264 is only meaningful if WHICH-FRAMES is non-nil.
2265 If nil or omitted, search all devices on the selected console.
2266 If a device, only search that device.
2267 If a console, search all devices on that console.
2268 If a device type, search all devices of that type.
2269 If `window-system', search all window-system devices.
2270 Any other non-nil value means search all devices.
2272 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2273 you can use `previous-window' to iterate through the entire cycle of
2274 acceptable windows, eventually ending up back at the window you started with.
2275 `next-window' traverses the same cycle, in the reverse order.
2277 (window, minibuf, which_frames, devices))
2280 Lisp_Object start_window;
2283 window = Fselected_window(Qnil);
2285 CHECK_LIVE_WINDOW(window);
2287 start_window = window;
2289 /* minibuf == nil may or may not include minibuffers.
2290 Decide if it does. */
2292 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2293 else if (!EQ(minibuf, Qt))
2295 /* Now `minibuf' is one of:
2296 t => count all minibuffer windows
2297 lambda => count none of them
2298 or a specific minibuffer window (the active one) to count. */
2300 /* which_frames == nil doesn't specify which frames to include.
2301 Decide which frames it includes. */
2302 if (NILP(which_frames))
2303 which_frames = (!EQ(minibuf, Qlambda)
2304 ? (FRAME_MINIBUF_WINDOW
2305 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2307 else if (EQ(which_frames, Qvisible)) ;
2308 else if (ZEROP(which_frames)) ;
2309 else if (FRAMEP(which_frames)
2310 && !EQ(which_frames, Fwindow_frame(window)))
2311 /* If which_frames is a frame and window arg isn't on that frame, just
2312 return the first window on the frame. */
2313 return frame_first_window(XFRAME(which_frames));
2314 else if (!EQ(which_frames, Qt))
2315 which_frames = Qnil;
2316 /* Now `which_frames' is one of:
2317 t => search all frames
2318 nil => search just the current frame
2319 visible => search just visible frames
2320 0 => search visible and iconified frames
2321 a window => search the frame that window belongs to. */
2323 /* Do this loop at least once, to get the next window, and perhaps
2324 again, if we hit the minibuffer and that is not acceptable. */
2326 /* Find a window that actually has a next one. This loop
2327 climbs up the tree. */
2328 while (tem = XWINDOW(window)->prev, NILP(tem))
2329 if (tem = XWINDOW(window)->parent, !NILP(tem))
2331 else { /* window must be minibuffer window now */
2333 /* We have found the top window on the frame.
2334 Which frames are acceptable? */
2335 tem = WINDOW_FRAME(XWINDOW(window));
2337 if (!NILP(which_frames))
2338 /* It's actually important that we use previous_frame here,
2339 rather than next_frame. All the windows acceptable
2340 according to the given parameters should form a ring;
2341 Fnext_window and Fprevious_window should go back and
2342 forth around the ring. If we use next_frame here,
2343 then Fnext_window and Fprevious_window take different
2344 paths through the set of acceptable windows.
2345 window_loop assumes that these `ring' requirement are
2348 Lisp_Object tem1 = tem;
2350 previous_frame(tem, which_frames,
2352 /* In the case where the minibuffer is active,
2353 and we include its frame as well as the selected one,
2354 next_frame may get stuck in that frame.
2355 If that happens, go back to the selected frame
2356 so we can complete the cycle. */
2362 /* If this frame has a minibuffer, find that window first,
2363 because it is conceptually the last window in that frame. */
2364 if (FRAME_HAS_MINIBUF_P(XFRAME(tem)))
2365 tem = FRAME_MINIBUF_WINDOW(XFRAME(tem));
2367 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2374 /* If we're in a combination window, find its first child and
2375 recurse on that. Otherwise, we've found the window we want. */
2377 if (!NILP(XWINDOW(window)->hchild))
2378 window = XWINDOW(window)->hchild;
2379 else if (!NILP(XWINDOW(window)->vchild))
2380 window = XWINDOW(window)->vchild;
2383 while (tem = XWINDOW(window)->next, !NILP(tem))
2387 /* Which windows are acceptable?
2388 Exit the loop and accept this window if
2389 this isn't a minibuffer window,
2390 or we're accepting all minibuffer windows,
2391 or this is the active minibuffer and we are accepting that one, or
2392 we've come all the way around and we're back at the original window. */
2393 while (MINI_WINDOW_P(XWINDOW(window))
2395 && !EQ(minibuf, window)
2396 && !EQ(window, start_window));
2401 DEFUN("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2402 Return the next window which is vertically after WINDOW.
2407 struct window *w = decode_window(window);
2408 XSETWINDOW(window, w);
2410 if (MINI_WINDOW_P(XWINDOW(window)))
2413 root = FRAME_ROOT_WINDOW(XFRAME(WINDOW_FRAME(XWINDOW(window))));
2415 if (EQ(window, root)) {
2417 if (!NILP(XWINDOW(window)->hchild))
2418 window = XWINDOW(window)->hchild;
2419 else if (!NILP(XWINDOW(window)->vchild))
2420 window = XWINDOW(window)->vchild;
2426 if (!NILP(XWINDOW(window)->parent) &&
2427 !NILP(XWINDOW(XWINDOW(window)->parent)->vchild)) {
2428 if (!NILP(XWINDOW(window)->next))
2429 return XWINDOW(window)->next;
2431 window = XWINDOW(window)->parent;
2433 window = XWINDOW(window)->parent;
2435 while (!EQ(window, root));
2438 if (!NILP(XWINDOW(window)->hchild))
2439 window = XWINDOW(window)->hchild;
2440 else if (!NILP(XWINDOW(window)->vchild))
2441 window = XWINDOW(window)->vchild;
2446 DEFUN("other-window", Fother_window, 1, 3, "p", /*
2447 Select the COUNT'th different window on this frame.
2448 All windows on current frame are arranged in a cyclic order.
2449 This command selects the window COUNT steps away in that order.
2450 A negative COUNT moves in the opposite order.
2452 By default, only the windows in the selected frame are considered.
2453 The optional argument WHICH-FRAMES changes this behavior:
2454 WHICH-FRAMES = `visible' means search windows on all visible frames.
2455 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2456 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2457 WHICH-FRAMES = a frame means search only windows on that frame.
2458 Anything else means restrict to the selected frame.
2460 The optional argument WHICH-DEVICES further clarifies on which devices
2461 to search for frames as specified by WHICH-FRAMES. This value is only
2462 meaningful if WHICH-FRAMES is non-nil.
2463 If nil or omitted, search all devices on the selected console.
2464 If a device, only search that device.
2465 If a console, search all devices on that console.
2466 If a device type, search all devices of that type.
2467 If `window-system', search all window-system devices.
2468 Any other non-nil value means search all devices.
2470 (count, which_frames, which_devices))
2476 w = Fselected_window(Qnil);
2480 w = Fnext_window(w, Qnil, which_frames, which_devices);
2484 w = Fprevious_window(w, Qnil, which_frames, which_devices);
2487 Fselect_window(w, Qnil);
2491 /* Look at all windows, performing an operation specified by TYPE
2494 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2495 frame. If FRAMES is a frame, just look at windows on that frame.
2496 If MINI is non-zero, perform the operation on minibuffer windows too.
2501 GET_BUFFER_WINDOW, /* Arg is buffer */
2502 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2503 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2504 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2505 UNDEDICATE_BUFFER, /* Arg is buffer */
2507 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2508 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2512 window_loop(enum window_loop type,
2515 Lisp_Object which_frames,
2516 int dedicated_too, Lisp_Object which_devices)
2518 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2520 Lisp_Object best_window = Qnil;
2521 Lisp_Object next_window;
2522 Lisp_Object last_window;
2523 struct frame *frame;
2524 Lisp_Object frame_arg = Qt;
2525 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2526 /* #### I think the change of "precomputing" last_window and next_window
2527 * #### catch the lossage this is meant(?) to punt on...
2530 Lisp_Object devcons, concons;
2532 /* If we're only looping through windows on a particular frame,
2533 FRAME points to that frame. If we're looping through windows
2534 on all frames, FRAME is 0. */
2535 if (FRAMEP(which_frames))
2536 frame = XFRAME(which_frames);
2537 else if (NILP(which_frames))
2538 frame = selected_frame();
2542 /* FRAME_ARG is Qlambda to stick to one frame,
2543 Qvisible to consider all visible frames,
2546 frame_arg = Qlambda;
2547 } else if (ZEROP(which_frames)) {
2548 frame_arg = which_frames;
2549 } else if (EQ(which_frames, Qvisible)) {
2550 frame_arg = which_frames;
2553 DEVICE_LOOP_NO_BREAK(devcons, concons) {
2554 Lisp_Object device = XCAR(devcons);
2555 Lisp_Object the_frame;
2558 XSETFRAME(the_frame, frame);
2560 the_frame = DEVICE_SELECTED_FRAME(XDEVICE(device));
2562 if (NILP(the_frame))
2565 if (!device_matches_device_spec(device,
2566 NILP(which_devices) ?
2567 FRAME_CONSOLE(XFRAME(the_frame))
2571 /* Pick a window to start with. */
2575 w = FRAME_SELECTED_WINDOW(XFRAME(the_frame));
2577 /* Figure out the last window we're going to mess with. Since
2578 Fnext_window, given the same options, is guaranteed to go in a
2579 ring, we can just use Fprevious_window to find the last one.
2581 We can't just wait until we hit the first window again,
2582 because it might be deleted. */
2585 Fprevious_window(w, mini ? Qt : Qnil, frame_arg, device);
2589 struct window *p = XWINDOW(w);
2591 /* Pick the next window now, since some operations will delete
2592 the current window. */
2594 Fnext_window(w, mini ? Qt : Qnil, frame_arg,
2597 /* #### Still needed ?? */
2598 /* Given the outstanding quality of the rest of this code,
2599 I feel no shame about putting this piece of shit in. */
2600 if (++lose_lose >= 500) {
2601 /* Call to abort() added by Darryl Okahata (16 Nov. 2001),
2602 at Ben's request, to catch any remaining bugs.
2604 If you find that SXEmacs is aborting here, and you
2605 need to be up and running ASAP, it should be safe to
2606 comment out the following abort(), as long as you
2607 leave the "break;" alone. */
2609 break; /* <--- KEEP THIS HERE! Do not delete! */
2612 /* Note that we do not pay attention here to whether
2613 the frame is visible, since Fnext_window skips non-visible frames
2614 if that is desired, under the control of frame_arg. */
2615 if (!MINI_WINDOW_P(p)
2616 || (mini && minibuf_level > 0))
2618 case GET_BUFFER_WINDOW: {
2619 if (XBUFFER(p->buffer) ==
2625 case GET_BUFFER_WINDOW_COUNT: {
2626 if (XBUFFER(p->buffer) ==
2632 case GET_LRU_WINDOW: {
2633 /* t as arg means consider only
2634 full-width windows */
2636 && !window_full_width_p(p))
2638 /* Ignore dedicated windows and
2640 if (MINI_WINDOW_P(p)
2641 || (dedicated_too ? 0 :
2642 !NILP(p->dedicated)))
2644 if (NILP(best_window) ||
2645 (XINT(XWINDOW(best_window)->
2647 > XINT(p->use_time)))
2652 case GET_BUFFER_MRU_WINDOW: {
2653 /* #### what about the first check in
2655 /* Ignore dedicated windows and
2657 if (MINI_WINDOW_P(p)
2658 || (dedicated_too ? 0 :
2659 !NILP(p->dedicated)))
2662 if (XBUFFER(p->buffer) ==
2664 if (NILP(best_window)
2677 case UNDEDICATE_BUFFER: {
2678 if ((XBUFFER(p->buffer) ==
2680 p->dedicated = Qnil;
2685 case DELETE_OTHER_WINDOWS: {
2686 /* Don't delete the last window on a
2687 frame; this can happen when the
2688 minibuffer is selected, and would
2689 cause the frame to be deleted. */
2690 if (p != XWINDOW(obj) &&
2691 !TOP_LEVEL_WINDOW_P(XWINDOW (w))) {
2692 Fdelete_window(w, Qnil);
2697 case DELETE_BUFFER_WINDOWS: {
2698 if (EQ(p->buffer, obj)) {
2700 XFRAME(WINDOW_FRAME(p));
2702 /* If this window is dedicated,
2703 and in a frame of its own,
2705 if (EQ (w, FRAME_ROOT_WINDOW (f))
2706 && !NILP(p->dedicated)
2707 && (allow_deletion_of_last_visible_frame
2708 || other_visible_frames (f)))
2725 /* As we go, check for the end of the
2726 loop. We mustn't start going
2727 around a second time. */
2728 if (EQ(next_window, last_window)) {
2746 /* Now we can safely delete the frame. */
2751 /* If we're deleting the
2754 the frame, find a new
2757 if (NILP(p->parent)) {
2790 case GET_LARGEST_WINDOW: {
2791 /* Ignore dedicated windows and
2793 if (MINI_WINDOW_P(p)
2794 || (dedicated_too ? 0 :
2795 !NILP(p->dedicated)))
2798 /* write the check as follows to
2800 error_check_window() --ben */
2804 XWINDOW(best_window);
2805 if (NILP(best_window) ||
2806 ((WINDOW_HEIGHT(p) *
2808 > (WINDOW_HEIGHT(b) *
2809 WINDOW_WIDTH(b)))) {
2816 case WINDOW_LOOP_UNUSED:
2821 if (EQ(w, last_window)) {
2829 return type == GET_BUFFER_WINDOW_COUNT ? make_int(count) : best_window;
2832 #if 0 /* not currently used */
2834 int buffer_window_count(struct buffer *b, struct frame *f)
2836 Lisp_Object buffer, frame;
2838 XSETFRAME(frame, f);
2839 XSETBUFFER(buffer, b);
2841 return XINT(window_loop(GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2845 int buffer_window_mru(struct window *w)
2847 Lisp_Object window =
2848 window_loop(GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2852 else if (XWINDOW(window) == w)
2860 void undedicate_windows(Lisp_Object buffer, Lisp_Object frame)
2862 window_loop(UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2865 DEFUN("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2866 Return the window least recently selected or used for display.
2868 By default, only the windows in the selected frame are considered.
2869 The optional argument WHICH-FRAMES changes this behavior:
2870 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2871 If WHICH-FRAMES is 0, search all visible and iconified frames.
2872 If WHICH-FRAMES is t, search all frames.
2873 If WHICH-FRAMES is nil, search only the selected frame.
2874 If WHICH-FRAMES is a frame, search only that frame.
2876 The optional argument WHICH-DEVICES further clarifies on which devices
2877 to search for frames as specified by WHICH-FRAMES. This value is only
2878 meaningful if WHICH-FRAMES is non-nil.
2879 If nil or omitted, search all devices on the selected console.
2880 If a device, only search that device.
2881 If a console, search all devices on that console.
2882 If a device type, search all devices of that type.
2883 If `window-system', search all devices on window-system consoles.
2884 Any other non-nil value means search all devices.
2886 (which_frames, which_devices))
2889 /* First try for a non-dedicated window that is full-width */
2890 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2891 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2894 /* Then try for any non-dedicated window */
2895 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 0,
2897 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2901 /* FSFmacs never returns a dedicated window here. If we do,
2902 it makes `display-buffer' not work right. #### All of this
2903 shit is so disgusting and awful that it needs to be rethought
2905 /* then try for a dedicated window that is full-width */
2906 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2907 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2910 /* If none of them, then all windows, dedicated or not. */
2911 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 1,
2914 /* At this point we damn well better have found something. */
2922 DEFUN("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2923 Return the window largest in area.
2925 By default, only the windows in the selected frame are considered.
2926 The optional argument WHICH-FRAMES changes this behavior:
2927 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2928 If WHICH-FRAMES is 0, search all visible and iconified frames.
2929 If WHICH-FRAMES is t, search all frames.
2930 If WHICH-FRAMES is nil, search only the selected frame.
2931 If WHICH-FRAMES is a frame, search only that frame.
2933 The optional argument WHICH-DEVICES further clarifies on which devices
2934 to search for frames as specified by WHICH-FRAMES. This value is only
2935 meaningful if WHICH-FRAMES is non-nil.
2936 If nil or omitted, search all devices on the selected console.
2937 If a device, only search that device.
2938 If a console, search all devices on that console.
2939 If a device type, search all devices of that type.
2940 If `window-system', search all devices on window-system consoles.
2941 Any other non-nil value means search all devices.
2943 (which_frames, which_devices))
2945 /* Don't search dedicated windows because FSFmacs doesn't.
2946 This stuff is all black magic so don't try to apply common
2948 return window_loop(GET_LARGEST_WINDOW, Qnil, 0,
2949 which_frames, 0, which_devices);
2952 DEFUN("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2953 Return a window currently displaying BUFFER, or nil if none.
2955 By default, only the windows in the selected frame are considered.
2956 The optional argument WHICH-FRAMES changes this behavior:
2957 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2958 If WHICH-FRAMES is 0, search all visible and iconified frames.
2959 If WHICH-FRAMES is t, search all frames.
2960 If WHICH-FRAMES is nil, search only the selected frame.
2961 If WHICH-FRAMES is a frame, search only that frame.
2963 The optional argument WHICH-DEVICES further clarifies on which devices
2964 to search for frames as specified by WHICH-FRAMES. This value is only
2965 meaningful if WHICH-FRAMES is non-nil.
2966 If nil or omitted, search all devices on the selected console.
2967 If a device, only search that device.
2968 If a console, search all devices on that console.
2969 If a device type, search all devices of that type.
2970 If `window-system', search all devices on window-system consoles.
2971 Any other non-nil value means search all devices.
2973 (buffer, which_frames, which_devices))
2975 buffer = Fget_buffer(buffer);
2976 if (BUFFERP(buffer))
2977 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2978 return window_loop(GET_BUFFER_WINDOW, buffer, 1,
2979 which_frames, 1, which_devices);
2984 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2985 but there is no sensible way to implement those functions, since
2986 you can't in general derive a window from a buffer. */
2988 DEFUN("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width, 0, 1, 0, /*
2989 Return the width in pixels of the left outside margin of window WINDOW.
2990 If WINDOW is nil, the selected window is assumed.
2994 return make_int(window_left_margin_width(decode_window(window)));
2997 DEFUN("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width, 0, 1, 0, /*
2998 Return the width in pixels of the right outside margin of window WINDOW.
2999 If WINDOW is nil, the selected window is assumed.
3003 return make_int(window_right_margin_width(decode_window(window)));
3006 DEFUN("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
3007 Make WINDOW (or the selected window) fill its frame.
3008 Only the frame WINDOW is on is affected.
3009 This function tries to reduce display jumps
3010 by keeping the text previously visible in WINDOW
3011 in the same place on the frame. Doing this depends on
3012 the value of (window-start WINDOW), so if calling this function
3013 in a program gives strange scrolling, make sure the window-start
3014 value is reasonable when this function is called.
3019 struct window *w = decode_window(window);
3020 struct buffer *b = XBUFFER(w->buffer);
3022 int old_top = WINDOW_TOP(w);
3024 XSETWINDOW(window, w);
3026 if (MINI_WINDOW_P(w) && old_top > 0)
3027 error("Can't expand minibuffer to full frame");
3029 /* Ignore dedicated windows. */
3030 window_loop(DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3032 start_pos = marker_position(w->start[CURRENT_DISP]);
3034 /* Try to minimize scrolling, by setting the window start to the
3035 point which will cause the text at the old window start to be at
3036 the same place on the frame. But don't try to do this if the
3037 window start is outside the visible portion (as might happen when
3038 the display is not current, due to typeahead). */
3039 if (start_pos >= BUF_BEGV(b) && start_pos <= BUF_ZV(b)
3040 && !MINI_WINDOW_P(w)) {
3042 start_with_line_at_pixpos(w, start_pos, old_top);
3044 if (new_start >= BUF_BEGV(b) && new_start <= BUF_ZV(b)) {
3045 Fset_marker(w->start[CURRENT_DISP], make_int(new_start),
3047 w->start_at_line_beg =
3048 beginning_of_line_p(b, new_start);
3050 /* We need to do this, so that the window-scroll-functions
3055 run_window_configuration_hook( window );
3060 DEFUN("delete-windows-on", Fdelete_windows_on, 1, 3, "bDelete windows on (buffer): ", /*
3061 Delete all windows showing BUFFER.
3063 Optional second argument WHICH-FRAMES controls which frames are affected.
3064 If nil or omitted, delete all windows showing BUFFER in any frame.
3065 If t, delete only windows showing BUFFER in the selected frame.
3066 If `visible', delete all windows showing BUFFER in any visible frame.
3067 If a frame, delete only windows showing BUFFER in that frame.
3068 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3069 except that the meanings of nil and t are reversed.
3071 The optional third argument WHICH-DEVICES further clarifies on which
3072 devices to search for frames as specified by WHICH-FRAMES. This value
3073 is only meaningful if WHICH-FRAMES is not t.
3074 If nil or omitted, search only the selected console.
3075 If a device, only search that device.
3076 If a console, search all devices on that console.
3077 If a device type, search all devices of that type.
3078 If `window-system', search all devices on a window system.
3079 Any other non-nil value means search all devices.
3081 (buffer, which_frames, which_devices))
3083 /* This function can GC */
3084 buffer = Fget_buffer(buffer);
3085 CHECK_BUFFER(buffer);
3087 /* WHICH-FRAMES values t and nil mean the opposite of what
3088 window_loop expects. */
3089 if (EQ(which_frames, Qnil))
3091 else if (EQ(which_frames, Qt))
3092 which_frames = Qnil;
3094 /* Ignore dedicated windows. */
3095 window_loop(DELETE_BUFFER_WINDOWS, buffer, 0,
3096 which_frames, 0, which_devices);
3100 static Lisp_Object list_windows(struct window *w, Lisp_Object value)
3103 if (!NILP(w->hchild))
3104 value = list_windows(XWINDOW(w->hchild), value);
3105 else if (!NILP(w->vchild))
3106 value = list_windows(XWINDOW(w->vchild), value);
3109 XSETWINDOW(window, w);
3110 value = Fcons(window, value);
3114 w = XWINDOW(w->next);
3120 list_all_windows(Lisp_Object frame_spec, Lisp_Object device_spec)
3122 Lisp_Object devcons, concons;
3123 Lisp_Object retval = Qnil;
3125 DEVICE_LOOP_NO_BREAK(devcons, concons) {
3126 Lisp_Object frame_list, the_window;
3127 Lisp_Object device, tail;
3129 device = XCAR(devcons);
3130 frame_list = DEVICE_FRAME_LIST(XDEVICE(device));
3132 LIST_LOOP(tail, frame_list) {
3133 if ((NILP(frame_spec)
3135 DEVICE_SELECTED_FRAME(XDEVICE(device))))
3136 || (EQ(frame_spec, Qvisible)
3137 && !FRAME_VISIBLE_P(XFRAME(XCAR(tail))))
3138 || (FRAMEP(frame_spec)
3139 && !EQ(frame_spec, XCAR(tail)))
3140 || (!NILP(frame_spec)
3141 && !device_matches_device_spec(device,
3147 the_window = FRAME_ROOT_WINDOW(XFRAME(XCAR(tail)));
3148 retval = list_windows(XWINDOW(the_window), retval);
3151 return Fnreverse(retval);
3154 DEFUN("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3, "bReplace buffer in windows: ", /*
3155 Replace BUFFER with some other buffer in all windows showing it.
3157 Optional second argument WHICH-FRAMES controls which frames are affected.
3158 If nil or omitted, all frames are affected.
3159 If t, only the selected frame is affected.
3160 If `visible', all visible frames are affected.
3161 If a frame, only that frame is affected.
3162 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3163 except that the meanings of nil and t are reversed.
3165 The optional third argument WHICH-DEVICES further clarifies on which
3166 devices to search for frames as specified by WHICH-FRAMES. This value
3167 is only meaningful if WHICH-FRAMES is not t.
3168 If nil or omitted, search only the selected console.
3169 If a device, only search that device.
3170 If a console, search all devices on that console.
3171 If a device type, search all devices of that type.
3172 If `window-system', search all devices on a window system.
3173 Any other non-nil value means search all devices.
3175 (buffer, which_frames, which_devices))
3177 /* This function can GC */
3178 Lisp_Object window_list;
3180 struct gcpro gcpro1, gcpro2;
3182 if (EQ(which_frames, Qnil))
3184 else if (EQ(which_frames, Qt))
3185 which_frames = Qnil;
3186 window_list = list_all_windows(which_frames, which_devices);
3188 buffer = Fget_buffer(buffer);
3189 CHECK_BUFFER(buffer);
3191 GCPRO2(window_list, buffer);
3192 LIST_LOOP(tail, window_list) {
3193 Lisp_Object window = XCAR(tail);
3194 if (!MINI_WINDOW_P(XWINDOW(window))
3195 && EQ(XWINDOW(window)->buffer, buffer)) {
3196 Lisp_Object another_buffer =
3197 Fother_buffer(buffer, Qnil, Qnil);
3198 Lisp_Object frame = WINDOW_FRAME(XWINDOW(window));
3199 if (NILP(another_buffer))
3200 another_buffer = Fget_buffer_create(QSscratch);
3201 if (!NILP(XWINDOW(window)->dedicated)
3202 && EQ(window, FRAME_ROOT_WINDOW(XFRAME(frame)))
3203 && (allow_deletion_of_last_visible_frame
3204 || other_visible_frames (XFRAME (frame))))
3206 delete_frame_internal(XFRAME(frame), 0, 0, 0); /* GC */
3208 Fset_window_buffer(window, another_buffer,
3210 if (EQ(window, Fselected_window(Qnil)))
3211 Fset_buffer(XWINDOW(window)->buffer);
3219 /* The smallest acceptable dimensions for a window. Anything smaller
3220 might crash Emacs. */
3221 #define MIN_SAFE_WINDOW_WIDTH (2)
3222 #define MIN_SAFE_WINDOW_HEIGHT (2)
3224 /* Make sure that window_min_height and window_min_width are
3225 not too small; if they are, set them to safe minima. */
3227 static void check_min_window_sizes(void)
3229 /* Smaller values might permit a crash. */
3230 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3231 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3232 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3233 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3236 static int frame_min_height(struct frame *frame)
3238 /* For height, we have to see whether the frame has a minibuffer, and
3239 whether it wants a modeline. */
3240 return (FRAME_MINIBUF_ONLY_P(frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3241 : (!FRAME_HAS_MINIBUF_P(frame)) ? MIN_SAFE_WINDOW_HEIGHT
3242 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3245 /* Return non-zero if both frame sizes are less than or equal to
3246 minimal allowed values. ROWS and COLS are in characters */
3247 int frame_size_valid_p(struct frame *frame, int rows, int cols)
3249 return (rows >= frame_min_height(frame)
3250 && cols >= MIN_SAFE_WINDOW_WIDTH);
3253 /* Return non-zero if both frame sizes are less than or equal to
3254 minimal allowed values. WIDTH and HEIGHT are in pixels */
3255 int frame_pixsize_valid_p(struct frame *frame, int width, int height)
3258 pixel_to_real_char_size(frame, width, height, &cols, &rows);
3259 return frame_size_valid_p(frame, rows, cols);
3262 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3263 minimum allowable size. */
3264 void check_frame_size(struct frame *frame, int *rows, int *cols)
3266 int min_height = frame_min_height(frame);
3268 if (*rows < min_height)
3270 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3271 *cols = MIN_SAFE_WINDOW_WIDTH;
3274 /* Normally the window is deleted if it gets too small.
3275 nodelete nonzero means do not do this.
3276 (The caller should check later and do so if appropriate) */
3278 set_window_pixsize(Lisp_Object window, int new_pixsize, int nodelete,
3281 struct window *w = XWINDOW(window);
3282 struct frame *f = XFRAME(w->frame);
3284 int old_pixsize = (set_height ? WINDOW_HEIGHT(w) : WINDOW_WIDTH(w));
3285 Lisp_Object child, minor_kid, major_kid;
3288 int defheight, defwidth;
3290 /* #### This is very likely incorrect and instead the char_to_pixel_
3291 functions should be called. */
3292 default_face_height_and_width(window, &defheight, &defwidth);
3293 line_size = (set_height ? defheight : defwidth);
3295 check_min_window_sizes();
3297 minsize = (set_height ? window_min_height : window_min_width);
3298 minsize *= line_size;
3300 if (!nodelete && !TOP_LEVEL_WINDOW_P(w)
3301 && new_pixsize < minsize) {
3302 Fdelete_window(window, Qnil);
3306 SET_LAST_MODIFIED(w, 0);
3307 SET_LAST_FACECHANGE(w);
3308 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f); /* multiple windows affected */
3310 WINDOW_HEIGHT(w) = new_pixsize;
3311 major_kid = w->vchild;
3312 minor_kid = w->hchild;
3314 WINDOW_WIDTH(w) = new_pixsize;
3315 major_kid = w->hchild;
3316 minor_kid = w->vchild;
3319 if (!NILP(minor_kid)) {
3320 for (child = minor_kid; !NILP(child);
3321 child = XWINDOW(child)->next) {
3323 WINDOW_TOP(XWINDOW(child)) = WINDOW_TOP(w);
3325 WINDOW_LEFT(XWINDOW(child)) = WINDOW_LEFT(w);
3327 set_window_pixsize(child, new_pixsize, nodelete,
3330 } else if (!NILP(major_kid)) {
3331 int last_pos, last_old_pos, pos, old_pos, first;
3332 int pixel_adj_left = new_pixsize - old_pixsize;
3333 int div_val = old_pixsize << 1;
3336 * Previously we bailed out here if there was no size change.
3337 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3338 * toolbar appears or disappears, windows may not change size,
3339 * but their top and left coordinates need to be updated.
3341 * So we don't bail until after the loop below.
3345 (set_height ? WINDOW_TOP(w) : WINDOW_LEFT(w));
3348 for (child = major_kid; !NILP(child); child = c->next) {
3352 old_pos = last_old_pos + WINDOW_HEIGHT(c);
3353 WINDOW_TOP(c) = last_pos;
3355 old_pos = last_old_pos + WINDOW_WIDTH(c);
3356 WINDOW_LEFT(c) = last_pos;
3360 (((old_pos * new_pixsize) << 1) +
3361 old_pixsize) / div_val;
3362 /* All but the last window should have a height which is
3363 a multiple of the default line height. */
3365 pos = (pos / line_size) * line_size;
3367 /* Avoid confusion: don't delete child if it becomes too small */
3368 set_window_pixsize(child, pos + first - last_pos, 1,
3371 last_pos = pos + first;
3372 last_old_pos = old_pos;
3375 /* Sometimes we may get called with our old size. In that case
3376 we don't need to do anything else. */
3377 if (!pixel_adj_left)
3380 /* Now delete any children that became too small. */
3382 for (child = major_kid; !NILP(child);
3383 child = XWINDOW(child)->next) {
3385 set_window_pixheight(child,
3390 set_window_pixwidth(child,
3391 WINDOW_WIDTH(XWINDOW
3398 /* Set the height of WINDOW and all its inferiors. */
3399 void set_window_pixheight(Lisp_Object window, int new_pixheight, int nodelete)
3401 set_window_pixsize(window, new_pixheight, nodelete, 1);
3404 /* Recursively set width of WINDOW and its inferiors. */
3405 void set_window_pixwidth(Lisp_Object window, int new_pixwidth, int nodelete)
3407 set_window_pixsize(window, new_pixwidth, nodelete, 0);
3410 static int window_select_count;
3412 DEFUN("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3413 Make WINDOW display BUFFER as its contents.
3414 When WINDOW is nil, the `selected-window' is used.
3415 BUFFER can be a buffer or buffer name.
3417 With non-nil optional argument NORECORD, do not modify the
3418 global or per-frame buffer ordering.
3421 (window, buffer, norecord))
3424 struct window *w = decode_window(window);
3425 int old_buffer_local_face_property = 0;
3427 buffer = Fget_buffer(buffer);
3428 CHECK_BUFFER(buffer);
3430 if (!BUFFER_LIVE_P(XBUFFER(buffer)))
3431 error("Attempt to display deleted buffer");
3435 error("Window is deleted");
3437 /* While this seems like a logical thing to do, it causes problems
3438 because of saved window configurations. It is possible for a
3439 buffer to get restored into a window in which it is already being
3440 displayed, but start and point are actually at completely
3441 different locations. So we let this function complete fully and
3442 it will then make sure redisplay correctly updates things.
3444 #### This is a kludge. The correct approach is not to do this
3445 but to fix set-window-configuration. */
3447 else if (EQ(tem, buffer))
3450 else if (!EQ(tem, Qt)) { /* w->buffer is t when the window
3451 is first being set up. */
3452 if (!NILP(w->dedicated) && !EQ(tem, buffer))
3453 error("Window is dedicated to buffer %s",
3454 XSTRING_DATA(XBUFFER(tem)->name));
3456 old_buffer_local_face_property =
3457 XBUFFER(w->buffer)->buffer_local_face_property;
3462 w->window_end_pos[CURRENT_DISP] = 0;
3464 w->modeline_hscroll = 0;
3465 Fset_marker(w->pointm[CURRENT_DISP],
3466 make_int(BUF_PT(XBUFFER(buffer))), buffer);
3467 set_marker_restricted(w->start[CURRENT_DISP],
3468 make_int(XBUFFER(buffer)->last_window_start),
3470 Fset_marker(w->sb_point, w->start[CURRENT_DISP], buffer);
3471 /* set start_at_line_beg correctly. GE */
3472 w->start_at_line_beg = beginning_of_line_p(XBUFFER(buffer),
3476 w->force_start = 0; /* Lucid fix */
3477 SET_LAST_MODIFIED(w, 1);
3478 SET_LAST_FACECHANGE(w);
3479 MARK_WINDOWS_CHANGED(w);
3481 int new_buffer_local_face_property =
3482 XBUFFER(w->buffer)->buffer_local_face_property;
3484 if (new_buffer_local_face_property
3485 || new_buffer_local_face_property !=
3486 old_buffer_local_face_property)
3487 MARK_WINDOW_FACES_CHANGED(w);
3489 recompute_all_cached_specifiers_in_window(w);
3490 if (EQ(window, Fselected_window(Qnil))) {
3492 Frecord_buffer(buffer);
3494 Fset_buffer(buffer);
3497 run_window_configuration_hook( window );
3502 DEFUN("select-window", Fselect_window, 1, 2, 0, /*
3503 Select WINDOW. Most editing will apply to WINDOW's buffer.
3504 The main editor command loop selects the buffer of the selected window
3505 before each command.
3507 With non-nil optional argument NORECORD, do not modify the
3508 global or per-frame buffer ordering.
3513 Lisp_Object old_selected_window = Fselected_window(Qnil);
3515 CHECK_LIVE_WINDOW(window);
3516 w = XWINDOW(window);
3518 /* we have already caught dead-window errors */
3519 if (!NILP(w->hchild) || !NILP(w->vchild))
3520 error("Trying to select non-leaf window");
3522 w->use_time = make_int(++window_select_count);
3524 if (EQ(window, old_selected_window))
3527 /* deselect the old window, if it exists (it might not exist if
3528 the selected device has no frames, which occurs at startup) */
3529 if (!NILP(old_selected_window)) {
3530 struct window *ow = XWINDOW(old_selected_window);
3532 Fset_marker(ow->pointm[CURRENT_DISP],
3533 make_int(BUF_PT(XBUFFER(ow->buffer))), ow->buffer);
3535 MARK_WINDOWS_CHANGED(ow);
3538 /* now select the window's frame */
3539 set_frame_selected_window(XFRAME(WINDOW_FRAME(w)), window);
3541 select_frame_1(WINDOW_FRAME(w));
3543 /* also select the window's buffer */
3545 Frecord_buffer(w->buffer);
3546 Fset_buffer(w->buffer);
3548 /* Go to the point recorded in the window.
3549 This is important when the buffer is in more
3550 than one window. It also matters when
3551 redisplay_window has altered point after scrolling,
3552 because it makes the change only in the window. */
3554 Bufpos new_point = marker_position(w->pointm[CURRENT_DISP]);
3555 if (new_point < BUF_BEGV(current_buffer))
3556 new_point = BUF_BEGV(current_buffer);
3557 else if (new_point > BUF_ZV(current_buffer))
3558 new_point = BUF_ZV(current_buffer);
3560 BUF_SET_PT(current_buffer, new_point);
3563 MARK_WINDOWS_CHANGED(w);
3569 display_buffer(Lisp_Object buffer, Lisp_Object not_this_window_p,
3570 Lisp_Object override_frame)
3572 return call3(Qdisplay_buffer, buffer, not_this_window_p,
3576 void temp_output_buffer_show(Lisp_Object buf, Lisp_Object same_frame)
3578 /* This function can GC */
3581 struct buffer *b = XBUFFER(buf);
3583 BUF_SAVE_MODIFF(XBUFFER(buf)) = BUF_MODIFF(b);
3585 BUF_SET_PT(b, BUF_BEG(b));
3587 if (!NILP(Vtemp_buffer_show_function))
3588 call1(Vtemp_buffer_show_function, buf);
3590 window = display_buffer(buf, Qnil, same_frame);
3592 if (!EQ(XWINDOW(window)->frame, Fselected_frame(Qnil)))
3593 Fmake_frame_visible(WINDOW_FRAME(XWINDOW(window)));
3595 Vminibuffer_scroll_window = window;
3596 w = XWINDOW(window);
3598 w->modeline_hscroll = 0;
3599 set_marker_restricted(w->start[CURRENT_DISP], make_int(1), buf);
3600 set_marker_restricted(w->pointm[CURRENT_DISP], make_int(1),
3602 set_marker_restricted(w->sb_point, make_int(1), buf);
3604 /* Run temp-buffer-show-hook, with the chosen window selected. */
3605 if (!preparing_for_armageddon) {
3607 tem = Fboundp(Qtemp_buffer_show_hook);
3609 tem = Fsymbol_value(Qtemp_buffer_show_hook);
3611 int count = specpdl_depth();
3613 /* Select the window that was chosen, for running
3615 record_unwind_protect
3616 (save_window_excursion_unwind,
3617 Fcurrent_window_configuration
3620 Fselect_window(window, Qnil);
3621 run_hook(Qtemp_buffer_show_hook);
3622 unbind_to(count, Qnil);
3629 static void make_dummy_parent(Lisp_Object window)
3632 struct window *o = XWINDOW(window);
3633 struct window *p = alloc_lcrecord_type(struct window, &lrecord_window);
3636 copy_lcrecord(p, o);
3638 /* Don't copy the pointers to the line start cache or the face
3640 p->line_start_cache = Dynarr_new(line_start_cache);
3641 p->face_cachels = Dynarr_new(face_cachel);
3642 p->glyph_cachels = Dynarr_new(glyph_cachel);
3643 p->subwindow_instance_cache = make_image_instance_cache_hash_table();
3645 /* Put new into window structure in place of window */
3646 replace_window(window, new);
3654 p->start[CURRENT_DISP] = Qnil;
3655 p->start[DESIRED_DISP] = Qnil;
3656 p->start[CMOTION_DISP] = Qnil;
3657 p->pointm[CURRENT_DISP] = Qnil;
3658 p->pointm[DESIRED_DISP] = Qnil;
3659 p->pointm[CMOTION_DISP] = Qnil;
3664 DEFUN("split-window", Fsplit_window, 0, 3, "", /*
3665 Split WINDOW, putting SIZE lines in the first of the pair.
3666 WINDOW defaults to the selected one and SIZE to half its size.
3667 If optional third arg HORFLAG is non-nil, split side by side and put
3668 SIZE columns in the first of the pair. The newly created window is
3672 (window, size, horflag))
3675 struct window *o, *p;
3681 window = Fselected_window(Qnil);
3683 CHECK_LIVE_WINDOW(window);
3685 o = XWINDOW(window);
3686 f = XFRAME(WINDOW_FRAME(o));
3690 /* In the new scheme, we are symmetric with respect to separators
3691 so there is no need to do weird things here. */
3694 (WINDOW_WIDTH(o) + window_divider_width(o)) >> 1;
3695 csize = window_pixel_width_to_char_width(o, psize, 0);
3697 psize = WINDOW_HEIGHT(o) >> 1;
3698 csize = window_pixel_height_to_char_height(o, psize, 1);
3704 psize = window_char_width_to_pixel_width(o, csize, 0);
3706 psize = window_char_height_to_pixel_height(o, csize, 1);
3709 if (MINI_WINDOW_P(o))
3710 error("Attempt to split minibuffer window");
3711 else if (FRAME_NO_SPLIT_P(XFRAME(WINDOW_FRAME(o))))
3712 error("Attempt to split unsplittable frame");
3714 check_min_window_sizes();
3716 if (NILP(horflag)) {
3717 if (csize < window_min_height)
3718 error("Window height %d too small (after splitting)",
3720 if (csize + window_min_height > window_char_height(o, 1))
3721 error("Window height %d too small (after splitting)",
3722 window_char_height(o, 1) - csize);
3724 || NILP(XWINDOW(o->parent)->vchild)) {
3725 make_dummy_parent(window);
3727 /* #### I can't understand why you have to reset face
3728 cachels here. This can cause crash so let's disable it
3729 and see the difference. See redisplay-tests.el --yh */
3730 reset_face_cachels(XWINDOW(window));
3733 XWINDOW(new)->vchild = window;
3734 XFRAME(o->frame)->mirror_dirty = 1;
3737 if (csize < window_min_width)
3738 error("Window width %d too small (after splitting)",
3740 if (csize + window_min_width > window_char_width(o, 0))
3741 error("Window width %d too small (after splitting)",
3742 window_char_width(o, 0) - csize);
3744 || NILP(XWINDOW(o->parent)->hchild)) {
3745 make_dummy_parent(window);
3747 /* #### See above. */
3748 reset_face_cachels(XWINDOW(window));
3751 XWINDOW(new)->hchild = window;
3752 XFRAME(o->frame)->mirror_dirty = 1;
3756 /* Now we know that window's parent is a vertical combination
3757 if we are dividing vertically, or a horizontal combination
3758 if we are making side-by-side windows */
3760 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
3761 new = allocate_window();
3764 p->frame = o->frame;
3767 XWINDOW(p->next)->prev = new;
3770 p->parent = o->parent;
3773 reset_face_cachels(p);
3774 reset_glyph_cachels(p);
3776 /* Apportion the available frame space among the two new windows */
3778 if (!NILP(horflag)) {
3779 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
3780 WINDOW_TOP(p) = WINDOW_TOP(o);
3781 WINDOW_WIDTH(p) = WINDOW_WIDTH(o) - psize;
3782 WINDOW_WIDTH(o) = psize;
3783 WINDOW_LEFT(p) = WINDOW_LEFT(o) + psize;
3785 WINDOW_LEFT(p) = WINDOW_LEFT(o);
3786 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
3787 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o) - psize;
3788 WINDOW_HEIGHT(o) = psize;
3789 WINDOW_TOP(p) = WINDOW_TOP(o) + psize;
3792 XFRAME(p->frame)->mirror_dirty = 1;
3793 /* do this last (after the window is completely initialized and
3794 the mirror-dirty flag is set) so that specifier recomputation
3795 caused as a result of this will work properly and not abort. */
3796 Fset_window_buffer(new, o->buffer, Qt);
3798 /* window-configuration-hook is called indirectly, in
3799 set-window-buffer. */
3804 DEFUN("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3805 Make the selected window COUNT lines taller.
3806 From program, optional second arg HORIZONTALP non-nil means grow
3807 sideways COUNT columns, and optional third arg WINDOW specifies the
3808 window to change instead of the selected window.
3811 (count, horizontalp, window))
3814 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3819 DEFUN("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3820 Make the selected window COUNT pixels taller.
3821 From program, optional second arg HORIZONTALP non-nil means grow
3822 sideways COUNT pixels, and optional third arg WINDOW specifies the
3823 window to change instead of the selected window.
3826 (count, horizontalp, window))
3829 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3834 DEFUN("shrink-window", Fshrink_window, 1, 3, "_p", /*
3835 Make the selected window COUNT lines shorter.
3836 From program, optional second arg HORIZONTALP non-nil means shrink
3837 sideways COUNT columns, and optional third arg WINDOW specifies the
3838 window to change instead of the selected window.
3841 (count, horizontalp, window))
3844 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3849 DEFUN("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3850 Make the selected window COUNT pixels smaller.
3851 From program, optional second arg HORIZONTALP non-nil means shrink
3852 sideways COUNT pixels, and optional third arg WINDOW specifies the
3853 window to change instead of the selected window.
3856 (count, horizontalp, window))
3859 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3865 window_pixel_height_to_char_height(struct window *w, int pixel_height,
3866 int include_gutters_p)
3869 int defheight, defwidth;
3873 XSETWINDOW(window, w);
3875 avail_height = (pixel_height -
3876 (include_gutters_p ? 0 :
3877 window_top_window_gutter_height(w) +
3878 window_bottom_window_gutter_height(w)));
3880 default_face_height_and_width(window, &defheight, &defwidth);
3882 char_height = avail_height / defheight;
3884 /* It's the calling function's responsibility to check these values
3885 and make sure they're not out of range.
3887 #### We need to go through the calling functions and actually
3889 return max(0, char_height);
3893 window_char_height_to_pixel_height(struct window *w, int char_height,
3894 int include_gutters_p)
3897 int defheight, defwidth;
3902 XSETWINDOW(window, w);
3904 default_face_height_and_width(window, &defheight, &defwidth);
3906 avail_height = char_height * defheight;
3907 pixel_height = (avail_height +
3908 (include_gutters_p ? 0 :
3909 window_top_window_gutter_height(w) +
3910 window_bottom_window_gutter_height(w)));
3912 /* It's the calling function's responsibility to check these values
3913 and make sure they're not out of range.
3915 #### We need to go through the calling functions and actually
3917 return max(0, pixel_height);
3920 /* Return number of default lines of text can fit in the window W.
3921 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3922 horizontal scrollbar) in the space that is used for the calculation.
3923 This doesn't include space used by the frame gutters.
3925 int window_char_height(struct window *w, int include_gutters_p)
3927 return window_pixel_height_to_char_height(w, window_pixel_height(w),
3932 * Return number of lines currently displayed in window w. If
3933 * end-of-buffer is displayed then the area below end-of-buffer is assume
3934 * to be blank lines of default height.
3935 * Does not include the modeline.
3937 int window_displayed_height(struct window *w)
3939 struct buffer *b = XBUFFER(w->buffer);
3940 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
3943 (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV(b)
3944 ? -1 : w->window_end_pos[CURRENT_DISP]);
3946 if (!Dynarr_length(dla))
3947 return window_char_height(w, 0);
3949 num_lines = Dynarr_length(dla);
3951 /* #### Document and assert somewhere that w->window_end_pos == -1
3952 indicates that end-of-buffer is being displayed. */
3953 if (end_pos == -1) {
3954 struct display_line *dl = Dynarr_atp(dla, 0);
3955 int ypos1 = dl->ypos + dl->descent;
3956 int ypos2 = WINDOW_TEXT_BOTTOM(w);
3958 int defheight, defwidth;
3960 XSETWINDOW(window, w);
3965 if (Dynarr_length(dla) == 1)
3966 ypos1 = WINDOW_TEXT_TOP(w);
3968 dl = Dynarr_atp(dla, Dynarr_length(dla) - 1);
3969 /* If this line is clipped then we know that there is no
3970 blank room between eob and the modeline. If we are
3971 scrolling on clipped lines just know off the clipped
3972 line and return . */
3973 if (scroll_on_clipped_lines && dl->clip)
3974 return num_lines - 1;
3975 ypos1 = dl->ypos + dl->descent - dl->clip;
3979 default_face_height_and_width(window, &defheight, &defwidth);
3980 /* #### This probably needs to know about the clipping area once a
3981 final definition is decided on. */
3982 num_lines += ((ypos2 - ypos1) / defheight);
3984 if (num_lines > 1 && Dynarr_atp(dla, 0)->modeline)
3987 if (scroll_on_clipped_lines
3988 && Dynarr_atp(dla, Dynarr_length(dla) - 1)->clip)
3995 static int window_pixel_width(Lisp_Object window)
3997 return WINDOW_WIDTH(XWINDOW(window));
4000 /* Calculate the pixel of a window, optionally including margin space
4001 but no vertical gutters. */
4003 window_pixel_width_to_char_width(struct window *w, int pixel_width,
4004 int include_margins_p)
4008 int defheight, defwidth;
4011 XSETWINDOW(window, w);
4013 avail_width = (pixel_width -
4014 window_left_gutter_width(w, 0) -
4015 window_right_gutter_width(w, 0) -
4016 (include_margins_p ? 0 : window_left_margin_width(w)) -
4017 (include_margins_p ? 0 : window_right_margin_width(w)));
4019 default_face_height_and_width(window, &defheight, &defwidth);
4021 char_width = (avail_width / defwidth);
4023 /* It's the calling function's responsibility to check these values
4024 and make sure they're not out of range.
4026 #### We need to go through the calling functions and actually
4028 return max(0, char_width);
4032 window_char_width_to_pixel_width(struct window *w, int char_width,
4033 int include_margins_p)
4037 int defheight, defwidth;
4040 XSETWINDOW(window, w);
4042 default_face_height_and_width(window, &defheight, &defwidth);
4044 avail_width = char_width * defwidth;
4045 pixel_width = (avail_width +
4046 window_left_window_gutter_width(w, 0) +
4047 window_right_window_gutter_width(w, 0) +
4048 (include_margins_p ? 0 : window_left_margin_width(w)) +
4049 (include_margins_p ? 0 : window_right_margin_width(w)));
4051 /* It's the calling function's responsibility to check these values
4052 and make sure they're not out of range.
4054 #### We need to go through the calling functions and actually
4056 return max(0, pixel_width);
4059 /* This returns the usable space which doesn't include space needed by
4060 scrollbars or divider lines. */
4061 int window_char_width(struct window *w, int include_margins_p)
4063 return window_pixel_width_to_char_width(w, WINDOW_WIDTH(w),
4067 #define MINSIZE(w) \
4069 ? window_min_width * defwidth \
4070 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4073 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4075 #define CURSIZE(w) \
4076 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4078 #define CURCHARSIZE(w) \
4079 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4081 #define MINCHARSIZE(window) \
4082 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4083 ? 1 : window_min_height)
4085 static int window_pixheight(Lisp_Object w)
4087 return window_pixel_height(XWINDOW(w));
4090 /* Unlike set_window_pixheight, this function
4091 also changes the heights of the siblings so as to
4092 keep everything consistent. */
4095 change_window_height(Lisp_Object window, int delta, Lisp_Object horizontalp,
4098 struct window *win = decode_window(window);
4099 int widthflag = !NILP(horizontalp);
4104 int (*sizefun) (Lisp_Object) = (widthflag
4105 ? window_pixel_width
4106 : window_pixheight);
4107 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4108 ? set_window_pixwidth
4109 : set_window_pixheight);
4111 int defheight, defwidth;
4116 check_min_window_sizes();
4118 XSETWINDOW(window, win);
4119 f = XFRAME(win->frame);
4120 if (EQ(window, FRAME_ROOT_WINDOW(f)))
4121 error("Won't change only window");
4123 /* #### This is very likely incorrect and instead the char_to_pixel_
4124 functions should be called. */
4125 default_face_height_and_width(window, &defheight, &defwidth);
4128 w = XWINDOW(window);
4133 sizep = &CURSIZE (w);
4134 dim = CURCHARSIZE (w);
4135 new_pixsize = inpixels?(*sizep + delta):(dim+delta);
4136 set_window_pixsize (window, new_pixsize, 0, 0);
4141 if (widthflag ? !NILP(XWINDOW(parent)->hchild)
4142 : !NILP(XWINDOW(parent)->vchild))
4147 sizep = &CURSIZE(w);
4148 dim = CURCHARSIZE(w);
4150 if ((inpixels && (*sizep + delta) < MINSIZE(window)) ||
4151 (!inpixels && (dim + delta) < MINCHARSIZE(window))) {
4152 if (MINI_WINDOW_P(XWINDOW(window)))
4154 else if (!NILP(parent)) {
4155 Fdelete_window(window, Qnil);
4161 delta *= (widthflag ? defwidth : defheight);
4166 maxdelta = ((!NILP(parent))
4167 ? (*sizefun) (parent) - *sizep : ((!NILP(w->next))
4177 /* This is a frame with only one window,
4178 a minibuffer-only or a minibufferless frame. */
4182 if (delta > maxdelta)
4183 /* This case traps trying to make the minibuffer
4184 the full frame, or make the only window aside from the
4185 minibuffer the full frame. */
4192 /* #### Chuck: is this correct? */
4193 if (*sizep + delta < MINSIZE(window)) {
4194 Fdelete_window(window);
4200 if (!NILP(w->next) &&
4201 (*sizefun) (w->next) - delta >= (int)MINSIZE(w->next)) {
4202 CURBEG(XWINDOW(w->next)) += delta;
4203 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4204 (*setsizefun) (window, *sizep + delta, 0);
4205 } else if (!NILP(w->prev) &&
4206 (*sizefun) (w->prev) - delta >= (int)MINSIZE(w->prev)) {
4207 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4209 (*setsizefun) (window, *sizep + delta, 0);
4212 int opht = (*sizefun) (parent);
4214 /* If trying to grow this window to or beyond size of the parent,
4215 make delta1 so big that, on shrinking back down,
4216 all the siblings end up with less than one line and are deleted. */
4217 if (opht <= *sizep + delta)
4218 delta1 = opht * opht * 2;
4219 /* Otherwise, make delta1 just right so that if we add delta1
4220 lines to this window and to the parent, and then shrink
4221 the parent back to its original size, the new proportional
4222 size of this window will increase by delta. */
4225 (delta * opht * 100) / ((opht - *sizep - delta) *
4228 /* Add delta1 lines or columns to this window, and to the parent,
4229 keeping things consistent while not affecting siblings. */
4230 CURSIZE(XWINDOW(parent)) = opht + delta1;
4231 (*setsizefun) (window, *sizep + delta1, 0);
4233 /* Squeeze out delta1 lines or columns from our parent,
4234 shrinking this window and siblings proportionately.
4235 This brings parent back to correct size.
4236 Delta1 was calculated so this makes this window the desired size,
4237 taking it all out of the siblings. */
4238 (*setsizefun) (parent, opht, 0);
4241 SET_LAST_MODIFIED(w, 0);
4242 SET_LAST_FACECHANGE(w);
4243 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
4244 /* overkill maybe, but better to be correct */
4245 MARK_FRAME_GUTTERS_CHANGED(f);
4247 run_window_configuration_hook( window );
4256 /* Scroll contents of window WINDOW up COUNT lines.
4257 If COUNT < (top line height / average line height) then we just adjust
4260 window_scroll(Lisp_Object window, Lisp_Object count, int direction,
4261 Error_behavior errb)
4263 struct window *w = XWINDOW(window);
4264 struct buffer *b = XBUFFER(w->buffer);
4265 int selected = EQ(window, Fselected_window(Qnil));
4267 Lisp_Object point, tem;
4268 display_line_dynarr *dla;
4269 int fheight, fwidth, modeline = 0;
4270 struct display_line *dl;
4273 point = make_int(BUF_PT(b));
4275 Bufpos pos = marker_position(w->pointm[CURRENT_DISP]);
4277 if (pos < BUF_BEGV(b))
4279 else if (pos > BUF_ZV(b))
4282 point = make_int(pos);
4285 /* Always set force_start so that redisplay_window will run
4286 the window-scroll-functions. */
4289 /* #### When the fuck does this happen? I'm so glad that history has
4290 completely documented the behavior of the scrolling functions under
4291 all circumstances. */
4292 tem = Fpos_visible_in_window_p(point, window);
4294 Fvertical_motion(make_int(-window_char_height(w, 0) / 2),
4296 Fset_marker(w->start[CURRENT_DISP], point, w->buffer);
4297 w->start_at_line_beg = beginning_of_line_p(b, XINT(point));
4298 WINDOW_TEXT_TOP_CLIP(w) = 0;
4299 MARK_WINDOWS_CHANGED(w);
4303 if (EQ(count, Qminus))
4306 count = Fprefix_numeric_value(count);
4307 value = XINT(count) * direction;
4310 return; /* someone just made a pointless call */
4314 /* If the user didn't specify how far to scroll then we have to figure it
4315 out by ourselves. */
4316 if (NILP(count) || EQ(count, Qminus)) {
4317 /* Going forwards is easy. If that is what we are doing then just
4318 set value and the section which handles the user specifying a
4319 positive value will work. */
4320 if (direction == 1) {
4322 window_displayed_height(w) -
4323 next_screen_context_lines;
4324 value = (value < 1 ? 1 : value);
4327 /* Going backwards is hard. We can't use the same loop used if the
4328 user specified a negative value because we care about
4329 next_screen_context_lines. In a variable height world you don't
4330 know how many lines above you can actually be displayed and still
4331 have the context lines appear. So we leave value set to 0 and add
4332 a separate section to deal with this. */
4336 if (direction == 1 && !value) {
4340 /* Determine parameters to test for partial line scrolling with. */
4341 dla = window_display_lines(w, CURRENT_DISP);
4343 if (INTP(Vwindow_pixel_scroll_increment))
4344 fheight = XINT(Vwindow_pixel_scroll_increment);
4345 else if (!NILP(Vwindow_pixel_scroll_increment))
4346 default_face_height_and_width(window, &fheight, &fwidth);
4348 if (Dynarr_length(dla) >= 1)
4349 modeline = Dynarr_atp(dla, 0)->modeline;
4351 dl = Dynarr_atp(dla, modeline);
4354 /* Go for partial display line scrolling. This just means bumping
4355 the clip by a reasonable amount and redisplaying, everything else
4356 remains unchanged. */
4357 if (!NILP(Vwindow_pixel_scroll_increment)
4358 && Dynarr_length(dla) >= (1 + modeline)
4359 && (dl->ascent - dl->top_clip) > fheight * value) {
4360 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4361 MARK_WINDOWS_CHANGED(w);
4364 Bufpos startp, old_start;
4366 if (WINDOW_TEXT_TOP_CLIP(w)) {
4367 WINDOW_TEXT_TOP_CLIP(w) = 0;
4368 MARK_WINDOWS_CHANGED(w);
4371 old_start = marker_position(w->start[CURRENT_DISP]);
4372 startp = vmotion(w, old_start, value, &vtarget);
4374 if (vtarget < value &&
4375 (w->window_end_pos[CURRENT_DISP] == -1
4376 || (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] >
4378 maybe_signal_error(Qend_of_buffer, Qnil,
4382 set_marker_restricted(w->start[CURRENT_DISP],
4386 w->start_at_line_beg =
4387 beginning_of_line_p(b, startp);
4388 MARK_WINDOWS_CHANGED(w);
4390 if (!point_would_be_visible
4391 (w, startp, XINT(point))) {
4393 BUF_SET_PT(b, startp);
4395 set_marker_restricted(w->
4405 } else if (value < 0) {
4406 /* Go for partial display line scrolling. This just means bumping
4407 the clip by a reasonable amount and redisplaying, everything else
4408 remains unchanged. */
4409 if (!NILP(Vwindow_pixel_scroll_increment)
4410 && Dynarr_length(dla) >= (1 + modeline)
4412 (dl->ascent - dl->top_clip) - fheight * value <
4413 (dl->ascent + dl->descent - dl->clip)
4414 && WINDOW_TEXT_TOP_CLIP(w) + value * fheight > 0) {
4415 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4416 MARK_WINDOWS_CHANGED(w);
4419 Bufpos startp, old_start;
4421 if (WINDOW_TEXT_TOP_CLIP(w)) {
4422 WINDOW_TEXT_TOP_CLIP(w) = 0;
4423 MARK_WINDOWS_CHANGED(w);
4426 old_start = marker_position(w->start[CURRENT_DISP]);
4427 startp = vmotion(w, old_start, value, &vtarget);
4430 && marker_position(w->start[CURRENT_DISP]) ==
4432 maybe_signal_error(Qbeginning_of_buffer, Qnil,
4436 set_marker_restricted(w->start[CURRENT_DISP],
4440 w->start_at_line_beg =
4441 beginning_of_line_p(b, startp);
4442 MARK_WINDOWS_CHANGED(w);
4444 /* #### Scroll back by less than a line. This code was
4445 originally for scrolling over large pixmaps and it
4446 loses when a line being *exposed* at the top of the
4447 window is bigger than the current one. However, for
4448 pixel based scrolling in general we can guess that
4449 the line we are going to display is probably the same
4450 size as the one we are on. In that instance we can
4451 have a reasonable stab at a suitable top clip. Fixing
4452 this properly is hard (and probably slow) as we would
4453 have to call redisplay to figure out the exposed line
4455 if (!NILP(Vwindow_pixel_scroll_increment)
4456 && Dynarr_length(dla) >= (1 + modeline)
4457 && dl->ascent + fheight * value > 0) {
4458 WINDOW_TEXT_TOP_CLIP(w) =
4459 (dl->ascent + fheight * value);
4462 if (!point_would_be_visible
4463 (w, startp, XINT(point))) {
4466 if (MINI_WINDOW_P(w))
4470 start_of_last_line(w,
4474 BUF_SET_PT(b, new_point);
4476 set_marker_restricted(w->
4486 } else { /* value == 0 && direction == -1 */
4488 if (WINDOW_TEXT_TOP_CLIP(w)) {
4489 WINDOW_TEXT_TOP_CLIP(w) = 0;
4490 MARK_WINDOWS_CHANGED(w);
4492 if (marker_position(w->start[CURRENT_DISP]) == BUF_BEGV(b)) {
4493 maybe_signal_error(Qbeginning_of_buffer, Qnil, Qwindow,
4498 int movement = next_screen_context_lines - 1;
4500 marker_position(w->start[CURRENT_DISP]);
4502 vmotion(w, old_startp, movement, &vtarget);
4504 start_with_point_on_display_line(w, bottom,
4508 if (startp >= old_startp)
4509 startp = vmotion(w, old_startp, -1, NULL);
4511 set_marker_restricted(w->start[CURRENT_DISP],
4512 make_int(startp), w->buffer);
4514 w->start_at_line_beg = beginning_of_line_p(b, startp);
4515 MARK_WINDOWS_CHANGED(w);
4517 if (!point_would_be_visible(w, startp, XINT(point))) {
4519 start_of_last_line(w, startp);
4522 BUF_SET_PT(b, new_point);
4524 set_marker_restricted(w->
4535 DEFUN("scroll-up", Fscroll_up, 0, 1, "_P", /*
4536 Scroll text of current window up COUNT lines; or near full screen if no arg.
4537 A near full screen is `next-screen-context-lines' less than a full screen.
4538 Negative COUNT means scroll downward.
4539 When calling from a program, supply an integer as argument or nil.
4540 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4541 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4544 The characters that are moved over may be added to the current selection
4545 \(i.e. active region) if the Shift key is held down, a motion key is used
4546 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4547 the documentation for this variable for more details.
4551 window_scroll(Fselected_window(Qnil), count, 1, ERROR_ME);
4555 DEFUN("scroll-down", Fscroll_down, 0, 1, "_P", /*
4556 Scroll text of current window down COUNT lines; or near full screen if no arg.
4557 A near full screen is `next-screen-context-lines' less than a full screen.
4558 Negative COUNT means scroll upward.
4559 When calling from a program, supply a number as argument or nil.
4560 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4561 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4564 The characters that are moved over may be added to the current selection
4565 \(i.e. active region) if the Shift key is held down, a motion key is used
4566 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4567 the documentation for this variable for more details.
4571 window_scroll(Fselected_window(Qnil), count, -1, ERROR_ME);
4575 DEFUN("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4576 Return the other window for "other window scroll" commands.
4577 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4578 specifies the window.
4579 If `other-window-scroll-buffer' is non-nil, a window
4580 showing that buffer is used.
4585 Lisp_Object selected_window = Fselected_window(Qnil);
4587 if (MINI_WINDOW_P(XWINDOW(selected_window))
4588 && !NILP(Vminibuffer_scroll_window))
4589 window = Vminibuffer_scroll_window;
4590 /* If buffer is specified, scroll that buffer. */
4591 else if (!NILP(Vother_window_scroll_buffer)) {
4593 Fget_buffer_window(Vother_window_scroll_buffer, Qnil, Qnil);
4596 display_buffer(Vother_window_scroll_buffer, Qt,
4599 /* Nothing specified; look for a neighboring window on the same
4601 window = Fnext_window(selected_window, Qnil, Qnil, Qnil);
4603 if (EQ(window, selected_window))
4604 /* That didn't get us anywhere; look for a window on another
4607 window = Fnext_window(window, Qnil, Qt, Qnil);
4608 while (!FRAME_VISIBLE_P
4609 (XFRAME(WINDOW_FRAME(XWINDOW(window))))
4610 && !EQ(window, selected_window));
4613 CHECK_LIVE_WINDOW(window);
4615 if (EQ(window, selected_window))
4616 error("There is no other window");
4621 DEFUN("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4622 Scroll next window upward COUNT lines; or near full frame if no arg.
4623 The next window is the one below the current one; or the one at the top
4624 if the current one is at the bottom. Negative COUNT means scroll downward.
4625 When calling from a program, supply a number as argument or nil.
4627 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4628 specifies the window to scroll.
4629 If `other-window-scroll-buffer' is non-nil, scroll the window
4630 showing that buffer, popping the buffer up if necessary.
4634 window_scroll(Fother_window_for_scrolling(), count, 1, ERROR_ME);
4638 DEFUN("scroll-left", Fscroll_left, 0, 1, "_P", /*
4639 Scroll selected window display COUNT columns left.
4640 Default for COUNT is window width minus 2.
4642 The characters that are moved over may be added to the current selection
4643 \(i.e. active region) if the Shift key is held down, a motion key is used
4644 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4645 the documentation for this variable for more details.
4649 Lisp_Object window = Fselected_window(Qnil);
4650 struct window *w = XWINDOW(window);
4651 int n = (NILP(count) ?
4652 window_char_width(w, 0) - 2 :
4653 XINT(Fprefix_numeric_value(count)));
4655 return Fset_window_hscroll(window, make_int(w->hscroll + n));
4658 DEFUN("scroll-right", Fscroll_right, 0, 1, "_P", /*
4659 Scroll selected window display COUNT columns right.
4660 Default for COUNT is window width minus 2.
4662 The characters that are moved over may be added to the current selection
4663 \(i.e. active region) if the Shift key is held down, a motion key is used
4664 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4665 the documentation for this variable for more details.
4669 Lisp_Object window = Fselected_window(Qnil);
4670 struct window *w = XWINDOW(window);
4671 int n = (NILP(count) ?
4672 window_char_width(w, 0) - 2 :
4673 XINT(Fprefix_numeric_value(count)));
4675 return Fset_window_hscroll(window, make_int(w->hscroll - n));
4678 DEFUN("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4679 Center point in WINDOW. With N, put point on line N.
4680 The desired position of point is always relative to the window.
4681 If WINDOW is nil, the selected window is used.
4685 struct window *w = decode_window(window);
4686 struct buffer *b = XBUFFER(w->buffer);
4687 Bufpos opoint = BUF_PT(b);
4692 start_with_line_at_pixpos(w, opoint, window_half_pixpos(w));
4694 n = Fprefix_numeric_value(n);
4696 startp = start_with_point_on_display_line(w, opoint, XINT(n));
4699 Fset_marker(w->start[CURRENT_DISP], make_int(startp), w->buffer);
4701 w->start_at_line_beg = beginning_of_line_p(b, startp);
4703 MARK_WINDOWS_CHANGED(w);
4707 DEFUN("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4708 Position point relative to WINDOW.
4709 With no argument, position text at center of window.
4710 An argument specifies window line; zero means top of window,
4711 negative means relative to bottom of window.
4712 If WINDOW is nil, the selected window is used.
4719 Bufpos start, new_point;
4722 /* Don't use decode_window() because we need the new value of
4725 window = Fselected_window(Qnil);
4727 CHECK_LIVE_WINDOW(window);
4728 w = XWINDOW(window);
4729 b = XBUFFER(w->buffer);
4731 height = window_displayed_height(w);
4732 selected = EQ(window, Fselected_window(w->frame));
4737 if (XINT(w->last_modified[CURRENT_DISP]) >= BUF_MODIFF(b)
4738 && XINT(w->last_facechange[CURRENT_DISP]) >=
4739 BUF_FACECHANGE(b)) {
4740 new_point = point_at_center(w, CURRENT_DISP, 0, 0);
4743 BUF_SET_PT(b, new_point);
4745 Fset_window_point(window, make_int(new_point));
4747 retval = line_at_center(w, CURRENT_DISP, 0, 0);
4749 start = marker_position(w->start[CURRENT_DISP]);
4750 if (start < BUF_BEGV(b))
4751 start = BUF_BEGV(b);
4752 else if (start > BUF_ZV(b))
4756 new_point = BUF_PT(b);
4759 marker_position(w->pointm[CURRENT_DISP]);
4762 point_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4765 BUF_SET_PT(b, new_point);
4767 Fset_window_point(window, make_int(new_point));
4770 line_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4773 return make_int(retval);
4775 /* #### Is this going to work right when at eob? */
4776 arg = Fprefix_numeric_value(arg);
4778 XSETINT(arg, XINT(arg) + height);
4781 start = marker_position(w->start[CURRENT_DISP]);
4782 if (start < BUF_BEGV(b) || start > BUF_ZV(b)) {
4784 new_point = BUF_PT(b);
4786 new_point = marker_position(w->pointm[CURRENT_DISP]);
4788 new_point = vmotion(XWINDOW(window), new_point, -height / 2, 0);
4791 BUF_SET_PT(b, new_point);
4793 Fset_window_point(window, make_int(new_point));
4795 Fset_marker(w->start[CURRENT_DISP], make_int(new_point),
4797 w->start_at_line_beg = beginning_of_line_p(b, new_point);
4801 BUF_SET_PT(b, start);
4803 Fset_window_point(window, make_int(start));
4807 return Fvertical_motion(arg, window, Qnil);
4810 new_point = vmotion(XWINDOW(window),
4811 marker_position(w->pointm[CURRENT_DISP]),
4813 Fset_window_point(window, make_int(new_point));
4814 return make_int(vpos);
4819 map_windows_1(Lisp_Object window,
4820 int (*mapfun) (struct window * w, void *closure), void *closure)
4822 for (; !NILP(window); window = XWINDOW(window)->next) {
4824 struct window *w = XWINDOW(window);
4826 if (!NILP(w->vchild))
4827 retval = map_windows_1(w->vchild, mapfun, closure);
4828 else if (!NILP(w->hchild))
4829 retval = map_windows_1(w->hchild, mapfun, closure);
4831 retval = (mapfun) (w, closure);
4840 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4841 invocation of MAPFUN. If any invocation of MAPFUN returns
4842 non-zero, the mapping is halted. Otherwise, map_windows() maps
4843 over all windows in F.
4845 If MAPFUN creates or deletes windows, the behavior is undefined. */
4848 map_windows(struct frame *f, int (*mapfun) (struct window * w, void *closure),
4852 return map_windows_1(FRAME_ROOT_WINDOW(f), mapfun, closure);
4854 Lisp_Object frmcons, devcons, concons;
4856 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
4858 map_windows_1(FRAME_ROOT_WINDOW
4859 (XFRAME(XCAR(frmcons))),
4870 modeline_shadow_thickness_changed(Lisp_Object specifier, struct window *w,
4873 w->shadow_thickness_changed = 1;
4874 MARK_WINDOWS_CHANGED(w);
4878 vertical_divider_changed_in_window(Lisp_Object specifier,
4879 struct window *w, Lisp_Object oldval)
4881 MARK_WINDOWS_CHANGED(w);
4882 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(XFRAME(WINDOW_FRAME(w)));
4885 /* also used in scrollbar.c */
4887 some_window_value_changed(Lisp_Object specifier, struct window *w,
4890 MARK_WINDOWS_CHANGED(w);
4893 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
4895 struct window_stats {
4898 #ifdef HAVE_SCROLLBARS
4902 int other_redisplay;
4907 compute_window_mirror_usage(struct window_mirror *mir,
4908 struct window_stats *stats,
4909 struct overhead_stats *ovstats)
4913 stats->other += malloced_storage_size(mir, sizeof(struct window_mirror),
4915 #ifdef HAVE_SCROLLBARS
4917 struct device *d = XDEVICE(FRAME_DEVICE(mir->frame));
4920 compute_scrollbar_instance_usage(d,
4922 scrollbar_vertical_instance,
4925 compute_scrollbar_instance_usage(d,
4927 scrollbar_horizontal_instance,
4930 #endif /* HAVE_SCROLLBARS */
4931 stats->other_redisplay +=
4932 compute_display_line_dynarr_usage(mir->current_display_lines,
4934 stats->other_redisplay +=
4935 compute_display_line_dynarr_usage(mir->desired_display_lines,
4940 compute_window_usage(struct window *w, struct window_stats *stats,
4941 struct overhead_stats *ovstats)
4945 malloced_storage_size(w, sizeof(struct window), ovstats);
4946 stats->face += compute_face_cachel_usage(w->face_cachels, ovstats);
4947 stats->glyph += compute_glyph_cachel_usage(w->glyph_cachels, ovstats);
4948 stats->line_start +=
4949 compute_line_start_cache_dynarr_usage(w->line_start_cache, ovstats);
4950 compute_window_mirror_usage(find_window_mirror(w), stats, ovstats);
4953 DEFUN("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4954 Return stats about the memory usage of window WINDOW.
4955 The values returned are in the form of an alist of usage types and byte
4956 counts. The byte counts attempt to encompass all the memory used
4957 by the window (separate from the memory logically associated with a
4958 buffer or frame), including internal structures and any malloc()
4959 overhead associated with them. In practice, the byte counts are
4960 underestimated because certain memory usage is very hard to determine
4961 \(e.g. the amount of memory used inside the Xt library or inside the
4962 X server) and because there is other stuff that might logically
4963 be associated with a window, buffer, or frame (e.g. window configurations,
4964 glyphs) but should not obviously be included in the usage counts.
4966 Multiple slices of the total memory usage may be returned, separated
4967 by a nil. Each slice represents a particular view of the memory, a
4968 particular way of partitioning it into groups. Within a slice, there
4969 is no overlap between the groups of memory, and each slice collectively
4970 represents all the memory concerned.
4974 struct window_stats stats;
4975 struct overhead_stats ovstats;
4976 Lisp_Object val = Qnil;
4978 CHECK_WINDOW(window); /* dead windows should be allowed, no? */
4980 compute_window_usage(XWINDOW(window), &stats, &ovstats);
4982 val = acons(Qface_cache, make_int(stats.face), val);
4983 val = acons(Qglyph_cache, make_int(stats.glyph), val);
4984 #ifdef HAVE_SCROLLBARS
4985 val = acons(Qscrollbar_instances, make_int(stats.scrollbar), val);
4987 val = acons(Qline_start_cache, make_int(stats.line_start), val);
4988 val = acons(Qother_redisplay, make_int(stats.other_redisplay), val);
4989 val = acons(Qother, make_int(stats.other), val);
4990 val = Fcons(Qnil, val);
4991 val = acons(Qactually_requested, make_int(ovstats.was_requested), val);
4992 val = acons(Qmalloc_overhead, make_int(ovstats.malloc_overhead), val);
4993 val = acons(Qdynarr_overhead, make_int(ovstats.dynarr_overhead), val);
4995 return Fnreverse(val);
4998 #endif /* MEMORY_USAGE_STATS */
5000 /************************************************************************/
5001 /* Window configurations */
5002 /************************************************************************/
5004 /* #### This window configuration stuff has had serious bugs lurking in it
5005 for years; it would be a -huge- win if this was reimplemented in lisp.
5008 /* If you add anything to this structure make sure saved_window_equal
5010 struct saved_window {
5011 Lisp_Object window; /* window */
5012 Lisp_Object buffer; /* buffer */
5013 Lisp_Object start; /* copied marker */
5014 Lisp_Object pointm; /* copied marker */
5015 Lisp_Object sb_point; /* copied marker */
5016 Lisp_Object mark; /* copied marker */
5022 Charcount modeline_hscroll;
5023 int parent_index; /* index into saved_windows */
5024 int prev_index; /* index into saved_windows */
5025 char start_at_line_beg; /* boolean */
5027 #define WINDOW_SLOT_DECLARATION
5028 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5029 #include "winslots.h"
5032 /* If you add anything to this structure make sure window_config_equal
5034 struct window_config {
5035 struct lcrecord_header header;
5036 /* int frame_width; No longer needed, JV
5037 int frame_height; */
5039 Lisp_Object selected_frame;
5041 Lisp_Object current_window;
5042 Lisp_Object current_buffer;
5043 Lisp_Object minibuffer_scroll_window;
5044 Lisp_Object root_window;
5045 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5046 /* Record the values of window-min-width and window-min-height
5047 so that window sizes remain consistent with them. */
5048 int min_width, min_height;
5049 unsigned int saved_windows_count;
5050 /* Zero-sized arrays aren't ANSI C */
5051 struct saved_window saved_windows[1];
5054 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5055 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5056 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5057 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5058 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5060 static Lisp_Object mark_window_config(Lisp_Object obj)
5062 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5064 mark_object(config->current_window);
5065 mark_object(config->current_buffer);
5066 mark_object(config->minibuffer_scroll_window);
5067 mark_object(config->root_window);
5069 for (i = 0; i < config->saved_windows_count; i++) {
5070 struct saved_window *s = SAVED_WINDOW_N(config, i);
5071 mark_object(s->window);
5072 mark_object(s->buffer);
5073 mark_object(s->start);
5074 mark_object(s->pointm);
5075 mark_object(s->sb_point);
5076 mark_object(s->mark);
5078 /* #### This looked like this. I do not see why specifier cached
5079 values should not be marked, as such specifiers as toolbars
5080 might have GC-able instances. Freed configs are not marked,
5081 aren't they? -- kkm */
5082 mark_object(s->dedicated);
5084 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5085 #include "winslots.h"
5091 inline static size_t sizeof_window_config_for_n_windows(unsigned int n)
5093 return FLEXIBLE_ARRAY_STRUCT_SIZEOF(struct window_config,
5094 struct saved_window, saved_windows,
5098 static size_t sizeof_window_config(const void *h)
5100 const struct window_config *c = (const struct window_config *)h;
5101 return sizeof_window_config_for_n_windows(c->saved_windows_count);
5105 print_window_config(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5107 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5109 error("printing unreadable object #<window-configuration 0x%x>",
5110 config->header.uid);
5111 write_fmt_str(printcharfun, "#<window-configuration 0x%x>", config->header.uid);
5114 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("window-configuration",
5115 window_configuration,
5117 print_window_config,
5118 0, 0, 0, 0, sizeof_window_config,
5119 struct window_config);
5121 /* Returns a boolean indicating whether the two saved windows are
5124 saved_window_equal(struct saved_window *win1, struct saved_window *win2)
5126 #define WINDOW_SLOT(slot, compare) \
5127 if (!compare (win1->slot, win2->slot)) \
5129 #include "winslots.h"
5132 EQ(win1->window, win2->window) &&
5133 EQ(win1->buffer, win2->buffer) &&
5134 internal_equal(win1->start, win2->start, 0) &&
5135 internal_equal(win1->pointm, win2->pointm, 0) &&
5136 internal_equal(win1->sb_point, win2->sb_point, 0) &&
5137 internal_equal(win1->mark, win2->mark, 0) &&
5138 win1->pixel_left == win2->pixel_left &&
5139 win1->pixel_top == win2->pixel_top &&
5140 win1->pixel_width == win2->pixel_width &&
5141 win1->pixel_height == win2->pixel_height &&
5142 win1->hscroll == win2->hscroll &&
5143 win1->modeline_hscroll == win2->modeline_hscroll &&
5144 win1->parent_index == win2->parent_index &&
5145 win1->prev_index == win2->prev_index &&
5146 win1->start_at_line_beg == win2->start_at_line_beg;
5149 /* Returns a boolean indicating whether the two given configurations
5151 static int window_config_equal(Lisp_Object conf1, Lisp_Object conf2)
5153 struct window_config *fig1, *fig2;
5156 /* First check if they are truly the same. */
5157 if (EQ(conf1, conf2))
5160 fig1 = XWINDOW_CONFIGURATION(conf1);
5161 fig2 = XWINDOW_CONFIGURATION(conf2);
5163 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5164 EQ(fig1->current_window, fig2->current_window) &&
5165 EQ(fig1->current_buffer, fig2->current_buffer) &&
5166 EQ(fig1->root_window, fig2->root_window) &&
5167 EQ(fig1->minibuffer_scroll_window,
5168 fig2->minibuffer_scroll_window)))
5170 fig1->frame_width == fig2->frame_width &&
5171 fig1->frame_height == fig2->frame_height)) */
5174 for (i = 0; i < fig1->saved_windows_count; i++) {
5175 if (!saved_window_equal(SAVED_WINDOW_N(fig1, i),
5176 SAVED_WINDOW_N(fig2, i)))
5183 DEFUN("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5184 Return t if OBJECT is a window-configuration object.
5188 return WINDOW_CONFIGURATIONP(object) ? Qt : Qnil;
5191 static int mark_windows_in_use_closure(struct window *w, void *closure)
5193 int mark = *(int *)closure;
5194 w->config_mark = mark;
5198 static void mark_windows_in_use(struct frame *f, int mark)
5200 map_windows(f, mark_windows_in_use_closure, &mark);
5203 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5204 static Lisp_Object free_window_configuration(Lisp_Object window_config)
5207 struct window_config *config = XWINDOW_CONFIGURATION(window_config);
5209 /* Free all the markers. It's not completely necessary that
5210 we do this (window configs sitting in a free list aren't
5211 marked normally so the markers wouldn't be marked anyway)
5212 but it's more efficient. */
5213 for (i = 0; i < config->saved_windows_count; i++) {
5214 struct saved_window *p = SAVED_WINDOW_N(config, i);
5216 if (!NILP(p->pointm)) {
5217 free_marker(XMARKER(p->pointm));
5220 if (!NILP(p->start)) {
5221 free_marker(XMARKER(p->start));
5224 if (!NILP(p->sb_point)) {
5225 free_marker(XMARKER(p->sb_point));
5228 if (!NILP(p->mark)) {
5229 free_marker(XMARKER(p->mark));
5234 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5235 xfree(window_config);
5238 if (config->saved_windows_count <=
5239 countof(Vwindow_configuration_free_list)) {
5240 free_managed_lcrecord(Vwindow_configuration_free_list
5241 [config->saved_windows_count - 1],
5248 DEFUN("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5249 Set the configuration of windows and buffers as specified by CONFIGURATION.
5250 CONFIGURATION must be a value previously returned
5251 by `current-window-configuration' (which see).
5256 struct window_config *config;
5257 struct saved_window *p;
5258 Lisp_Object new_current_buffer;
5262 struct gcpro gcpro1;
5263 Lisp_Object old_window_config;
5264 /* int previous_frame_height;
5265 int previous_frame_width; */
5266 int previous_pixel_top;
5267 int previous_pixel_height;
5268 int previous_pixel_left;
5269 int previous_pixel_width;
5270 int previous_minibuf_height, previous_minibuf_top,
5271 previous_minibuf_width;
5272 int real_font_height;
5273 int converted_minibuf_height, target_minibuf_height;
5274 int specpdl_count = specpdl_depth();
5276 GCPRO1(configuration);
5278 CHECK_WINDOW_CONFIGURATION(configuration);
5279 config = XWINDOW_CONFIGURATION(configuration);
5281 frame = XWINDOW(SAVED_WINDOW_N(config, 0)->window)->frame;
5284 /* Do not signal an error here if the frame was deleted. There are
5285 reasonable cases where we could get here with a deleted frame and
5286 just want to do close to nothing instead. */
5288 if (FRAME_LIVE_P(f)) {
5289 /* restore the frame characteristics */
5291 new_current_buffer = config->current_buffer;
5292 if (!BUFFER_LIVE_P(XBUFFER(new_current_buffer)))
5293 new_current_buffer = Qnil;
5296 * Assumed precondition: w->config_mark = 0 for all w
5297 * This procedure should ensure this is true by the time it exits
5298 * to ensure the precondition for future calls.
5300 * We use w->config_mark to know whether we're modifying a
5301 * window that is currently visible on the frame (#### we
5302 * should just be able to check whether the window is dead
5303 * or not, but this way is safer?). As we process each
5304 * window, we set its config_mark to 0. At the end, we
5305 * go through all the windows that used to be on the frame,
5306 * set each one's config_mark to 0 (to maintain the
5307 * assumed precondition) and delete each one that's no
5310 * #### Using a window-configuration to keep track of
5311 * the current windows is wasteful. All we need is the
5312 * list of windows, so we could just use a dynarr.
5314 old_window_config = Fcurrent_window_configuration(frame);
5316 /* If the new configuration is already equal to the old, then stop
5317 right here. This saves the work below and it also saves
5318 triggering a full redisplay of this window. This is a huge win
5319 when using the mouse since the mode motion code uses
5320 save-window-excursion extensively but will rarely cause the
5321 configuration to actually change. */
5322 if (window_config_equal(configuration, old_window_config)) {
5323 free_window_configuration(old_window_config);
5328 /* We can't quit or even check for quit because that may cause
5329 investigation of the frame state, which may crash if the frame is
5330 in an inconsistent state. */
5331 begin_dont_check_for_quit();
5332 record_unwind_protect(free_window_configuration,
5335 mark_windows_in_use(f, 1);
5336 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5337 /* Force subwindows to be remapped. This is overkill but saves
5338 us having to rely on the redisplay code to unmap any extant
5341 #### It does cause some extra flashing though which we could
5342 possibly avoid. So consider trying to get redisplay to work
5345 Removing the instances from the frame cache is wrong because
5346 an instance is only put in the frame cache when it is
5347 instantiated. So if we do this there is a chance that stuff
5348 will never get put back in the frame cache. */
5349 reset_frame_subwindow_instance_cache(f);
5352 /* JV: This is bogus,
5353 First of all, the units are inconsistent. The frame sizes are measured
5354 in characters but the window sizes are stored in pixels. So if a
5355 font size change happened between saving and restoring, the
5356 frame "sizes" maybe equal but the windows still should be
5357 resized. This is tickled a lot by the new "character size
5358 stays constant" policy in 21.0. It leads to very weird
5359 glitches (and possibly crashes when asserts are tickled).
5361 Just changing the units doesn't help because changing the
5362 toolbar configuration can also change the pixel positions.
5363 Luckily there is a much simpler way of doing this, see below.
5365 previous_frame_width = FRAME_WIDTH(f);
5366 previous_frame_height = FRAME_HEIGHT(f);
5367 /* If the frame has been resized since this window configuration was
5368 made, we change the frame to the size specified in the
5369 configuration, restore the configuration, and then resize it
5370 back. We keep track of the prevailing height in these variables. */
5371 if (config->frame_height != FRAME_HEIGHT(f)
5372 || config->frame_width != FRAME_WIDTH(f))
5373 change_frame_size(f, config->frame_height,
5374 config->frame_width, 0);
5377 previous_pixel_top = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top;
5378 previous_pixel_height =
5379 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_height;
5380 previous_pixel_left = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left;
5381 previous_pixel_width =
5382 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_width;
5384 /* remember some properties of the minibuffer */
5386 default_face_height_and_width(frame, &real_font_height, 0);
5387 assert(real_font_height > 0);
5389 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f)) {
5390 previous_minibuf_height
5391 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5392 previous_minibuf_top
5393 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5394 previous_minibuf_width
5395 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5397 previous_minibuf_height = 0;
5398 previous_minibuf_top = 0;
5399 previous_minibuf_width = 0;
5401 converted_minibuf_height = (previous_minibuf_height % real_font_height) == 0 ? -(previous_minibuf_height / real_font_height) : /* lines */
5402 previous_minibuf_height; /* pixels */
5404 /* Temporarily avoid any problems with windows that are smaller
5405 than they are supposed to be. */
5406 window_min_height = 1;
5407 window_min_width = 1;
5409 /* OK, now restore all the windows in the window config.
5410 This may involve "undeleting" windows, since the
5411 windows in the window config may be deleted.
5413 for (k = 0; k < config->saved_windows_count; k++) {
5414 p = SAVED_WINDOW_N(config, k);
5415 w = XWINDOW(p->window);
5418 /* The window might be dead. In this case, its redisplay
5419 structures were freed, so we need to reallocate them. */
5420 if (!w->face_cachels) {
5421 w->face_cachels = Dynarr_new(face_cachel);
5422 reset_face_cachels(w);
5424 if (!w->glyph_cachels)
5425 w->glyph_cachels = Dynarr_new(glyph_cachel);
5426 if (!w->line_start_cache)
5427 w->line_start_cache =
5428 Dynarr_new(line_start_cache);
5429 w->gutter_extent_modiff[0] = 0;
5430 w->gutter_extent_modiff[1] = 0;
5431 w->gutter_extent_modiff[2] = 0;
5432 w->gutter_extent_modiff[3] = 0;
5435 if (p->parent_index >= 0)
5437 SAVED_WINDOW_N(config,
5438 p->parent_index)->window;
5442 if (p->prev_index >= 0) {
5444 SAVED_WINDOW_N(config,
5445 p->prev_index)->window;
5447 /* This is true for a minibuffer-only frame. */
5448 if (!NILP(w->mini_p) && EQ(w->prev, p->window))
5451 XWINDOW(w->prev)->next = p->window;
5454 if (!NILP(w->parent)) {
5455 if (WINDOW_WIDTH(p) ==
5456 WINDOW_WIDTH(XWINDOW(w->parent))) {
5457 XWINDOW(w->parent)->vchild =
5459 XWINDOW(w->parent)->hchild =
5462 XWINDOW(w->parent)->hchild =
5464 XWINDOW(w->parent)->vchild =
5469 if (!w->config_mark) {
5470 /* #### This should be equivalent to the window previously
5471 having been dead. If we're brave, we'll put in an
5472 assertion to this effect. */
5473 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
5474 } else { /* if (!EQ (w->buffer, p->buffer)) */
5476 /* With the new redisplay we let it know that a change has
5477 been made and it will take care of the rest. If we don't
5478 tell it something has possibly changed it could lead to
5479 incorrect display. */
5480 MARK_WINDOWS_CHANGED(w);
5483 WINDOW_LEFT(w) = WINDOW_LEFT(p);
5484 WINDOW_TOP(w) = WINDOW_TOP(p);
5485 WINDOW_WIDTH(w) = WINDOW_WIDTH(p);
5486 WINDOW_HEIGHT(w) = WINDOW_HEIGHT(p);
5487 w->hscroll = p->hscroll;
5488 w->modeline_hscroll = p->modeline_hscroll;
5489 w->line_cache_last_updated = Qzero;
5490 /* When we restore a window's configuration, the identity of
5491 the window hasn't actually changed - so there is no
5492 reason why we shouldn't preserve the instance cache for
5493 it - unless it was originally deleted. This will often
5494 buy us something as we will not have to re-instantiate
5495 all the instances. This is because this is an instance
5496 cache - not a display cache. Preserving the display cache
5497 would definitely be wrong.
5499 We specifically want to do this for tabs, since for some
5500 reason finding a file will cause the configuration to be
5502 if (NILP(w->subwindow_instance_cache))
5503 w->subwindow_instance_cache =
5504 make_image_instance_cache_hash_table();
5506 SET_LAST_MODIFIED(w, 1);
5507 SET_LAST_FACECHANGE(w);
5510 /* #### Consider making the instance cache a winslot. */
5511 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5512 #include "winslots.h"
5514 /* Reinstall the saved buffer and pointers into it. */
5515 if (NILP(p->buffer))
5516 w->buffer = p->buffer;
5518 if (BUFFER_LIVE_P(XBUFFER(p->buffer)))
5519 /* If saved buffer is alive, install it. */
5521 w->buffer = p->buffer;
5522 w->start_at_line_beg =
5523 p->start_at_line_beg;
5524 set_marker_restricted(w->
5530 set_marker_restricted(w->
5536 set_marker_restricted(w->sb_point,
5540 Fset_marker(XBUFFER(w->buffer)->mark,
5541 Fmarker_position(p->mark),
5544 /* As documented in Fcurrent_window_configuration, don't
5545 save the location of point in the buffer which was current
5546 when the window configuration was recorded. */
5547 if (!EQ(p->buffer, new_current_buffer)
5548 && XBUFFER(p->buffer) ==
5551 pointm[CURRENT_DISP],
5553 } else if (NILP(w->buffer)
5555 !BUFFER_LIVE_P(XBUFFER(w->buffer)))
5556 /* Else if window's old buffer is dead too, get a live one. */
5558 /* #### The following line makes me nervous... */
5559 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist)); */
5561 Fget_buffer_create(QSscratch);
5562 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5563 /* This will set the markers to beginning of visible
5565 set_marker_restricted(w->
5569 set_marker_restricted(w->
5573 set_marker_restricted(w->sb_point,
5575 w->start_at_line_beg = 1;
5577 /* Keeping window's old buffer; make sure the markers
5580 /* Set window markers at start of visible range. */
5581 if (XMARKER(w->start[CURRENT_DISP])->
5583 set_marker_restricted(w->
5589 if (XMARKER(w->sb_point)->buffer == 0)
5590 set_marker_restricted(w->
5595 if (XMARKER(w->pointm[CURRENT_DISP])->
5597 set_marker_restricted(w->
5607 w->start_at_line_beg = 1;
5612 FRAME_ROOT_WINDOW(f) = config->root_window;
5613 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5614 then calls do_switch_frame() below to select the frame that was
5615 recorded in the window config as being selected.
5617 Instead, we don't ever change the selected frame, and either
5618 call Fselect_window() below if the window config's frame is
5619 currently selected, or just set the selected window of the
5620 window config's frame. */
5623 /* Set the frame height to the value it had before this function. */
5624 if (previous_frame_height != FRAME_HEIGHT(f)
5625 || previous_frame_width != FRAME_WIDTH(f))
5626 change_frame_size(f, previous_frame_height,
5627 previous_frame_width, 0);
5629 /* We just reset the size and position of the minibuffer, to its old
5630 value, which needn't be valid. So we do some magic to see which value
5631 to actually take. Then we set it.
5634 We take the old value if is in the same units but differs from the
5637 #### Now we get more cases correct then ever before, but
5638 are we treating all? For instance what if the frames minibuf window
5639 is no longer the same one?
5641 target_minibuf_height = previous_minibuf_height;
5642 if (converted_minibuf_height &&
5643 (converted_minibuf_height * config->minibuf_height) > 0 &&
5644 (converted_minibuf_height != config->minibuf_height)) {
5645 target_minibuf_height = config->minibuf_height < 0 ?
5646 -(config->minibuf_height * real_font_height) :
5647 config->minibuf_height;
5648 target_minibuf_height =
5649 max(target_minibuf_height, real_font_height);
5651 if (previous_minibuf_height) {
5652 XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top
5653 = previous_minibuf_top -
5654 (target_minibuf_height - previous_minibuf_height);
5655 set_window_pixheight(FRAME_MINIBUF_WINDOW(f),
5656 target_minibuf_height, 0);
5657 set_window_pixwidth(FRAME_MINIBUF_WINDOW(f),
5658 previous_minibuf_width, 0);
5661 /* This is a better way to deal with frame resizing, etc.
5662 What we _actually_ want is for the old (just restored)
5664 into the place of the new one. So we just do that. Simple! */
5665 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top = previous_pixel_top;
5666 /* Note that this function also updates the subwindow
5668 set_window_pixheight(FRAME_ROOT_WINDOW(f),
5669 previous_pixel_height -
5670 (target_minibuf_height -
5671 previous_minibuf_height), 0);
5672 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left = previous_pixel_left;
5673 /* Note that this function also updates the subwindow
5675 set_window_pixwidth(FRAME_ROOT_WINDOW(f), previous_pixel_width,
5678 /* If restoring in the current frame make the window current,
5679 otherwise just update the frame selected_window slot to be
5680 the restored current_window. */
5681 if (f == selected_frame()) {
5683 /* When using `pop-window-configuration', often the minibuffer
5684 ends up as the selected window even though it's not active ...
5685 I really don't know the cause of this, but it should never
5686 happen. This kludge should fix it.
5688 #### Find out why this is really going wrong. */
5689 if (!minibuf_level &&
5690 MINI_WINDOW_P(XWINDOW(config->current_window)))
5692 Fnext_window(config->current_window, Qnil,
5695 window_to_select = config->current_window;
5697 /* Do this last so that buffer stacking is calculated
5699 Fselect_window(config->current_window, Qnil);
5701 if (!NILP(new_current_buffer)) {
5702 Fset_buffer(new_current_buffer);
5703 Frecord_buffer(new_current_buffer);
5705 Fset_buffer(XWINDOW(config->current_window)->
5707 Frecord_buffer(XWINDOW(config->current_window)->
5711 set_frame_selected_window(f, config->current_window);
5713 old_window_config = Qnil; /* Warning suppression */
5715 /* Restore the minimum heights recorded in the configuration. */
5716 window_min_height = config->min_height;
5717 window_min_width = config->min_width;
5720 /* see above comment */
5721 /* Fselect_window will have made f the selected frame, so we
5722 reselect the proper frame here. Fhandle_switch_frame will change the
5723 selected window too, but that doesn't make the call to
5724 Fselect_window above totally superfluous; it still sets f's
5726 if (FRAME_LIVE_P(XFRAME(config->selected_frame)))
5727 do_switch_frame(config->selected_frame, Qnil, 0);
5730 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5732 if (FRAME_LIVE_P(f)) {
5733 /* Do this before calling recompute_all_cached_specifiers_in_window()
5734 so that things like redisplay_redraw_cursor() won't abort due
5735 to no window mirror present. */
5736 f->mirror_dirty = 1;
5738 config = XWINDOW_CONFIGURATION(old_window_config);
5739 for (k = 0; k < config->saved_windows_count; k++) {
5740 p = SAVED_WINDOW_N(config, k);
5741 w = XWINDOW(p->window);
5742 /* Remember, we set w->config_mark on all currently visible
5743 windows, and reset it on all newly visible windows.
5744 Any windows still marked need to be deleted. */
5745 if (w->config_mark) {
5746 mark_window_as_deleted(w);
5749 /* We just potentially changed the window's buffer and
5750 potentially turned a dead window into a live one,
5751 so we need to recompute the cached specifier values. */
5752 recompute_all_cached_specifiers_in_window(w);
5757 /* Now restore things, when everything else if OK. */
5759 unbind_to(specpdl_count, Qnil);
5766 /* Mark all subwindows of a window as deleted. The argument
5767 W is actually the subwindow tree of the window in question. */
5769 void delete_all_subwindows(struct window *w)
5772 delete_all_subwindows(XWINDOW(w->next));
5773 if (!NILP(w->vchild))
5774 delete_all_subwindows(XWINDOW(w->vchild));
5775 if (!NILP(w->hchild))
5776 delete_all_subwindows(XWINDOW(w->hchild));
5778 mark_window_as_deleted(w);
5781 static unsigned int count_windows(struct window *window)
5784 (!NILP(window->next) ? count_windows(XWINDOW(window->next)) : 0) +
5785 (!NILP(window->vchild) ? count_windows(XWINDOW(window->vchild)) : 0)
5787 (!NILP(window->hchild) ? count_windows(XWINDOW(window->hchild)) :
5792 saved_window_index(Lisp_Object window, struct window_config *config, int lim)
5795 for (j = 0; j < lim; j++) {
5796 if (EQ(SAVED_WINDOW_N(config, j)->window, window))
5800 return 0; /* suppress compiler warning */
5804 save_window_save(Lisp_Object window, struct window_config *config, int i)
5808 for (; !NILP(window); window = w->next) {
5809 struct saved_window *p = SAVED_WINDOW_N(config, i);
5811 w = XWINDOW(window);
5814 p->buffer = w->buffer;
5815 WINDOW_LEFT(p) = WINDOW_LEFT(w);
5816 WINDOW_TOP(p) = WINDOW_TOP(w);
5817 WINDOW_WIDTH(p) = WINDOW_WIDTH(w);
5818 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(w);
5819 p->hscroll = w->hscroll;
5820 p->modeline_hscroll = w->modeline_hscroll;
5822 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5823 #include "winslots.h"
5825 if (!NILP(w->buffer)) {
5826 /* Save w's value of point in the window configuration.
5827 If w is the selected window, then get the value of point
5828 from the buffer; pointm is garbage in the selected window. */
5829 if (EQ(window, Fselected_window(Qnil))) {
5830 p->pointm = noseeum_make_marker();
5831 Fset_marker(p->pointm,
5833 (XBUFFER(w->buffer))),
5837 noseeum_copy_marker(w->pointm[CURRENT_DISP],
5841 noseeum_copy_marker(w->start[CURRENT_DISP], Qnil);
5842 p->sb_point = noseeum_copy_marker(w->sb_point, Qnil);
5843 p->start_at_line_beg = w->start_at_line_beg;
5846 noseeum_copy_marker(XBUFFER(w->buffer)->mark, Qnil);
5852 p->start_at_line_beg = 0;
5855 if (NILP(w->parent))
5856 p->parent_index = -1;
5859 saved_window_index(w->parent, config, i);
5863 p->prev_index = saved_window_index(w->prev, config, i);
5864 if (!NILP(w->vchild))
5865 i = save_window_save(w->vchild, config, i);
5866 if (!NILP(w->hchild))
5867 i = save_window_save(w->hchild, config, i);
5874 /* Added to doc string:
5876 This also records the currently selected frame, and FRAME's focus
5877 redirection (see `redirect-frame-focus').
5882 DEFUN("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5883 Return an object representing the current window configuration of FRAME.
5884 If FRAME is nil or omitted, use the selected frame.
5885 This describes the number of windows, their sizes and current buffers,
5886 and for each window on FRAME the displayed buffer, where display
5887 starts, and the positions of point and mark.
5888 An exception is made for point in the current buffer:
5889 its value is -not- saved.
5894 struct frame *f = decode_frame(frame);
5895 struct window_config *config;
5896 unsigned int n_windows = count_windows(XWINDOW(FRAME_ROOT_WINDOW(f)));
5898 int real_font_height;
5900 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5901 config = (struct window_config *)
5902 alloc_lcrecord(sizeof_window_config_for_n_windows(
5904 &lrecord_window_configuration);
5906 if (n_windows <= countof(Vwindow_configuration_free_list)) {
5908 allocate_managed_lcrecord(
5909 Vwindow_configuration_free_list[n_windows - 1]);
5910 config = XWINDOW_CONFIGURATION(tmp);
5912 /* More than ten windows; just allocate directly */
5913 config = (struct window_config *)
5914 alloc_lcrecord(sizeof_window_config_for_n_windows(
5916 &lrecord_window_configuration);
5919 XSETWINDOW_CONFIGURATION(result, config);
5921 config->frame_width = FRAME_WIDTH (f);
5922 config->frame_height = FRAME_HEIGHT (f); */
5923 /* #### When using `push-window-configuration', often the minibuffer
5924 ends up as the selected window because functions run as the result
5925 of user interaction e.g. hyper-apropos. It seems to me the sensible
5926 thing to do is not record the minibuffer here.
5928 #### Unfortunately this is a change to previous behaviour,
5929 however logical it may be, so revert for the moment. */
5931 if (FRAME_MINIBUF_ONLY_P(f) || minibuf_level)
5932 config->current_window = FRAME_SELECTED_WINDOW(f);
5934 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW(f);
5936 config->current_window = FRAME_SELECTED_WINDOW(f);
5937 XSETBUFFER(config->current_buffer, current_buffer);
5938 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5939 config->root_window = FRAME_ROOT_WINDOW(f);
5940 config->min_height = window_min_height;
5941 config->min_width = window_min_width;
5942 config->saved_windows_count = n_windows;
5943 save_window_save(FRAME_ROOT_WINDOW(f), config, 0);
5945 /* save the minibuffer height using the heuristics from
5946 change_frame_size_1 */
5948 XSETFRAME(frame, f); /* frame could have been nil ! */
5949 default_face_height_and_width(frame, &real_font_height, 0);
5950 assert(real_font_height > 0);
5952 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f))
5953 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5956 config->minibuf_height = (minibuf_height % real_font_height) == 0 ? -(minibuf_height / real_font_height) : /* lines */
5957 minibuf_height; /* pixels */
5962 Lisp_Object save_window_excursion_unwind(Lisp_Object window_config)
5964 Lisp_Object val = Fset_window_configuration(window_config);
5965 free_window_configuration(window_config);
5969 DEFUN("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5970 Execute body, preserving window sizes and contents.
5971 Restores which buffer appears in which window, where display starts,
5972 as well as the current buffer.
5973 Does not restore the value of point in current buffer.
5977 /* This function can GC */
5979 int speccount = specpdl_depth();
5981 record_unwind_protect(save_window_excursion_unwind,
5982 Fcurrent_window_configuration(Qnil));
5984 return unbind_to(speccount, val);
5987 DEFUN("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5988 Return the horizontal pixel position of POS in window.
5989 Beginning of line is column 0. This is calculated using the redisplay
5990 display tables. If WINDOW is nil, the current window is assumed.
5991 If POS is nil, point is assumed. Note that POS must be visible for
5992 a non-nil result to be returned.
5996 struct window *w = decode_window(window);
5997 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
5999 struct display_line *dl = 0;
6000 struct display_block *db = 0;
6001 struct rune *rb = 0;
6002 int y = w->last_point_y[CURRENT_DISP];
6003 int x = w->last_point_x[CURRENT_DISP];
6005 if (MINI_WINDOW_P(w))
6008 if (y < 0 || x < 0 || y >= Dynarr_length(dla) || !NILP(pos)) {
6013 pos = Fwindow_point(window);
6018 if (Dynarr_length(dla) && Dynarr_atp(dla, 0)->modeline)
6023 for (i = first_line; i < Dynarr_length(dla); i++) {
6024 dl = Dynarr_atp(dla, i);
6025 /* find the vertical location first */
6026 if (point >= dl->bufpos && point <= dl->end_bufpos) {
6027 db = get_display_block_from_line(dl, TEXT);
6028 for (i = 0; i < Dynarr_length(db->runes); i++) {
6029 rb = Dynarr_atp(db->runes, i);
6030 if (point <= rb->bufpos)
6040 /* optimized case */
6041 dl = Dynarr_atp(dla, y);
6042 db = get_display_block_from_line(dl, TEXT);
6044 if (x >= Dynarr_length(db->runes))
6047 rb = Dynarr_atp(db->runes, x);
6050 return make_int(rb->xpos - WINDOW_LEFT(w));
6053 #ifdef DEBUG_SXEMACS
6054 /* This is short and simple in elisp, but... it was written to debug
6055 problems purely on the C side. That is where we need to call it so
6057 static void debug_print_window(Lisp_Object window, int level)
6060 Lisp_Object child = Fwindow_first_vchild(window);
6063 child = Fwindow_first_hchild(window);
6065 for (i = level; i > 0; i--)
6068 stderr_out("#<window");
6070 Lisp_Object buffer = XWINDOW(window)->buffer;
6071 if (!NILP(buffer) && BUFFERP(buffer))
6072 stderr_out(" on %s",
6073 XSTRING_DATA(XBUFFER(buffer)->name));
6075 stderr_out(" 0x%x>", XWINDOW(window)->header.uid);
6077 while (!NILP(child)) {
6078 debug_print_window(child, level + 1);
6079 child = Fwindow_next_child(child);
6083 void debug_print_windows(struct frame *f);
6084 void debug_print_windows(struct frame *f)
6086 debug_print_window(f->root_window, 0);
6089 #endif /* DEBUG_SXEMACS */
6091 /************************************************************************/
6092 /* initialization */
6093 /************************************************************************/
6095 void syms_of_window(void)
6097 INIT_LRECORD_IMPLEMENTATION(window);
6098 INIT_LRECORD_IMPLEMENTATION(window_configuration);
6100 defsymbol(&Qwindowp, "windowp");
6101 defsymbol(&Qwindow_live_p, "window-live-p");
6102 defsymbol(&Qwindow_configurationp, "window-configuration-p");
6103 defsymbol(&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6104 defsymbol(&Qdisplay_buffer, "display-buffer");
6106 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6107 defsymbol(&Qface_cache, "face-cache");
6108 defsymbol(&Qglyph_cache, "glyph-cache");
6109 defsymbol(&Qline_start_cache, "line-start-cache");
6110 #ifdef HAVE_SCROLLBARS
6111 defsymbol(&Qscrollbar_instances, "scrollbar-instances");
6113 defsymbol(&Qother_redisplay, "other-redisplay");
6114 /* Qother in general.c */
6117 DEFSYMBOL(Qtruncate_partial_width_windows);
6118 DEFSYMBOL (Qwindow_configuration_hook);
6120 DEFSUBR(Fselected_window);
6121 DEFSUBR(Flast_nonminibuf_window);
6122 DEFSUBR(Fminibuffer_window);
6123 DEFSUBR(Fwindow_minibuffer_p);
6125 DEFSUBR(Fwindow_live_p);
6126 DEFSUBR(Fwindow_first_hchild);
6127 DEFSUBR(Fwindow_first_vchild);
6128 DEFSUBR(Fwindow_next_child);
6129 DEFSUBR(Fwindow_previous_child);
6130 DEFSUBR(Fwindow_parent);
6131 DEFSUBR(Fwindow_lowest_p);
6132 DEFSUBR(Fwindow_truncated_p);
6133 DEFSUBR(Fwindow_highest_p);
6134 DEFSUBR(Fwindow_leftmost_p);
6135 DEFSUBR(Fwindow_rightmost_p);
6136 DEFSUBR(Fpos_visible_in_window_p);
6137 DEFSUBR(Fwindow_buffer);
6138 DEFSUBR(Fwindow_frame);
6139 DEFSUBR(Fwindow_height);
6140 DEFSUBR(Fwindow_displayed_height);
6141 DEFSUBR(Fwindow_width);
6142 DEFSUBR(Fwindow_full_width);
6143 DEFSUBR(Fwindow_pixel_height);
6144 DEFSUBR(Fwindow_pixel_width);
6145 DEFSUBR(Fwindow_text_area_height);
6146 DEFSUBR(Fwindow_text_area_pixel_height);
6147 DEFSUBR(Fwindow_displayed_text_pixel_height);
6148 DEFSUBR(Fwindow_text_area_pixel_width);
6149 DEFSUBR(Fwindow_hscroll);
6150 DEFSUBR(Fset_window_hscroll);
6151 DEFSUBR(Fmodeline_hscroll);
6152 DEFSUBR(Fset_modeline_hscroll);
6153 #if 0 /* bogus FSF crock */
6154 DEFSUBR(Fwindow_redisplay_end_trigger);
6155 DEFSUBR(Fset_window_redisplay_end_trigger);
6157 DEFSUBR(Fwindow_pixel_edges);
6158 DEFSUBR(Fwindow_text_area_pixel_edges);
6159 DEFSUBR(Fwindow_point);
6160 DEFSUBR(Fwindow_start);
6161 DEFSUBR(Fwindow_end);
6162 DEFSUBR(Fwindow_last_line_visible_height);
6163 DEFSUBR(Fset_window_point);
6164 DEFSUBR(Fset_window_start);
6165 DEFSUBR(Fwindow_dedicated_p);
6166 DEFSUBR(Fset_window_dedicated_p);
6167 DEFSUBR(Fnext_window);
6168 DEFSUBR(Fprevious_window);
6169 DEFSUBR(Fnext_vertical_window);
6170 DEFSUBR(Fother_window);
6171 DEFSUBR(Fget_lru_window);
6172 DEFSUBR(Fget_largest_window);
6173 DEFSUBR(Fget_buffer_window);
6174 DEFSUBR(Fwindow_left_margin_pixel_width);
6175 DEFSUBR(Fwindow_right_margin_pixel_width);
6176 DEFSUBR(Fdelete_other_windows);
6177 DEFSUBR(Fdelete_windows_on);
6178 DEFSUBR(Freplace_buffer_in_windows);
6179 DEFSUBR(Fdelete_window);
6180 DEFSUBR(Fset_window_buffer);
6181 DEFSUBR(Fselect_window);
6182 DEFSUBR(Fsplit_window);
6183 DEFSUBR(Fenlarge_window);
6184 DEFSUBR(Fenlarge_window_pixels);
6185 DEFSUBR(Fshrink_window);
6186 DEFSUBR(Fshrink_window_pixels);
6187 DEFSUBR(Fscroll_up);
6188 DEFSUBR(Fscroll_down);
6189 DEFSUBR(Fscroll_left);
6190 DEFSUBR(Fscroll_right);
6191 DEFSUBR(Fother_window_for_scrolling);
6192 DEFSUBR(Fscroll_other_window);
6193 DEFSUBR(Fcenter_to_window_line);
6194 DEFSUBR(Fmove_to_window_line);
6195 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6196 DEFSUBR(Fwindow_memory_usage);
6198 DEFSUBR(Fwindow_configuration_p);
6199 DEFSUBR(Fset_window_configuration);
6200 DEFSUBR(Fcurrent_window_configuration);
6201 DEFSUBR(Fsave_window_excursion);
6202 DEFSUBR(Fcurrent_pixel_column);
6205 void reinit_vars_of_window(void)
6207 /* Make sure all windows get marked */
6208 minibuf_window = Qnil;
6209 staticpro_nodump(&minibuf_window);
6211 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
6212 for (unsigned int i = 0;
6213 i < countof(Vwindow_configuration_free_list); i++) {
6214 Vwindow_configuration_free_list[i] =
6215 make_lcrecord_list(sizeof_window_config_for_n_windows(
6217 &lrecord_window_configuration);
6218 staticpro_nodump(&Vwindow_configuration_free_list[i]);
6224 void vars_of_window(void)
6226 reinit_vars_of_window();
6228 DEFVAR_BOOL("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6229 *Non-nil means to scroll if point lands on a line which is clipped.
6231 scroll_on_clipped_lines = 1;
6233 DEFVAR_LISP("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6234 See `temp-buffer-show-function'.
6236 Vtemp_buffer_show_hook = Qnil;
6238 DEFVAR_LISP("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6239 Non-nil means call as function to display a help buffer.
6240 The function is called with one argument, the buffer to be displayed.
6241 Used by `with-output-to-temp-buffer'.
6242 If this function is used, then it must do the entire job of showing
6243 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6244 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6246 Vtemp_buffer_show_function = Qnil;
6248 DEFVAR_LISP("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6249 Non-nil means it is the window that
6250 \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should
6253 Vminibuffer_scroll_window = Qnil;
6255 DEFVAR_LISP("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6256 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6258 Vother_window_scroll_buffer = Qnil;
6260 DEFVAR_LISP("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6261 *Number of pixels to scroll by per requested line.
6262 If nil then normal line scrolling occurs regardless of line height.
6263 If t then scrolling is done in increments equal to the height of the default face.
6265 Vwindow_pixel_scroll_increment = Qt;
6267 DEFVAR_LISP ("window-configuration-hook", &Vwindow_configuration_hook /*
6268 Function(s) to call when a frame's window configuration has changed.
6270 Please see (Info-goto-node "(lispref)Window Configuration Hook") where all the
6271 details are documented.
6274 Vwindow_configuration_hook = Qnil;
6277 DEFVAR_INT("next-screen-context-lines", &next_screen_context_lines /*
6278 *Number of lines of continuity when scrolling by screenfuls.
6280 next_screen_context_lines = 2;
6282 DEFVAR_INT("window-min-height", &window_min_height /*
6283 *Delete any window less than this tall (including its modeline).
6285 window_min_height = 4;
6287 DEFVAR_INT("window-min-width", &window_min_width /*
6288 *Delete any window less than this wide.
6290 window_min_width = 10;
6293 void specifier_vars_of_window(void)
6295 DEFVAR_SPECIFIER("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6296 *How thick to draw 3D shadows around modelines.
6297 If this is set to 0, modelines will be the traditional 2D. Sizes above
6298 10 will be accepted but the maximum thickness that will be drawn is 10.
6299 This is a specifier; use `set-specifier' to change it.
6301 Vmodeline_shadow_thickness = Fmake_specifier(Qinteger);
6302 /* The initial value for modeline-shadow-thickness is 2, but if the
6303 user removes all specifications we provide a fallback value of 0,
6304 which is probably what was expected. */
6305 set_specifier_fallback(Vmodeline_shadow_thickness,
6306 list1(Fcons(Qnil, Qzero)));
6307 Fadd_spec_to_specifier(Vmodeline_shadow_thickness, make_int(2),
6309 set_specifier_caching(Vmodeline_shadow_thickness,
6310 offsetof(struct window,
6311 modeline_shadow_thickness),
6312 modeline_shadow_thickness_changed, 0, 0, 0);
6314 DEFVAR_SPECIFIER("has-modeline-p", &Vhas_modeline_p /*
6315 *Whether the modeline should be displayed.
6316 This is a specifier; use `set-specifier' to change it.
6318 Vhas_modeline_p = Fmake_specifier(Qboolean);
6319 set_specifier_fallback(Vhas_modeline_p, list1(Fcons(Qnil, Qt)));
6320 set_specifier_caching(Vhas_modeline_p,
6321 offsetof(struct window, has_modeline_p),
6322 /* #### It's strange that we need a special
6323 flag to indicate that the shadow-thickness
6324 has changed, but not one to indicate that
6325 the modeline has been turned off or on. */
6326 some_window_value_changed, 0, 0, 0);
6328 DEFVAR_SPECIFIER("vertical-divider-always-visible-p", &Vvertical_divider_always_visible_p /*
6329 *Should SXEmacs always display vertical dividers between windows.
6331 When this is non-nil, vertical dividers are always shown, and are
6332 draggable. When it is nil, vertical dividers are shown only when
6333 there are no scrollbars in between windows, and are not draggable.
6335 This is a specifier; use `set-specifier' to change it.
6337 Vvertical_divider_always_visible_p = Fmake_specifier(Qboolean);
6338 set_specifier_fallback(Vvertical_divider_always_visible_p,
6339 list1(Fcons(Qnil, Qt)));
6340 set_specifier_caching(Vvertical_divider_always_visible_p,
6341 offsetof(struct window,
6342 vertical_divider_always_visible_p),
6343 vertical_divider_changed_in_window, 0, 0, 0);
6345 DEFVAR_SPECIFIER("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6346 *How thick to draw 3D shadows around vertical dividers.
6347 This is a specifier; use `set-specifier' to change it.
6349 Vvertical_divider_shadow_thickness = Fmake_specifier(Qinteger);
6350 set_specifier_fallback(Vvertical_divider_shadow_thickness,
6351 list1(Fcons(Qnil, Qzero)));
6352 Fadd_spec_to_specifier(Vvertical_divider_shadow_thickness, make_int(2),
6354 set_specifier_caching(Vvertical_divider_shadow_thickness,
6355 offsetof(struct window,
6356 vertical_divider_shadow_thickness),
6357 vertical_divider_changed_in_window, 0, 0, 0);
6358 DEFVAR_SPECIFIER("vertical-divider-line-width", &Vvertical_divider_line_width /*
6359 *The width of the vertical dividers, not including shadows.
6361 For TTY windows, divider line is always one character wide. When
6362 instance of this specifier is zero in a TTY window, no divider is
6363 drawn at all between windows. When non-zero, a one character wide
6364 divider is displayed.
6366 This is a specifier; use `set-specifier' to change it.
6369 Vvertical_divider_line_width = Fmake_specifier(Qnatnum);
6371 Lisp_Object fb = Qnil;
6373 fb = Fcons(Fcons(list1(Qtty), make_int(1)), fb);
6375 #ifdef HAVE_X_WINDOWS
6376 fb = Fcons(Fcons(list1(Qx), make_int(3)), fb);
6378 set_specifier_fallback(Vvertical_divider_line_width, fb);
6380 set_specifier_caching(Vvertical_divider_line_width,
6381 offsetof(struct window,
6382 vertical_divider_line_width),
6383 vertical_divider_changed_in_window, 0, 0, 0);
6385 DEFVAR_SPECIFIER("vertical-divider-spacing", &Vvertical_divider_spacing /*
6386 *How much space to leave around the vertical dividers.
6388 In TTY windows, spacing is always zero, and the value of this
6389 specifier is ignored.
6391 This is a specifier; use `set-specifier' to change it.
6393 Vvertical_divider_spacing = Fmake_specifier(Qnatnum);
6395 Lisp_Object fb = Qnil;
6397 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
6399 #ifdef HAVE_X_WINDOWS
6400 /* #### 3D dividers look great on MS Windows with spacing = 0.
6401 Should not the same value be the fallback under X? - kkm */
6402 fb = Fcons(Fcons(list1(Qx), make_int(2)), fb);
6404 set_specifier_fallback(Vvertical_divider_spacing, fb);
6406 set_specifier_caching(Vvertical_divider_spacing,
6407 offsetof(struct window, vertical_divider_spacing),
6408 vertical_divider_changed_in_window, 0, 0, 0);