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);
565 if (which == CURRENT_DISP)
566 return t->current_display_lines;
567 else if (which == DESIRED_DISP)
568 return t->desired_display_lines;
569 else if (which == CMOTION_DISP)
570 /* The CMOTION_DISP display lines are global. */
571 return cmotion_display_lines;
575 return 0; /* shut up compiler */
578 struct buffer *window_display_buffer(struct window *w)
580 struct window_mirror *t;
582 if (XFRAME(w->frame)->mirror_dirty)
583 update_frame_window_mirror(XFRAME(w->frame));
584 t = find_window_mirror(w);
591 void set_window_display_buffer(struct window *w, struct buffer *b)
593 struct window_mirror *t;
595 if (XFRAME(w->frame)->mirror_dirty)
596 update_frame_window_mirror(XFRAME(w->frame));
597 t = find_window_mirror(w);
604 /* Determining a window's position based solely on its pixel
605 positioning doesn't work. Instead, we do it the intelligent way,
606 by checking its positioning in the window hierarchy. */
607 int window_is_leftmost(struct window *w)
609 Lisp_Object parent, current_ancestor, window;
611 XSETWINDOW(window, w);
613 parent = XWINDOW(window)->parent;
614 current_ancestor = window;
616 while (!NILP(parent)) {
617 if (!NILP(XWINDOW(parent)->hchild) &&
618 !EQ(XWINDOW(parent)->hchild, current_ancestor))
621 current_ancestor = parent;
622 parent = XWINDOW(parent)->parent;
628 int window_is_rightmost(struct window *w)
630 Lisp_Object parent, current_ancestor, window;
632 XSETWINDOW(window, w);
634 parent = XWINDOW(window)->parent;
635 current_ancestor = window;
637 while (!NILP(parent)) {
638 if (!NILP(XWINDOW(parent)->hchild)
639 && !NILP(XWINDOW(current_ancestor)->next))
642 current_ancestor = parent;
643 parent = XWINDOW(parent)->parent;
649 static int window_full_width_p(struct window *w)
651 return window_is_leftmost(w) && window_is_rightmost(w);
654 int window_is_highest(struct window *w)
656 Lisp_Object parent, current_ancestor, window;
658 XSETWINDOW(window, w);
660 parent = XWINDOW(window)->parent;
661 current_ancestor = window;
663 while (!NILP(parent)) {
664 if (!NILP(XWINDOW(parent)->vchild) &&
665 !EQ(XWINDOW(parent)->vchild, current_ancestor))
668 current_ancestor = parent;
669 parent = XWINDOW(parent)->parent;
672 /* This is really to catch the minibuffer but we make it generic in
673 case we ever change things around to let the minibuffer be on top. */
674 if (NILP(XWINDOW(current_ancestor)->prev))
680 int window_is_lowest(struct window *w)
682 Lisp_Object parent, current_ancestor, window;
684 XSETWINDOW(window, w);
686 parent = XWINDOW(window)->parent;
687 current_ancestor = window;
689 while (!NILP(parent)) {
690 if (!NILP(XWINDOW(parent)->vchild)
691 && !NILP(XWINDOW(current_ancestor)->next))
694 current_ancestor = parent;
695 parent = XWINDOW(parent)->parent;
701 #if 0 /* not currently used */
703 static int window_full_height_p(struct window *w)
705 return window_is_highest(w) && window_is_lowest(w);
710 int window_truncation_on(struct window *w)
712 /* Minibuffer windows are never truncated.
713 #### is this the right way ? */
714 if (MINI_WINDOW_P(w))
717 /* Horizontally scrolled windows are truncated. */
721 /* If truncate_partial_width_windows is true and the window is not
722 the full width of the frame it is truncated. */
723 if (!NILP(symbol_value_in_buffer(Qtruncate_partial_width_windows,
725 && !(window_is_leftmost(w) && window_is_rightmost(w)))
728 /* If the window's buffer's value of truncate_lines is non-nil, then
729 the window is truncated. */
730 if (!NILP(XBUFFER(w->buffer)->truncate_lines))
736 DEFUN("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
737 Returns non-nil if text in the window is truncated.
741 struct window *w = decode_window(window);
743 return window_truncation_on(w) ? Qt : Qnil;
746 static int have_undivided_common_edge(struct window *w_right, void *closure)
748 struct window *w_left = (struct window *)closure;
749 return (WINDOW_RIGHT(w_left) == WINDOW_LEFT(w_right)
750 && WINDOW_TOP(w_left) < WINDOW_BOTTOM(w_right)
751 && WINDOW_TOP(w_right) < WINDOW_BOTTOM(w_left)
752 #ifdef HAVE_SCROLLBARS
753 && (NILP(w_right->scrollbar_on_left_p)
754 || NILP(w_right->vertical_scrollbar_visible_p)
755 || ZEROP(w_right->scrollbar_width))
760 static int window_needs_vertical_divider_1(struct window *w)
762 /* Never if we're on the right */
763 if (window_is_rightmost(w))
766 /* Always if draggable */
767 if (!NILP(w->vertical_divider_always_visible_p))
770 #ifdef HAVE_SCROLLBARS
771 /* Our right scrollbar is enough to separate us at the right */
772 if (NILP(w->scrollbar_on_left_p)
773 && !NILP(w->vertical_scrollbar_visible_p)
774 && !ZEROP(w->scrollbar_width))
778 /* Ok. to determine whether we need a divider on the left, we must
779 check that our right neighbor windows have scrollbars on their
780 left sides. We must check all such windows which have common
781 left edge with our window's right edge. */
782 return map_windows(XFRAME(WINDOW_FRAME(w)),
783 have_undivided_common_edge, (void *)w);
786 int window_needs_vertical_divider(struct window *w)
788 if (!w->need_vertical_divider_valid_p) {
789 w->need_vertical_divider_p = window_needs_vertical_divider_1(w);
790 w->need_vertical_divider_valid_p = 1;
792 return w->need_vertical_divider_p;
795 /* Called from invalidate_vertical_divider_cache_in_frame */
797 invalidate_vertical_divider_cache_in_window(struct window *w, void *u_n_u_s_e_d)
799 w->need_vertical_divider_valid_p = 0;
803 /* Calculate width of vertical divider, including its shadows
804 and spacing. The returned value is effectively the distance
805 between adjacent window edges. This function does not check
806 whether a window needs a vertical divider, so the returned
807 value is a "theoretical" one */
808 int window_divider_width(struct window *w)
810 /* the shadow thickness can be negative. This means that the divider
811 will have a depressed look */
813 if (FRAME_WIN_P(XFRAME(WINDOW_FRAME(w))))
814 return XINT(w->vertical_divider_line_width)
815 + 2 * XINT(w->vertical_divider_spacing)
816 + 2 * abs(XINT(w->vertical_divider_shadow_thickness));
818 return XINT(w->vertical_divider_line_width) == 0 ? 0 : 1;
821 int window_scrollbar_width(struct window *w)
823 #ifdef HAVE_SCROLLBARS
827 || NILP(w->vertical_scrollbar_visible_p))
828 /* #### when does NILP (w->buffer) happen? */
831 return XINT(w->scrollbar_width);
834 #endif /* HAVE_SCROLLBARS */
837 /* Horizontal scrollbars are only active on windows with truncation
839 int window_scrollbar_height(struct window *w)
841 #ifdef HAVE_SCROLLBARS
845 || NILP(w->horizontal_scrollbar_visible_p)
846 || !window_truncation_on(w))
849 return XINT(w->scrollbar_height);
852 #endif /* HAVE_SCROLLBARS */
855 int window_modeline_height(struct window *w)
857 struct frame *f = XFRAME(w->frame);
860 if (MINI_WINDOW_P(w) || NILP(w->buffer)) {
862 } else if (!WINDOW_HAS_MODELINE_P(w)) {
863 if (window_scrollbar_height(w))
866 modeline_height = FRAMEMETH(f, divider_height, ());
868 if (!EQ(Qzero, w->modeline_shadow_thickness)
871 (2 * MODELINE_SHADOW_THICKNESS(w));
877 display_line_dynarr *dla;
879 /* We don't force a regeneration of the modeline here.
880 Instead it is now a precondition that any function calling
881 this should make sure that one of these structures is
882 up-to-date. In practice this only affects two internal
883 redisplay functions, regenerate_window and
884 regenerate_window_point_center. */
885 /* We check DESIRED_DISP because if it is valid it is more
886 up-to-date than CURRENT_DISP. For calls to this outside
887 of redisplay it doesn't matter which structure we check
888 since there is a redisplay condition that these
889 structures be identical outside of redisplay. */
890 dla = window_display_lines(w, DESIRED_DISP);
891 if (dla && Dynarr_length(dla)
892 && Dynarr_atp(dla, 0)->modeline)
894 (Dynarr_atp(dla, 0)->ascent +
895 Dynarr_atp(dla, 0)->descent);
897 dla = window_display_lines(w, CURRENT_DISP);
898 if (dla && Dynarr_length(dla)
899 && Dynarr_atp(dla, 0)->modeline)
901 (Dynarr_atp(dla, 0)->ascent +
902 Dynarr_atp(dla, 0)->descent);
904 /* This should be an abort except I'm not yet 100%
905 confident that it won't ever get hit (though I
906 haven't been able to trigger it). It is extremely
907 unlikely to cause any noticeable problem and even if
908 it does it will be a minor display glitch. */
909 /* #### Bullshit alert. It does get hit and it causes
910 noticeable glitches. real_current_modeline_height
911 is a kludge to fix this for 19.14. */
913 real_current_modeline_height(w);
916 if (!EQ(Qzero, w->modeline_shadow_thickness)
919 (2 * MODELINE_SHADOW_THICKNESS(w));
923 return modeline_height;
926 /*****************************************************************************
927 margin_width_internal
929 For a given window, return the width in pixels of the specified margin.
930 ****************************************************************************/
931 static int margin_width_internal(struct window *w, int left_margin)
933 int window_cwidth = window_char_width(w, 1);
938 /* We might be getting called on a non-leaf. */
942 /* The minibuffer never has margins. */
943 if (MINI_WINDOW_P(w))
946 XSETWINDOW(window, w);
947 (void)XBUFFER(w->buffer);
948 margin_cwidth = (left_margin ? XINT(w->left_margin_width) :
949 XINT(w->right_margin_width));
951 default_face_height_and_width(window, 0, &font_width);
953 /* The left margin takes precedence over the right margin so we
954 subtract its width from the space available for the right
957 window_cwidth -= XINT(w->left_margin_width);
959 /* The margin cannot be wider than the window is. We allow the
960 value to be bigger since it is possible for the user to enlarge
961 the window such that the left margin value would no longer be too
962 big, but we won't return a value that is larger. */
963 if (margin_cwidth > window_cwidth)
964 margin_cwidth = window_cwidth;
966 /* At the user level the margin is always specified in characters.
967 Internally however it is manipulated in terms of pixels. */
968 return margin_cwidth * font_width;
971 int window_left_margin_width(struct window *w)
973 return margin_width_internal(w, 1);
976 int window_right_margin_width(struct window *w)
978 return margin_width_internal(w, 0);
981 /*****************************************************************************
984 The gutters of a window are those areas in the boundary defined by
985 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
986 do not contain text. Items which may be in the gutters include
987 scrollbars, toolbars and modelines. The margin areas are not
988 included. This is an exception made because redisplay special cases
989 the handling of those areas in many places in such a way that
990 including them in the gutter area would make life difficult.
992 The size functions refer to height for the bottom and top gutters and
993 width for the left and right gutters. The starting position
994 functions refer to the Y coord for bottom and top gutters and the X
995 coord for left and right gutters. All starting positions are
996 relative to the frame, not the window.
997 ****************************************************************************/
999 static int window_top_window_gutter_height(struct window *w)
1001 if (!NILP(w->hchild) || !NILP(w->vchild))
1004 #ifdef HAVE_SCROLLBARS
1005 if (!NILP(w->scrollbar_on_top_p))
1006 return window_scrollbar_height(w);
1012 int window_top_gutter_height(struct window *w)
1014 return window_top_window_gutter_height(w);
1017 static int window_bottom_window_gutter_height(struct window *w)
1021 if (!NILP(w->hchild) || !NILP(w->vchild))
1024 gutter = window_modeline_height(w);
1026 #ifdef HAVE_SCROLLBARS
1027 if (NILP(w->scrollbar_on_top_p))
1028 return window_scrollbar_height(w) + gutter;
1034 int window_bottom_gutter_height(struct window *w)
1036 return window_bottom_window_gutter_height(w);
1039 static int window_left_window_gutter_width(struct window *w, int modeline)
1041 if (!NILP(w->hchild) || !NILP(w->vchild))
1044 #ifdef HAVE_SCROLLBARS
1045 if (!modeline && !NILP(w->scrollbar_on_left_p))
1046 return window_scrollbar_width(w);
1052 int window_left_gutter_width(struct window *w, int modeline)
1054 return window_left_window_gutter_width(w, modeline);
1057 static int window_right_window_gutter_width(struct window *w, int modeline)
1061 if (!NILP(w->hchild) || !NILP(w->vchild))
1064 #ifdef HAVE_SCROLLBARS
1065 if (!modeline && NILP(w->scrollbar_on_left_p))
1066 gutter += window_scrollbar_width(w);
1069 if (window_needs_vertical_divider(w))
1070 gutter += window_divider_width(w);
1075 int window_right_gutter_width(struct window *w, int modeline)
1077 return window_right_window_gutter_width(w, modeline);
1080 static int window_pixel_height(struct window *w)
1082 return WINDOW_HEIGHT(w);
1085 DEFUN("windowp", Fwindowp, 1, 1, 0, /*
1086 Return t if OBJECT is a window.
1090 return WINDOWP(object) ? Qt : Qnil;
1093 DEFUN("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1094 Return t if OBJECT is a window which is currently visible.
1098 return WINDOWP(object) && WINDOW_LIVE_P(XWINDOW(object))
1102 DEFUN("selected-window", Fselected_window, 0, 1, 0, /*
1103 Return the window that the cursor now appears in and commands apply
1104 to. If the optional argument CON-DEV-OR-FRAME is specified and is a
1105 frame, return the selected window used by that frame. If
1106 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1107 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1108 that console's selected device will be used. Otherwise, the selected
1113 if (NILP(con_dev_or_frame) && NILP(Fselected_device(Qnil)))
1114 return Qnil; /* happens at startup */
1117 struct frame *f = decode_frame_or_selected(con_dev_or_frame);
1118 return FRAME_SELECTED_WINDOW(f);
1122 DEFUN("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1123 Return the last selected window that is not a minibuffer window.
1124 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1125 return the last non-minibuffer window used by that frame. If
1126 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1127 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1128 that console's selected device will be used. Otherwise, the selected
1133 if (NILP(con_dev_or_frame) && NILP(Fselected_device(Qnil)))
1134 return Qnil; /* happens at startup */
1137 struct frame *f = decode_frame_or_selected(con_dev_or_frame);
1138 return FRAME_LAST_NONMINIBUF_WINDOW(f);
1142 DEFUN("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1143 Return the window used now for minibuffers.
1144 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1145 return the minibuffer window used by that frame. If CON-DEV-OR-FRAME
1146 is a device, then the selected frame on that device will be used. If
1147 CON-DEV-OR-FRAME is a console, the selected frame on that console's
1148 selected device will be used. Otherwise, the selected frame is used.
1152 return FRAME_MINIBUF_WINDOW(decode_frame_or_selected(con_dev_or_frame));
1155 DEFUN("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1156 Return non-nil if WINDOW is a minibuffer window.
1160 return MINI_WINDOW_P(decode_window(window)) ? Qt : Qnil;
1163 DEFUN("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1164 Return the first horizontal child of WINDOW, or nil.
1168 return decode_window(window)->hchild;
1171 DEFUN("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1172 Return the first vertical child of WINDOW, or nil.
1176 return decode_window(window)->vchild;
1179 DEFUN("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1180 Return the next window on the same level as WINDOW, or nil.
1184 return decode_window(window)->next;
1187 DEFUN("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1188 Return the previous window on the same level as WINDOW, or nil.
1192 return decode_window(window)->prev;
1195 DEFUN("window-parent", Fwindow_parent, 1, 1, 0, /*
1196 Return the parent of WINDOW, or nil.
1200 return decode_window(window)->parent;
1203 DEFUN("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1204 Return non-nil if WINDOW is along the bottom of its frame.
1208 return window_is_lowest(decode_window(window)) ? Qt : Qnil;
1211 DEFUN("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1212 Return non-nil if WINDOW is along the top of its frame.
1216 return window_is_highest(decode_window(window)) ? Qt : Qnil;
1219 DEFUN("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1220 Return non-nil if WINDOW is along the left edge of its frame.
1224 return window_is_leftmost(decode_window(window)) ? Qt : Qnil;
1227 DEFUN("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1228 Return non-nil if WINDOW is along the right edge of its frame.
1232 return window_is_rightmost(decode_window(window)) ? Qt : Qnil;
1235 DEFUN("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1236 Return t if position POS is currently on the frame in WINDOW.
1237 Returns nil if that position is scrolled vertically out of view. POS
1238 defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1242 struct window *w = decode_window(window);
1243 Bufpos top = marker_position(w->start[CURRENT_DISP]);
1245 struct buffer *buf = XBUFFER(w->buffer);
1248 posint = BUF_PT(buf);
1250 CHECK_INT_COERCE_MARKER(pos);
1254 if (posint < top || posint > BUF_ZV(buf))
1257 /* w->start can be out of range. If it is, do something reasonable. */
1258 if (top < BUF_BEGV(buf) || top > BUF_ZV(buf))
1261 return point_would_be_visible(w, top, posint) ? Qt : Qnil;
1264 struct window *decode_window(Lisp_Object window)
1267 Lisp_Object tmp = Fselected_window(Qnil);
1268 return XWINDOW(tmp);
1270 CHECK_LIVE_WINDOW(window);
1271 return XWINDOW(window);
1274 DEFUN("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1275 Return the buffer that WINDOW is displaying.
1279 return decode_window(window)->buffer;
1282 DEFUN("window-frame", Fwindow_frame, 0, 1, 0, /*
1283 Return the frame that window WINDOW is on.
1287 return decode_window(window)->frame;
1290 DEFUN("window-height", Fwindow_height, 0, 1, 0, /*
1291 Return the number of default lines in WINDOW.
1292 This actually works by dividing the window's pixel height (including
1293 the modeline and horizontal scrollbar, if any) by the height of the
1294 default font; therefore, the number of displayed lines will probably
1297 Use `window-height' to get consistent results in geometry calculations.
1298 Use `window-displayed-height' to get the actual number of lines
1299 currently displayed in a window.
1301 The names are somewhat confusing; here's a table to help out:
1304 ---------------------------------------------------------------------
1306 (rows/columns) window-width window-text-area-height
1307 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1310 (rows/columns) window-full-width window-height
1311 (pixels) window-pixel-width window-pixel-height
1314 (rows/columns) ---- window-displayed-height
1315 (pixels) ---- window-displayed-text-pixel-height
1319 return make_int(window_char_height(decode_window(window), 1));
1322 DEFUN("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1323 Return the number of lines currently displayed in WINDOW.
1324 This counts the actual number of lines displayed in WINDOW
1325 \(as opposed to `window-height'). The modeline and horizontal
1326 scrollbar do not count as lines. If there is some blank space
1327 between the end of the buffer and the end of the window, this
1328 function pretends that there are lines of text in the default
1333 return make_int(window_displayed_height(decode_window(window)));
1336 DEFUN("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1337 Return the height of WINDOW in pixels. Defaults to current window.
1338 This includes the window's modeline and horizontal scrollbar (if any).
1342 return make_int(window_pixel_height(decode_window(window)));
1345 DEFUN("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1346 Return the number of default lines in the text area of WINDOW.
1347 This actually works by dividing the window's text area pixel height
1348 (i.e. excluding the modeline and horizontal scrollbar, if any) by the
1349 height of the default font; therefore, the number of displayed lines
1350 will probably be different.
1352 See also `window-height' and `window-displayed-height'.
1356 return make_int(window_char_height(decode_window(window), 0));
1359 DEFUN("window-text-area-pixel-height", Fwindow_text_area_pixel_height, 0, 1, 0, /*
1360 Return the height in pixels of the text-displaying portion of WINDOW.
1361 Unlike `window-pixel-height', the space occupied by the modeline and
1362 horizontal scrollbar, if any, is not counted.
1366 struct window *w = decode_window(window);
1368 return make_int(WINDOW_TEXT_HEIGHT(w));
1371 DEFUN("window-displayed-text-pixel-height", Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1372 Return the height in pixels of the text displayed in WINDOW.
1373 Unlike `window-text-area-pixel-height', any blank space below the
1374 end of the buffer is not included. If optional argument NOCLIPPED
1375 is non-nil, do not include space occupied by clipped lines.
1377 (window, noclipped))
1380 Bufpos start, eobuf;
1382 int hlimit, height, prev_height = -1;
1386 line_start_cache_dynarr *cache;
1389 window = Fselected_window(Qnil);
1391 CHECK_LIVE_WINDOW(window);
1392 w = XWINDOW(window);
1394 start = marker_position(w->start[CURRENT_DISP]);
1395 hlimit = WINDOW_TEXT_HEIGHT(w);
1396 eobuf = BUF_ZV(XBUFFER(w->buffer));
1398 default_face_height_and_width(window, &defheight, NULL);
1400 /* guess lines needed in line start cache + a few extra */
1401 needed = (hlimit + defheight - 1) / defheight + 3;
1404 elt = point_in_line_start_cache(w, start, needed);
1405 assert(elt >= 0); /* in the cache */
1407 cache = w->line_start_cache;
1408 nelt = Dynarr_length(cache);
1411 for (i = elt; i < nelt; i++) {
1412 line = Dynarr_atp(cache, i)->height;
1414 if (height + line > hlimit)
1415 return make_int(!NILP(noclipped) ? height :
1420 if (height == hlimit
1421 || Dynarr_atp(cache, i)->end >= eobuf)
1422 return make_int(height);
1425 /* get here => need more cache lines. try again. */
1426 assert(height > prev_height); /* progress? */
1427 prev_height = height;
1430 ((hlimit - height) * (nelt - elt) + height - 1) / height +
1434 RETURN_NOT_REACHED(make_int(0)) /* shut up compiler */
1437 DEFUN("window-width", Fwindow_width, 0, 1, 0, /*
1438 Return the number of display columns in WINDOW.
1439 This is the width that is usable columns available for text in WINDOW,
1440 and does not include vertical scrollbars, dividers, or the like. See also
1441 `window-full-width' and `window-height'.
1445 return make_int(window_char_width(decode_window(window), 0));
1448 DEFUN("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1449 Return the total number of columns in WINDOW.
1450 This is like `window-width' but includes vertical scrollbars, dividers,
1455 return make_int(window_char_width(decode_window(window), 1));
1458 DEFUN("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1459 Return the width of WINDOW in pixels. Defaults to current window.
1463 return make_int(decode_window(window)->pixel_width);
1466 DEFUN("window-text-area-pixel-width", Fwindow_text_area_pixel_width, 0, 1, 0, /*
1467 Return the width in pixels of the text-displaying portion of WINDOW.
1468 Unlike `window-pixel-width', the space occupied by the vertical
1469 scrollbar or divider, if any, is not counted.
1473 struct window *w = decode_window(window);
1475 return make_int(WINDOW_TEXT_WIDTH(w));
1478 DEFUN("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1479 Return the number of columns by which WINDOW is scrolled from left margin.
1483 return make_int(decode_window(window)->hscroll);
1486 DEFUN("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1487 Return the horizontal scrolling amount of WINDOW's modeline.
1488 If the window has no modeline, return nil.
1492 struct window *w = decode_window(window);
1494 return (WINDOW_HAS_MODELINE_P(w)) ? make_int((int)w->modeline_hscroll) :
1498 DEFUN("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1499 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1500 If NCOL is negative, it will silently be forced to 0.
1501 If the window has no modeline, return nil. Otherwise, return the actual
1506 struct window *w = decode_window(window);
1508 if (WINDOW_HAS_MODELINE_P(w)) {
1512 ncols = (XINT(ncol) <= 0) ? 0 : (Charcount) XINT(ncol);
1513 if (ncols != w->modeline_hscroll) {
1514 MARK_MODELINE_CHANGED;
1515 w->modeline_hscroll = ncols;
1517 return make_int((int)ncols);
1523 DEFUN("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1524 Set number of columns WINDOW is scrolled from left margin to NCOL.
1525 NCOL should be zero or positive.
1536 w = decode_window(window);
1537 if (w->hscroll != ncols)
1538 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1543 #if 0 /* bogus FSF crock */
1545 xxDEFUN("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1546 Return WINDOW's redisplay end trigger value.
1547 See `set-window-redisplay-end-trigger' for more information.
1551 return decode_window(window)->redisplay_end_trigger;
1554 xxDEFUN("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1555 Set WINDOW's redisplay end trigger value to VALUE.
1556 VALUE should be a buffer position (typically a marker) or nil.
1557 If it is a buffer position, then if redisplay in WINDOW reaches a position
1558 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1559 with two arguments: WINDOW, and the end trigger value.
1560 Afterwards the end-trigger value is reset to nil.
1564 return (decode_window(window)->redisplay_end_trigger = value);
1569 DEFUN("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1570 Return a list of the pixel edge coordinates of WINDOW.
1571 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1572 all relative to 0, 0 at the top left corner of WINDOW's frame.
1573 The frame toolbars, menubars and gutters are considered to be outside
1574 of this area, while the scrollbars are considered to be inside.
1578 struct window *w = decode_window(window);
1579 struct frame *f = XFRAME(w->frame);
1582 w->pixel_left - FRAME_LEFT_BORDER_END(f) -
1583 FRAME_LEFT_GUTTER_BOUNDS(f);
1585 w->pixel_top - FRAME_TOP_BORDER_END(f) - FRAME_TOP_GUTTER_BOUNDS(f);
1587 return list4(make_int(left),
1589 make_int(left + w->pixel_width),
1590 make_int(top + w->pixel_height));
1593 DEFUN("window-text-area-pixel-edges", Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1594 Return a list of the pixel edge coordinates of the text area of WINDOW.
1595 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1596 all relative to 0, 0 at the top left corner of the total area allocated
1597 to the window, which includes the scrollbars.
1601 struct window *w = decode_window(window);
1603 int left = window_left_gutter_width(w, /* modeline = */ 0);
1604 int top = window_top_gutter_height(w);
1605 int right = WINDOW_WIDTH(w) - window_right_gutter_width(w, 0);
1606 int bottom = WINDOW_HEIGHT(w) - window_bottom_gutter_height(w);
1608 return list4(make_int(left),
1609 make_int(top), make_int(right), make_int(bottom));
1612 DEFUN("window-point", Fwindow_point, 0, 1, 0, /*
1613 Return current value of point in WINDOW.
1614 For a non-selected window, this is the value point would have
1615 if that window were selected.
1617 Note that, when WINDOW is the selected window and its buffer
1618 is also currently selected, the value returned is the same as (point).
1619 It would be more strictly correct to return the `top-level' value
1620 of point, outside of any save-excursion forms.
1621 But that value is hard to find.
1625 struct window *w = decode_window(window);
1626 Lisp_Object tmp_win = Fselected_window(XFRAME(w->frame)->device);
1628 /* The special check for current buffer is necessary for this
1629 function to work as defined when called within an excursion. */
1630 if (w == XWINDOW(tmp_win)
1631 && current_buffer == XBUFFER(w->buffer)) {
1632 return Fpoint(Qnil);
1634 return Fmarker_position(w->pointm[CURRENT_DISP]);
1637 DEFUN("window-start", Fwindow_start, 0, 1, 0, /*
1638 Return position at which display currently starts in WINDOW.
1639 This is updated by redisplay or by calling `set-window-start'.
1643 return Fmarker_position(decode_window(window)->start[CURRENT_DISP]);
1646 DEFUN("window-end", Fwindow_end, 0, 2, 0, /*
1647 Return position at which display currently ends in WINDOW.
1648 This is updated by redisplay, when it runs to completion.
1649 Simply changing the buffer text or setting `window-start' does not
1650 update this value. WINDOW defaults to the selected window.
1652 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1653 to be the same value as this function would return at the end of the
1654 next full redisplay assuming nothing else changes in the meantime.
1655 This function is potentially much slower with this flag set.
1657 (window, guarantee))
1659 struct window *w = decode_window(window);
1661 if (NILP(guarantee)) {
1665 return make_int(BUF_Z(XBUFFER(buf)) -
1666 w->window_end_pos[CURRENT_DISP]);
1668 Bufpos startp = marker_position(w->start[CURRENT_DISP]);
1669 return make_int(end_of_last_line(w, startp));
1673 DEFUN("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1674 Return pixel height of visible part of last window line if it is clipped.
1675 If the last line is not clipped, return nil.
1679 struct window *w = decode_window(window);
1680 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
1681 int num_lines = Dynarr_length(dla);
1682 struct display_line *dl;
1684 /* No lines - no clipped lines */
1685 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp(dla, 0)->modeline))
1688 dl = Dynarr_atp(dla, num_lines - 1);
1692 return make_int(dl->ascent + dl->descent - dl->clip);
1695 DEFUN("set-window-point", Fset_window_point, 2, 2, 0, /*
1696 Make point value in WINDOW be at position POS in WINDOW's buffer.
1700 struct window *w = decode_window(window);
1701 Lisp_Object tmp_win;
1703 CHECK_INT_COERCE_MARKER(pos);
1705 tmp_win = Fselected_window(Qnil);
1706 if (w == XWINDOW(tmp_win)) {
1707 Fgoto_char(pos, Qnil);
1709 set_marker_restricted(w->pointm[CURRENT_DISP], pos, w->buffer);
1715 DEFUN("set-window-start", Fset_window_start, 2, 3, 0, /*
1716 Make display in WINDOW start at position POS in WINDOW's buffer.
1717 Optional third arg NOFORCE non-nil inhibits next redisplay
1718 from overriding motion of point in order to display at this exact start.
1720 (window, pos, noforce))
1722 struct window *w = decode_window(window);
1724 CHECK_INT_COERCE_MARKER(pos);
1725 set_marker_restricted(w->start[CURRENT_DISP], pos, w->buffer);
1726 /* this is not right, but much easier than doing what is right. */
1727 /* w->start_at_line_beg = 0; */
1728 /* WTF is the above supposed to mean? GE */
1729 w->start_at_line_beg = beginning_of_line_p(XBUFFER(w->buffer),
1735 w->redo_modeline = 1;
1736 SET_LAST_MODIFIED(w, 0);
1737 SET_LAST_FACECHANGE(w);
1739 MARK_WINDOWS_CHANGED(w);
1744 DEFUN("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1745 Return WINDOW's dedicated object, usually t or nil.
1746 See also `set-window-dedicated-p'.
1750 return decode_window(window)->dedicated;
1753 DEFUN("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1754 Control whether WINDOW is dedicated to the buffer it displays.
1755 If it is dedicated, Emacs will not automatically change
1756 which buffer appears in it.
1757 The second argument is the new value for the dedication flag;
1762 struct window *w = decode_window(window);
1764 w->dedicated = NILP(arg) ? Qnil : Qt;
1766 return w->dedicated;
1769 /* FSFmacs has window-display-table here. We have display table as a
1772 /* Record info on buffer window w is displaying
1773 when it is about to cease to display that buffer. */
1774 static void unshow_buffer(struct window *w)
1776 Lisp_Object buf = w->buffer;
1778 if (XBUFFER(buf) != XMARKER(w->pointm[CURRENT_DISP])->buffer)
1781 /* FSF disables this check, so I'll do it too. I hope it won't
1782 break things. --ben */
1784 if (w == XWINDOW(Fselected_window(Qnil))
1785 || !EQ(buf, XWINDOW(Fselected_window(Qnil))->buffer))
1786 /* Do this except when the selected window's buffer
1787 is being removed from some other window. */
1789 /* last_window_start records the start position that this buffer
1790 had in the last window to be disconnected from it. Now that
1791 this statement is unconditional, it is possible for the
1792 buffer to be displayed in the selected window, while
1793 last_window_start reflects another window which was recently
1794 showing the same buffer. Some people might say that might be
1795 a good thing. Let's see. */
1796 XBUFFER(buf)->last_window_start =
1797 marker_position(w->start[CURRENT_DISP]);
1799 /* Point in the selected window's buffer is actually stored in that
1800 buffer, and the window's pointm isn't used. So don't clobber point
1803 Lisp_Object tmp = Fselected_window(Qnil);
1804 if (!EQ(buf, XWINDOW(tmp)->buffer)) {
1805 struct buffer *b = XBUFFER(buf);
1806 BUF_SET_PT(b, bufpos_clip_to_bounds(
1809 w->pointm[CURRENT_DISP]),
1815 /* Put REPLACEMENT into the window structure in place of OLD. */
1816 static void replace_window(Lisp_Object old, Lisp_Object replacement)
1819 struct window *o = XWINDOW(old), *p = XWINDOW(replacement);
1821 /* If OLD is its frame's root_window, then replacement is the new
1822 root_window for that frame. */
1824 if (EQ(old, FRAME_ROOT_WINDOW(XFRAME(o->frame))))
1825 FRAME_ROOT_WINDOW(XFRAME(o->frame)) = replacement;
1827 WINDOW_LEFT(p) = WINDOW_LEFT(o);
1828 WINDOW_TOP(p) = WINDOW_TOP(o);
1829 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
1830 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
1832 p->next = tem = o->next;
1834 XWINDOW(tem)->prev = replacement;
1836 p->prev = tem = o->prev;
1838 XWINDOW(tem)->next = replacement;
1840 p->parent = tem = o->parent;
1842 if (EQ(XWINDOW(tem)->vchild, old))
1843 XWINDOW(tem)->vchild = replacement;
1844 if (EQ(XWINDOW(tem)->hchild, old))
1845 XWINDOW(tem)->hchild = replacement;
1848 /* #### Here, if replacement is a vertical combination
1849 and so is its new parent, we should make replacement's
1850 children be children of that parent instead. */
1852 ERROR_CHECK_SUBWINDOW_CACHE(p);
1855 static void window_unmap_subwindows(struct window *w)
1857 assert(!NILP(w->subwindow_instance_cache));
1858 elisp_maphash(unmap_subwindow_instance_cache_mapper,
1859 w->subwindow_instance_cache, (void *)1);
1862 /* we're deleting W; set the structure of W to indicate this. */
1864 static void mark_window_as_deleted(struct window *w)
1866 /* The window instance cache is going away now, so need to get the
1867 cachels reset by redisplay. */
1868 MARK_FRAME_SUBWINDOWS_CHANGED(XFRAME(WINDOW_FRAME(w)));
1870 /* The cache is going away. If we leave unmapping to
1871 reset_subwindow_cachels then we get in a situation where the
1872 domain (the window) has been deleted but we still need access to
1873 its attributes in order to unmap windows properly. Since the
1874 subwindows are going to get GC'd anyway as a result of the domain
1875 going away, it is safer to just unmap them all while we know the
1876 domain is still valid. */
1877 ERROR_CHECK_SUBWINDOW_CACHE(w);
1878 window_unmap_subwindows(w);
1881 (while t (split-window) (delete-window))
1882 we end up with a tree of deleted windows which are all connected
1883 through the `next' slot. This might not seem so bad, as they're
1884 deleted, and will presumably be GCed - but if even *one* of those
1885 windows is still being pointed to, by the user, or by a window
1886 configuration, then *all* of those windows stick around.
1888 Since the window-configuration code doesn't need any of the
1889 pointers to other windows (they are all recreated from the
1890 window-config data), we set them all to nil so that we
1891 are able to collect more actual garbage. */
1897 w->subwindow_instance_cache = Qnil;
1901 /* Free the extra data structures attached to windows immediately so
1902 they don't sit around consuming excess space. They will be
1903 reinitialized by the window-configuration code as necessary. */
1904 finalize_window((void *)w, 0);
1907 DEFUN("delete-window", Fdelete_window, 0, 2, "", /*
1908 Remove WINDOW from the display. Default is selected window.
1909 If window is the only one on its frame, the frame is deleted as well.
1910 Normally, you cannot delete the last non-minibuffer-only frame (you
1911 must use `save-buffers-kill-emacs' or `kill-emacs'). However, if
1912 optional second argument FORCE is non-nil, you can delete the last
1913 frame. (This will automatically call `save-buffers-kill-emacs'.)
1918 /* This function can GC if this is the only window in the frame */
1926 /* Note: this function is called by other C code on non-leaf
1929 /* Do the equivalent of decode_window() but don't error out on
1930 deleted window; it's OK to delete an already-deleted window. */
1932 window = Fselected_window(Qnil);
1934 CHECK_WINDOW(window);
1936 w = XWINDOW(window);
1938 /* It's okay to delete an already-deleted window. */
1939 if (!WINDOW_LIVE_P(w))
1942 frame = WINDOW_FRAME(w);
1944 d = XDEVICE(FRAME_DEVICE(f));
1946 if (TOP_LEVEL_WINDOW_P(w)) {
1947 if (NILP(memq_no_quit(frame, DEVICE_FRAME_LIST(d))))
1948 /* this frame isn't fully initialized yet; don't blow up. */
1951 if (MINI_WINDOW_P(XWINDOW(window)))
1952 error("Attempt to delete the minibuffer window");
1954 /* It has been suggested that it's a good thing for C-x 0 to have this
1955 behavior, but not such a good idea for #'delete-window to have it.
1956 Maybe C-x 0 should be bound to something else, or maybe frame
1957 deletion should only happen when this is called interactively.
1959 delete_frame_internal(f, !NILP(force), 0, 0);
1963 /* At this point, we know the window has a parent. */
1965 par = XWINDOW(parent);
1967 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1968 /* It's quite likely that deleting a window will result in
1969 subwindows needing to be deleted also (since they are cached
1970 per-window). So we mark them as changed, so that the cachels will
1971 get reset by redisplay and thus deleted subwindows can get
1973 MARK_FRAME_SUBWINDOWS_CHANGED(f);
1975 /* Are we trying to delete any frame's selected window?
1976 Note that we could be dealing with a non-leaf window
1977 where the selected window is one of our children.
1978 So, we check by scanning all the ancestors of the
1979 frame's selected window and comparing each one with
1982 Lisp_Object pwindow;
1984 pwindow = FRAME_SELECTED_WINDOW(f);
1986 while (!NILP(pwindow)) {
1987 if (EQ(window, pwindow))
1989 pwindow = XWINDOW(pwindow)->parent;
1992 if (EQ(window, pwindow)) {
1993 /* OK, we found it. */
1994 Lisp_Object alternative;
1995 alternative = Fnext_window(window, Qlambda, Qnil, Qnil);
1997 /* If we're about to delete the selected window on the
1998 selected frame, then we should use Fselect_window to select
1999 the new window. On the other hand, if we're about to
2000 delete the selected window on any other frame, we shouldn't do
2001 anything but set the frame's selected_window slot. */
2002 if (EQ(frame, Fselected_frame(Qnil)))
2003 Fselect_window(alternative, Qnil);
2005 set_frame_selected_window(f, alternative);
2009 /* w->buffer is nil in a non-leaf window; in this case,
2010 get rid of the markers we maintain that point into that buffer. */
2011 if (!NILP(w->buffer)) {
2013 unchain_marker(w->pointm[CURRENT_DISP]);
2014 unchain_marker(w->pointm[DESIRED_DISP]);
2015 unchain_marker(w->pointm[CMOTION_DISP]);
2016 unchain_marker(w->start[CURRENT_DISP]);
2017 unchain_marker(w->start[DESIRED_DISP]);
2018 unchain_marker(w->start[CMOTION_DISP]);
2019 unchain_marker(w->sb_point);
2020 /* This breaks set-window-configuration if windows in the saved
2021 configuration get deleted and multiple frames are in use. */
2022 /* w->buffer = Qnil; */
2025 /* close up the hole in the sibling list */
2027 XWINDOW(w->next)->prev = w->prev;
2029 XWINDOW(w->prev)->next = w->next;
2030 if (EQ(window, par->hchild))
2031 par->hchild = w->next;
2032 if (EQ(window, par->vchild))
2033 par->vchild = w->next;
2035 /* Find one of our siblings to give our space to. */
2037 Lisp_Object sib = w->prev;
2039 /* If w gives its space to its next sibling, that sibling needs
2040 to have its top/left side pulled back to where w's is.
2041 set_window_{height,width} will re-position the sibling's
2044 WINDOW_TOP(XWINDOW(sib)) = WINDOW_TOP(w);
2045 WINDOW_LEFT(XWINDOW(sib)) = WINDOW_LEFT(w);
2048 /* Stretch that sibling. */
2049 if (!NILP(par->vchild))
2050 set_window_pixheight
2052 (WINDOW_HEIGHT(XWINDOW(sib)) + WINDOW_HEIGHT(w)),
2054 if (!NILP(par->hchild))
2057 (WINDOW_WIDTH(XWINDOW(sib)) + WINDOW_WIDTH(w)), 1);
2060 run_window_configuration_hook( sib );
2064 /* If parent now has only one child,
2065 put the child into the parent's place. */
2067 Lisp_Object parchild = par->hchild;
2069 parchild = par->vchild;
2070 if (NILP(XWINDOW(parchild)->next)) {
2071 replace_window(parent, parchild);
2072 mark_window_as_deleted(XWINDOW(parent));
2076 /* Since we may be deleting combination windows, we must make sure that
2077 not only W but all its children have been marked as deleted. */
2078 if (!NILP(w->hchild))
2079 delete_all_subwindows(XWINDOW(w->hchild));
2080 else if (!NILP(w->vchild))
2081 delete_all_subwindows(XWINDOW(w->vchild));
2083 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and
2084 therefore redisplay, so it requires the mirror structure to be
2085 correct. We must dirty the mirror before it is called. */
2086 f->mirror_dirty = 1;
2088 mark_window_as_deleted(w);
2093 DEFUN("next-window", Fnext_window, 0, 4, 0, /*
2094 Return the next window after WINDOW in the canonical ordering of windows.
2095 If omitted, WINDOW defaults to the selected window.
2097 Optional second arg MINIBUF t means count the minibuffer window even
2098 if not active. MINIBUF nil or omitted means count the minibuffer iff
2099 it is active. MINIBUF neither t nor nil means not to count the
2100 minibuffer even if it is active.
2102 Several frames may share a single minibuffer; if the minibuffer
2103 counts, all windows on all frames that share that minibuffer count
2104 too. Therefore, `next-window' can be used to iterate through the
2105 set of windows even when the minibuffer is on another frame. If the
2106 minibuffer does not count, only windows from WINDOW's frame count.
2108 By default, only the windows in the selected frame are considered.
2109 The optional argument WHICH-FRAMES changes this behavior:
2110 WHICH-FRAMES = `visible' means search windows on all visible frames.
2111 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2112 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2113 WHICH-FRAMES = a frame means search only windows on that frame.
2114 Anything else means restrict to the selected frame.
2116 The optional fourth argument WHICH-DEVICES further clarifies on which
2117 devices to search for frames as specified by WHICH-FRAMES. This value
2118 is only meaningful if WHICH-FRAMES is non-nil.
2119 If nil or omitted, search all devices on the selected console.
2120 If a device, only search that device.
2121 If a console, search all devices on that console.
2122 If a device type, search all devices of that type.
2123 If `window-system', search all window-system devices.
2124 Any other non-nil value means search all devices.
2126 If you use consistent values for MINIBUF, WHICH-FRAMES, and
2127 WHICH-DEVICES, you can use `next-window' to iterate through the entire
2128 cycle of acceptable windows, eventually ending up back at the window
2129 you started with. `previous-window' traverses the same cycle, in the
2132 (window, minibuf, which_frames, which_devices))
2135 Lisp_Object start_window;
2138 window = Fselected_window(Qnil);
2140 CHECK_LIVE_WINDOW(window);
2142 start_window = window;
2144 /* minibuf == nil may or may not include minibuffers.
2145 Decide if it does. */
2147 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2148 else if (!EQ(minibuf, Qt))
2150 /* Now `minibuf' is one of:
2151 t => count all minibuffer windows
2152 lambda => count none of them
2153 or a specific minibuffer window (the active one) to count. */
2155 /* which_frames == nil doesn't specify which frames to include. */
2156 if (NILP(which_frames))
2157 which_frames = (!EQ(minibuf, Qlambda)
2158 ? (FRAME_MINIBUF_WINDOW
2159 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2161 else if (EQ(which_frames, Qvisible)) ;
2162 else if (ZEROP(which_frames)) ;
2163 else if (FRAMEP(which_frames)
2164 && !EQ(which_frames, Fwindow_frame(window)))
2165 /* If which_frames is a frame and window arg isn't on that frame, just
2166 return the first window on the frame. */
2167 return frame_first_window(XFRAME(which_frames));
2168 else if (!EQ(which_frames, Qt))
2169 which_frames = Qnil;
2170 /* Now `which_frames' is one of:
2171 t => search all frames
2172 nil => search just the current frame
2173 visible => search just visible frames
2174 0 => search visible and iconified frames
2175 a window => search the frame that window belongs to. */
2177 /* Do this loop at least once, to get the next window, and perhaps
2178 again, if we hit the minibuffer and that is not acceptable. */
2180 /* Find a window that actually has a next one. This loop
2181 climbs up the tree. */
2182 while (tem = XWINDOW(window)->next, NILP(tem))
2183 if (tem = XWINDOW(window)->parent, !NILP(tem))
2185 else { /* window must be minibuffer window now */
2187 /* We've reached the end of this frame.
2188 Which other frames are acceptable? */
2189 tem = WINDOW_FRAME(XWINDOW(window));
2191 if (!NILP(which_frames)) {
2192 Lisp_Object tem1 = tem;
2194 next_frame(tem, which_frames,
2197 /* In the case where the minibuffer is active,
2198 and we include its frame as well as the selected one,
2199 next_frame may get stuck in that frame.
2200 If that happens, go back to the selected frame
2201 so we can complete the cycle. */
2207 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2213 /* If we're in a combination window, find its first child and
2214 recurse on that. Otherwise, we've found the window we want. */
2216 if (!NILP(XWINDOW(window)->hchild))
2217 window = XWINDOW(window)->hchild;
2218 else if (!NILP(XWINDOW(window)->vchild))
2219 window = XWINDOW(window)->vchild;
2224 /* Which windows are acceptable?
2225 Exit the loop and accept this window if
2226 this isn't a minibuffer window,
2227 or we're accepting all minibuffer windows,
2228 or this is the active minibuffer and we are accepting that one, or
2229 we've come all the way around and we're back at the original window. */
2230 while (MINI_WINDOW_P(XWINDOW(window))
2232 && !EQ(minibuf, window)
2233 && !EQ(window, start_window));
2238 DEFUN("previous-window", Fprevious_window, 0, 4, 0, /*
2239 Return the window preceding WINDOW in the canonical ordering of windows.
2240 If omitted, WINDOW defaults to the selected window.
2242 Optional second arg MINIBUF t means count the minibuffer window even
2243 if not active. MINIBUF nil or omitted means count the minibuffer iff
2244 it is active. MINIBUF neither t nor nil means not to count the
2245 minibuffer even if it is active.
2247 Several frames may share a single minibuffer; if the minibuffer
2248 counts, all windows on all frames that share that minibuffer count
2249 too. Therefore, `previous-window' can be used to iterate through
2250 the set of windows even when the minibuffer is on another frame. If
2251 the minibuffer does not count, only windows from WINDOW's frame count.
2253 By default, only the windows in the selected frame are considered.
2254 The optional argument WHICH-FRAMES changes this behavior:
2255 WHICH-FRAMES = `visible' means search windows on all visible frames.
2256 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2257 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2258 WHICH-FRAMES = a frame means search only windows on that frame.
2259 Anything else means restrict to the selected frame.
2261 The optional fourth argument WHICH-DEVICES further clarifies on which
2262 devices to search for frames as specified by WHICH-FRAMES. This value
2263 is only meaningful if WHICH-FRAMES is non-nil.
2264 If nil or omitted, search all devices on the selected console.
2265 If a device, only search that device.
2266 If a console, search all devices on that console.
2267 If a device type, search all devices of that type.
2268 If `window-system', search all window-system devices.
2269 Any other non-nil value means search all devices.
2271 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2272 you can use `previous-window' to iterate through the entire cycle of
2273 acceptable windows, eventually ending up back at the window you started with.
2274 `next-window' traverses the same cycle, in the reverse order.
2276 (window, minibuf, which_frames, devices))
2279 Lisp_Object start_window;
2282 window = Fselected_window(Qnil);
2284 CHECK_LIVE_WINDOW(window);
2286 start_window = window;
2288 /* minibuf == nil may or may not include minibuffers.
2289 Decide if it does. */
2291 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2292 else if (!EQ(minibuf, Qt))
2294 /* Now `minibuf' is one of:
2295 t => count all minibuffer windows
2296 lambda => count none of them
2297 or a specific minibuffer window (the active one) to count. */
2299 /* which_frames == nil doesn't specify which frames to include.
2300 Decide which frames it includes. */
2301 if (NILP(which_frames))
2302 which_frames = (!EQ(minibuf, Qlambda)
2303 ? (FRAME_MINIBUF_WINDOW
2304 (XFRAME(WINDOW_FRAME(XWINDOW(window)))))
2306 else if (EQ(which_frames, Qvisible)) ;
2307 else if (ZEROP(which_frames)) ;
2308 else if (FRAMEP(which_frames)
2309 && !EQ(which_frames, Fwindow_frame(window)))
2310 /* If which_frames is a frame and window arg isn't on that frame, just
2311 return the first window on the frame. */
2312 return frame_first_window(XFRAME(which_frames));
2313 else if (!EQ(which_frames, Qt))
2314 which_frames = Qnil;
2315 /* Now `which_frames' is one of:
2316 t => search all frames
2317 nil => search just the current frame
2318 visible => search just visible frames
2319 0 => search visible and iconified frames
2320 a window => search the frame that window belongs to. */
2322 /* Do this loop at least once, to get the next window, and perhaps
2323 again, if we hit the minibuffer and that is not acceptable. */
2325 /* Find a window that actually has a next one. This loop
2326 climbs up the tree. */
2327 while (tem = XWINDOW(window)->prev, NILP(tem))
2328 if (tem = XWINDOW(window)->parent, !NILP(tem))
2330 else { /* window must be minibuffer window now */
2332 /* We have found the top window on the frame.
2333 Which frames are acceptable? */
2334 tem = WINDOW_FRAME(XWINDOW(window));
2336 if (!NILP(which_frames))
2337 /* It's actually important that we use previous_frame here,
2338 rather than next_frame. All the windows acceptable
2339 according to the given parameters should form a ring;
2340 Fnext_window and Fprevious_window should go back and
2341 forth around the ring. If we use next_frame here,
2342 then Fnext_window and Fprevious_window take different
2343 paths through the set of acceptable windows.
2344 window_loop assumes that these `ring' requirement are
2347 Lisp_Object tem1 = tem;
2349 previous_frame(tem, which_frames,
2351 /* In the case where the minibuffer is active,
2352 and we include its frame as well as the selected one,
2353 next_frame may get stuck in that frame.
2354 If that happens, go back to the selected frame
2355 so we can complete the cycle. */
2361 /* If this frame has a minibuffer, find that window first,
2362 because it is conceptually the last window in that frame. */
2363 if (FRAME_HAS_MINIBUF_P(XFRAME(tem)))
2364 tem = FRAME_MINIBUF_WINDOW(XFRAME(tem));
2366 tem = FRAME_ROOT_WINDOW(XFRAME(tem));
2373 /* If we're in a combination window, find its first child and
2374 recurse on that. Otherwise, we've found the window we want. */
2376 if (!NILP(XWINDOW(window)->hchild))
2377 window = XWINDOW(window)->hchild;
2378 else if (!NILP(XWINDOW(window)->vchild))
2379 window = XWINDOW(window)->vchild;
2382 while (tem = XWINDOW(window)->next, !NILP(tem))
2386 /* Which windows are acceptable?
2387 Exit the loop and accept this window if
2388 this isn't a minibuffer window,
2389 or we're accepting all minibuffer windows,
2390 or this is the active minibuffer and we are accepting that one, or
2391 we've come all the way around and we're back at the original window. */
2392 while (MINI_WINDOW_P(XWINDOW(window))
2394 && !EQ(minibuf, window)
2395 && !EQ(window, start_window));
2400 DEFUN("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2401 Return the next window which is vertically after WINDOW.
2406 struct window *w = decode_window(window);
2407 XSETWINDOW(window, w);
2409 if (MINI_WINDOW_P(XWINDOW(window)))
2412 root = FRAME_ROOT_WINDOW(XFRAME(WINDOW_FRAME(XWINDOW(window))));
2414 if (EQ(window, root)) {
2416 if (!NILP(XWINDOW(window)->hchild))
2417 window = XWINDOW(window)->hchild;
2418 else if (!NILP(XWINDOW(window)->vchild))
2419 window = XWINDOW(window)->vchild;
2425 if (!NILP(XWINDOW(window)->parent) &&
2426 !NILP(XWINDOW(XWINDOW(window)->parent)->vchild)) {
2427 if (!NILP(XWINDOW(window)->next))
2428 return XWINDOW(window)->next;
2430 window = XWINDOW(window)->parent;
2432 window = XWINDOW(window)->parent;
2434 while (!EQ(window, root));
2437 if (!NILP(XWINDOW(window)->hchild))
2438 window = XWINDOW(window)->hchild;
2439 else if (!NILP(XWINDOW(window)->vchild))
2440 window = XWINDOW(window)->vchild;
2445 DEFUN("other-window", Fother_window, 1, 3, "p", /*
2446 Select the COUNT'th different window on this frame.
2447 All windows on current frame are arranged in a cyclic order.
2448 This command selects the window COUNT steps away in that order.
2449 A negative COUNT moves in the opposite order.
2451 By default, only the windows in the selected frame are considered.
2452 The optional argument WHICH-FRAMES changes this behavior:
2453 WHICH-FRAMES = `visible' means search windows on all visible frames.
2454 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2455 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2456 WHICH-FRAMES = a frame means search only windows on that frame.
2457 Anything else means restrict to the selected frame.
2459 The optional argument WHICH-DEVICES further clarifies on which devices
2460 to search for frames as specified by WHICH-FRAMES. This value is only
2461 meaningful if WHICH-FRAMES is non-nil.
2462 If nil or omitted, search all devices on the selected console.
2463 If a device, only search that device.
2464 If a console, search all devices on that console.
2465 If a device type, search all devices of that type.
2466 If `window-system', search all window-system devices.
2467 Any other non-nil value means search all devices.
2469 (count, which_frames, which_devices))
2475 w = Fselected_window(Qnil);
2479 w = Fnext_window(w, Qnil, which_frames, which_devices);
2483 w = Fprevious_window(w, Qnil, which_frames, which_devices);
2486 Fselect_window(w, Qnil);
2490 /* Look at all windows, performing an operation specified by TYPE
2493 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2494 frame. If FRAMES is a frame, just look at windows on that frame.
2495 If MINI is non-zero, perform the operation on minibuffer windows too.
2500 GET_BUFFER_WINDOW, /* Arg is buffer */
2501 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2502 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2503 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2504 UNDEDICATE_BUFFER, /* Arg is buffer */
2506 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2507 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2511 window_loop(enum window_loop type,
2514 Lisp_Object which_frames,
2515 int dedicated_too, Lisp_Object which_devices)
2517 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2519 Lisp_Object best_window = Qnil;
2520 Lisp_Object next_window;
2521 Lisp_Object last_window;
2522 struct frame *frame;
2523 Lisp_Object frame_arg = Qt;
2524 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2525 /* #### I think the change of "precomputing" last_window and next_window
2526 * #### catch the lossage this is meant(?) to punt on...
2529 Lisp_Object devcons, concons;
2531 /* If we're only looping through windows on a particular frame,
2532 FRAME points to that frame. If we're looping through windows
2533 on all frames, FRAME is 0. */
2534 if (FRAMEP(which_frames))
2535 frame = XFRAME(which_frames);
2536 else if (NILP(which_frames))
2537 frame = selected_frame();
2541 /* FRAME_ARG is Qlambda to stick to one frame,
2542 Qvisible to consider all visible frames,
2545 frame_arg = Qlambda;
2546 } else if (ZEROP(which_frames)) {
2547 frame_arg = which_frames;
2548 } else if (EQ(which_frames, Qvisible)) {
2549 frame_arg = which_frames;
2552 DEVICE_LOOP_NO_BREAK(devcons, concons) {
2553 Lisp_Object device = XCAR(devcons);
2554 Lisp_Object the_frame;
2557 XSETFRAME(the_frame, frame);
2559 the_frame = DEVICE_SELECTED_FRAME(XDEVICE(device));
2561 if (NILP(the_frame))
2564 if (!device_matches_device_spec(device,
2565 NILP(which_devices) ?
2566 FRAME_CONSOLE(XFRAME(the_frame))
2570 /* Pick a window to start with. */
2574 w = FRAME_SELECTED_WINDOW(XFRAME(the_frame));
2576 /* Figure out the last window we're going to mess with. Since
2577 Fnext_window, given the same options, is guaranteed to go in a
2578 ring, we can just use Fprevious_window to find the last one.
2580 We can't just wait until we hit the first window again,
2581 because it might be deleted. */
2584 Fprevious_window(w, mini ? Qt : Qnil, frame_arg, device);
2588 struct window *p = XWINDOW(w);
2590 /* Pick the next window now, since some operations will delete
2591 the current window. */
2593 Fnext_window(w, mini ? Qt : Qnil, frame_arg,
2596 /* #### Still needed ?? */
2597 /* Given the outstanding quality of the rest of this code,
2598 I feel no shame about putting this piece of shit in. */
2599 if (++lose_lose >= 500) {
2600 /* Call to abort() added by Darryl Okahata (16 Nov. 2001),
2601 at Ben's request, to catch any remaining bugs.
2603 If you find that SXEmacs is aborting here, and you
2604 need to be up and running ASAP, it should be safe to
2605 comment out the following abort(), as long as you
2606 leave the "break;" alone. */
2608 break; /* <--- KEEP THIS HERE! Do not delete! */
2611 /* Note that we do not pay attention here to whether
2612 the frame is visible, since Fnext_window skips non-visible frames
2613 if that is desired, under the control of frame_arg. */
2614 if (!MINI_WINDOW_P(p)
2615 || (mini && minibuf_level > 0))
2617 case GET_BUFFER_WINDOW: {
2618 if (XBUFFER(p->buffer) ==
2624 case GET_BUFFER_WINDOW_COUNT: {
2625 if (XBUFFER(p->buffer) ==
2631 case GET_LRU_WINDOW: {
2632 /* t as arg means consider only
2633 full-width windows */
2635 && !window_full_width_p(p))
2637 /* Ignore dedicated windows and
2639 if (MINI_WINDOW_P(p)
2640 || (dedicated_too ? 0 :
2641 !NILP(p->dedicated)))
2643 if (NILP(best_window) ||
2644 (XINT(XWINDOW(best_window)->
2646 > XINT(p->use_time)))
2651 case GET_BUFFER_MRU_WINDOW: {
2652 /* #### what about the first check in
2654 /* Ignore dedicated windows and
2656 if (MINI_WINDOW_P(p)
2657 || (dedicated_too ? 0 :
2658 !NILP(p->dedicated)))
2661 if (XBUFFER(p->buffer) ==
2663 if (NILP(best_window)
2676 case UNDEDICATE_BUFFER: {
2677 if ((XBUFFER(p->buffer) ==
2679 p->dedicated = Qnil;
2684 case DELETE_OTHER_WINDOWS: {
2685 /* Don't delete the last window on a
2686 frame; this can happen when the
2687 minibuffer is selected, and would
2688 cause the frame to be deleted. */
2689 if (p != XWINDOW(obj) &&
2690 !TOP_LEVEL_WINDOW_P(XWINDOW (w))) {
2691 Fdelete_window(w, Qnil);
2696 case DELETE_BUFFER_WINDOWS: {
2697 if (EQ(p->buffer, obj)) {
2699 XFRAME(WINDOW_FRAME(p));
2701 /* If this window is dedicated,
2702 and in a frame of its own,
2704 if (EQ (w, FRAME_ROOT_WINDOW (f))
2705 && !NILP(p->dedicated)
2706 && (allow_deletion_of_last_visible_frame
2707 || other_visible_frames (f)))
2724 /* As we go, check for the end of the
2725 loop. We mustn't start going
2726 around a second time. */
2727 if (EQ(next_window, last_window)) {
2745 /* Now we can safely delete the frame. */
2750 /* If we're deleting the
2753 the frame, find a new
2756 if (NILP(p->parent)) {
2789 case GET_LARGEST_WINDOW: {
2790 /* Ignore dedicated windows and
2792 if (MINI_WINDOW_P(p)
2793 || (dedicated_too ? 0 :
2794 !NILP(p->dedicated)))
2797 /* write the check as follows to
2799 error_check_window() --ben */
2803 XWINDOW(best_window);
2804 if (NILP(best_window) ||
2805 ((WINDOW_HEIGHT(p) *
2807 > (WINDOW_HEIGHT(b) *
2808 WINDOW_WIDTH(b)))) {
2815 case WINDOW_LOOP_UNUSED:
2820 if (EQ(w, last_window)) {
2828 return type == GET_BUFFER_WINDOW_COUNT ? make_int(count) : best_window;
2831 #if 0 /* not currently used */
2833 int buffer_window_count(struct buffer *b, struct frame *f)
2835 Lisp_Object buffer, frame;
2837 XSETFRAME(frame, f);
2838 XSETBUFFER(buffer, b);
2840 return XINT(window_loop(GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2844 int buffer_window_mru(struct window *w)
2846 Lisp_Object window =
2847 window_loop(GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2851 else if (XWINDOW(window) == w)
2859 void undedicate_windows(Lisp_Object buffer, Lisp_Object frame)
2861 window_loop(UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2864 DEFUN("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2865 Return the window least recently selected or used for display.
2867 By default, only the windows in the selected frame are considered.
2868 The optional argument WHICH-FRAMES changes this behavior:
2869 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2870 If WHICH-FRAMES is 0, search all visible and iconified frames.
2871 If WHICH-FRAMES is t, search all frames.
2872 If WHICH-FRAMES is nil, search only the selected frame.
2873 If WHICH-FRAMES is a frame, search only that frame.
2875 The optional argument WHICH-DEVICES further clarifies on which devices
2876 to search for frames as specified by WHICH-FRAMES. This value is only
2877 meaningful if WHICH-FRAMES is non-nil.
2878 If nil or omitted, search all devices on the selected console.
2879 If a device, only search that device.
2880 If a console, search all devices on that console.
2881 If a device type, search all devices of that type.
2882 If `window-system', search all devices on window-system consoles.
2883 Any other non-nil value means search all devices.
2885 (which_frames, which_devices))
2888 /* First try for a non-dedicated window that is full-width */
2889 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2890 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2893 /* Then try for any non-dedicated window */
2894 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 0,
2896 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2900 /* FSFmacs never returns a dedicated window here. If we do,
2901 it makes `display-buffer' not work right. #### All of this
2902 shit is so disgusting and awful that it needs to be rethought
2904 /* then try for a dedicated window that is full-width */
2905 w = window_loop(GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2906 if (!NILP(w) && !EQ(w, Fselected_window(Qnil)))
2909 /* If none of them, then all windows, dedicated or not. */
2910 w = window_loop(GET_LRU_WINDOW, Qnil, 0, which_frames, 1,
2913 /* At this point we damn well better have found something. */
2921 DEFUN("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2922 Return the window largest in area.
2924 By default, only the windows in the selected frame are considered.
2925 The optional argument WHICH-FRAMES changes this behavior:
2926 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2927 If WHICH-FRAMES is 0, search all visible and iconified frames.
2928 If WHICH-FRAMES is t, search all frames.
2929 If WHICH-FRAMES is nil, search only the selected frame.
2930 If WHICH-FRAMES is a frame, search only that frame.
2932 The optional argument WHICH-DEVICES further clarifies on which devices
2933 to search for frames as specified by WHICH-FRAMES. This value is only
2934 meaningful if WHICH-FRAMES is non-nil.
2935 If nil or omitted, search all devices on the selected console.
2936 If a device, only search that device.
2937 If a console, search all devices on that console.
2938 If a device type, search all devices of that type.
2939 If `window-system', search all devices on window-system consoles.
2940 Any other non-nil value means search all devices.
2942 (which_frames, which_devices))
2944 /* Don't search dedicated windows because FSFmacs doesn't.
2945 This stuff is all black magic so don't try to apply common
2947 return window_loop(GET_LARGEST_WINDOW, Qnil, 0,
2948 which_frames, 0, which_devices);
2951 DEFUN("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2952 Return a window currently displaying BUFFER, or nil if none.
2954 By default, only the windows in the selected frame are considered.
2955 The optional argument WHICH-FRAMES changes this behavior:
2956 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2957 If WHICH-FRAMES is 0, search all visible and iconified frames.
2958 If WHICH-FRAMES is t, search all frames.
2959 If WHICH-FRAMES is nil, search only the selected frame.
2960 If WHICH-FRAMES is a frame, search only that frame.
2962 The optional argument WHICH-DEVICES further clarifies on which devices
2963 to search for frames as specified by WHICH-FRAMES. This value is only
2964 meaningful if WHICH-FRAMES is non-nil.
2965 If nil or omitted, search all devices on the selected console.
2966 If a device, only search that device.
2967 If a console, search all devices on that console.
2968 If a device type, search all devices of that type.
2969 If `window-system', search all devices on window-system consoles.
2970 Any other non-nil value means search all devices.
2972 (buffer, which_frames, which_devices))
2974 buffer = Fget_buffer(buffer);
2975 if (BUFFERP(buffer))
2976 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2977 return window_loop(GET_BUFFER_WINDOW, buffer, 1,
2978 which_frames, 1, which_devices);
2983 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2984 but there is no sensible way to implement those functions, since
2985 you can't in general derive a window from a buffer. */
2987 DEFUN("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width, 0, 1, 0, /*
2988 Return the width in pixels of the left outside margin of window WINDOW.
2989 If WINDOW is nil, the selected window is assumed.
2993 return make_int(window_left_margin_width(decode_window(window)));
2996 DEFUN("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width, 0, 1, 0, /*
2997 Return the width in pixels of the right outside margin of window WINDOW.
2998 If WINDOW is nil, the selected window is assumed.
3002 return make_int(window_right_margin_width(decode_window(window)));
3005 DEFUN("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
3006 Make WINDOW (or the selected window) fill its frame.
3007 Only the frame WINDOW is on is affected.
3008 This function tries to reduce display jumps
3009 by keeping the text previously visible in WINDOW
3010 in the same place on the frame. Doing this depends on
3011 the value of (window-start WINDOW), so if calling this function
3012 in a program gives strange scrolling, make sure the window-start
3013 value is reasonable when this function is called.
3018 struct window *w = decode_window(window);
3019 struct buffer *b = XBUFFER(w->buffer);
3021 int old_top = WINDOW_TOP(w);
3023 XSETWINDOW(window, w);
3025 if (MINI_WINDOW_P(w) && old_top > 0)
3026 error("Can't expand minibuffer to full frame");
3028 /* Ignore dedicated windows. */
3029 window_loop(DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3031 start_pos = marker_position(w->start[CURRENT_DISP]);
3033 /* Try to minimize scrolling, by setting the window start to the
3034 point which will cause the text at the old window start to be at
3035 the same place on the frame. But don't try to do this if the
3036 window start is outside the visible portion (as might happen when
3037 the display is not current, due to typeahead). */
3038 if (start_pos >= BUF_BEGV(b) && start_pos <= BUF_ZV(b)
3039 && !MINI_WINDOW_P(w)) {
3041 start_with_line_at_pixpos(w, start_pos, old_top);
3043 if (new_start >= BUF_BEGV(b) && new_start <= BUF_ZV(b)) {
3044 Fset_marker(w->start[CURRENT_DISP], make_int(new_start),
3046 w->start_at_line_beg =
3047 beginning_of_line_p(b, new_start);
3049 /* We need to do this, so that the window-scroll-functions
3054 run_window_configuration_hook( window );
3059 DEFUN("delete-windows-on", Fdelete_windows_on, 1, 3, "bDelete windows on (buffer): ", /*
3060 Delete all windows showing BUFFER.
3062 Optional second argument WHICH-FRAMES controls which frames are affected.
3063 If nil or omitted, delete all windows showing BUFFER in any frame.
3064 If t, delete only windows showing BUFFER in the selected frame.
3065 If `visible', delete all windows showing BUFFER in any visible frame.
3066 If a frame, delete only windows showing BUFFER in that frame.
3067 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3068 except that the meanings of nil and t are reversed.
3070 The optional third argument WHICH-DEVICES further clarifies on which
3071 devices to search for frames as specified by WHICH-FRAMES. This value
3072 is only meaningful if WHICH-FRAMES is not t.
3073 If nil or omitted, search only the selected console.
3074 If a device, only search that device.
3075 If a console, search all devices on that console.
3076 If a device type, search all devices of that type.
3077 If `window-system', search all devices on a window system.
3078 Any other non-nil value means search all devices.
3080 (buffer, which_frames, which_devices))
3082 /* This function can GC */
3083 buffer = Fget_buffer(buffer);
3084 CHECK_BUFFER(buffer);
3086 /* WHICH-FRAMES values t and nil mean the opposite of what
3087 window_loop expects. */
3088 if (EQ(which_frames, Qnil))
3090 else if (EQ(which_frames, Qt))
3091 which_frames = Qnil;
3093 /* Ignore dedicated windows. */
3094 window_loop(DELETE_BUFFER_WINDOWS, buffer, 0,
3095 which_frames, 0, which_devices);
3099 static Lisp_Object list_windows(struct window *w, Lisp_Object value)
3102 if (!NILP(w->hchild))
3103 value = list_windows(XWINDOW(w->hchild), value);
3104 else if (!NILP(w->vchild))
3105 value = list_windows(XWINDOW(w->vchild), value);
3108 XSETWINDOW(window, w);
3109 value = Fcons(window, value);
3113 w = XWINDOW(w->next);
3119 list_all_windows(Lisp_Object frame_spec, Lisp_Object device_spec)
3121 Lisp_Object devcons, concons;
3122 Lisp_Object retval = Qnil;
3124 DEVICE_LOOP_NO_BREAK(devcons, concons) {
3125 Lisp_Object frame_list, the_window;
3126 Lisp_Object device, tail;
3128 device = XCAR(devcons);
3129 frame_list = DEVICE_FRAME_LIST(XDEVICE(device));
3131 LIST_LOOP(tail, frame_list) {
3132 if ((NILP(frame_spec)
3134 DEVICE_SELECTED_FRAME(XDEVICE(device))))
3135 || (EQ(frame_spec, Qvisible)
3136 && !FRAME_VISIBLE_P(XFRAME(XCAR(tail))))
3137 || (FRAMEP(frame_spec)
3138 && !EQ(frame_spec, XCAR(tail)))
3139 || (!NILP(frame_spec)
3140 && !device_matches_device_spec(device,
3146 the_window = FRAME_ROOT_WINDOW(XFRAME(XCAR(tail)));
3147 retval = list_windows(XWINDOW(the_window), retval);
3150 return Fnreverse(retval);
3153 DEFUN("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3, "bReplace buffer in windows: ", /*
3154 Replace BUFFER with some other buffer in all windows showing it.
3156 Optional second argument WHICH-FRAMES controls which frames are affected.
3157 If nil or omitted, all frames are affected.
3158 If t, only the selected frame is affected.
3159 If `visible', all visible frames are affected.
3160 If a frame, only that frame is affected.
3161 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3162 except that the meanings of nil and t are reversed.
3164 The optional third argument WHICH-DEVICES further clarifies on which
3165 devices to search for frames as specified by WHICH-FRAMES. This value
3166 is only meaningful if WHICH-FRAMES is not t.
3167 If nil or omitted, search only the selected console.
3168 If a device, only search that device.
3169 If a console, search all devices on that console.
3170 If a device type, search all devices of that type.
3171 If `window-system', search all devices on a window system.
3172 Any other non-nil value means search all devices.
3174 (buffer, which_frames, which_devices))
3176 /* This function can GC */
3177 Lisp_Object window_list;
3179 struct gcpro gcpro1, gcpro2;
3181 if (EQ(which_frames, Qnil))
3183 else if (EQ(which_frames, Qt))
3184 which_frames = Qnil;
3185 window_list = list_all_windows(which_frames, which_devices);
3187 buffer = Fget_buffer(buffer);
3188 CHECK_BUFFER(buffer);
3190 GCPRO2(window_list, buffer);
3191 LIST_LOOP(tail, window_list) {
3192 Lisp_Object window = XCAR(tail);
3193 if (!MINI_WINDOW_P(XWINDOW(window))
3194 && EQ(XWINDOW(window)->buffer, buffer)) {
3195 Lisp_Object another_buffer =
3196 Fother_buffer(buffer, Qnil, Qnil);
3197 Lisp_Object frame = WINDOW_FRAME(XWINDOW(window));
3198 if (NILP(another_buffer))
3199 another_buffer = Fget_buffer_create(QSscratch);
3200 if (!NILP(XWINDOW(window)->dedicated)
3201 && EQ(window, FRAME_ROOT_WINDOW(XFRAME(frame)))
3202 && (allow_deletion_of_last_visible_frame
3203 || other_visible_frames (XFRAME (frame))))
3205 delete_frame_internal(XFRAME(frame), 0, 0, 0); /* GC */
3207 Fset_window_buffer(window, another_buffer,
3209 if (EQ(window, Fselected_window(Qnil)))
3210 Fset_buffer(XWINDOW(window)->buffer);
3218 /* The smallest acceptable dimensions for a window. Anything smaller
3219 might crash Emacs. */
3220 #define MIN_SAFE_WINDOW_WIDTH (2)
3221 #define MIN_SAFE_WINDOW_HEIGHT (2)
3223 /* Make sure that window_min_height and window_min_width are
3224 not too small; if they are, set them to safe minima. */
3226 static void check_min_window_sizes(void)
3228 /* Smaller values might permit a crash. */
3229 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3230 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3231 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3232 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3235 static int frame_min_height(struct frame *frame)
3237 /* For height, we have to see whether the frame has a minibuffer, and
3238 whether it wants a modeline. */
3239 return (FRAME_MINIBUF_ONLY_P(frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3240 : (!FRAME_HAS_MINIBUF_P(frame)) ? MIN_SAFE_WINDOW_HEIGHT
3241 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3244 /* Return non-zero if both frame sizes are less than or equal to
3245 minimal allowed values. ROWS and COLS are in characters */
3246 int frame_size_valid_p(struct frame *frame, int rows, int cols)
3248 return (rows >= frame_min_height(frame)
3249 && cols >= MIN_SAFE_WINDOW_WIDTH);
3252 /* Return non-zero if both frame sizes are less than or equal to
3253 minimal allowed values. WIDTH and HEIGHT are in pixels */
3254 int frame_pixsize_valid_p(struct frame *frame, int width, int height)
3257 pixel_to_real_char_size(frame, width, height, &cols, &rows);
3258 return frame_size_valid_p(frame, rows, cols);
3261 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3262 minimum allowable size. */
3263 void check_frame_size(struct frame *frame, int *rows, int *cols)
3265 int min_height = frame_min_height(frame);
3267 if (*rows < min_height)
3269 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3270 *cols = MIN_SAFE_WINDOW_WIDTH;
3273 /* Normally the window is deleted if it gets too small.
3274 nodelete nonzero means do not do this.
3275 (The caller should check later and do so if appropriate) */
3277 set_window_pixsize(Lisp_Object window, int new_pixsize, int nodelete,
3280 struct window *w = XWINDOW(window);
3281 struct frame *f = XFRAME(w->frame);
3283 int old_pixsize = (set_height ? WINDOW_HEIGHT(w) : WINDOW_WIDTH(w));
3284 Lisp_Object child, minor_kid, major_kid;
3287 int defheight, defwidth;
3289 /* #### This is very likely incorrect and instead the char_to_pixel_
3290 functions should be called. */
3291 default_face_height_and_width(window, &defheight, &defwidth);
3292 line_size = (set_height ? defheight : defwidth);
3294 check_min_window_sizes();
3296 minsize = (set_height ? window_min_height : window_min_width);
3297 minsize *= line_size;
3299 if (!nodelete && !TOP_LEVEL_WINDOW_P(w)
3300 && new_pixsize < minsize) {
3301 Fdelete_window(window, Qnil);
3305 SET_LAST_MODIFIED(w, 0);
3306 SET_LAST_FACECHANGE(w);
3307 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f); /* multiple windows affected */
3309 WINDOW_HEIGHT(w) = new_pixsize;
3310 major_kid = w->vchild;
3311 minor_kid = w->hchild;
3313 WINDOW_WIDTH(w) = new_pixsize;
3314 major_kid = w->hchild;
3315 minor_kid = w->vchild;
3318 if (!NILP(minor_kid)) {
3319 for (child = minor_kid; !NILP(child);
3320 child = XWINDOW(child)->next) {
3322 WINDOW_TOP(XWINDOW(child)) = WINDOW_TOP(w);
3324 WINDOW_LEFT(XWINDOW(child)) = WINDOW_LEFT(w);
3326 set_window_pixsize(child, new_pixsize, nodelete,
3329 } else if (!NILP(major_kid)) {
3330 int last_pos, last_old_pos, pos, old_pos, first;
3331 int pixel_adj_left = new_pixsize - old_pixsize;
3332 int div_val = old_pixsize << 1;
3335 * Previously we bailed out here if there was no size change.
3336 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3337 * toolbar appears or disappears, windows may not change size,
3338 * but their top and left coordinates need to be updated.
3340 * So we don't bail until after the loop below.
3344 (set_height ? WINDOW_TOP(w) : WINDOW_LEFT(w));
3347 for (child = major_kid; !NILP(child); child = c->next) {
3351 old_pos = last_old_pos + WINDOW_HEIGHT(c);
3352 WINDOW_TOP(c) = last_pos;
3354 old_pos = last_old_pos + WINDOW_WIDTH(c);
3355 WINDOW_LEFT(c) = last_pos;
3359 (((old_pos * new_pixsize) << 1) +
3360 old_pixsize) / div_val;
3361 /* All but the last window should have a height which is
3362 a multiple of the default line height. */
3364 pos = (pos / line_size) * line_size;
3366 /* Avoid confusion: don't delete child if it becomes too small */
3367 set_window_pixsize(child, pos + first - last_pos, 1,
3370 last_pos = pos + first;
3371 last_old_pos = old_pos;
3374 /* Sometimes we may get called with our old size. In that case
3375 we don't need to do anything else. */
3376 if (!pixel_adj_left)
3379 /* Now delete any children that became too small. */
3381 for (child = major_kid; !NILP(child);
3382 child = XWINDOW(child)->next) {
3384 set_window_pixheight(child,
3389 set_window_pixwidth(child,
3390 WINDOW_WIDTH(XWINDOW
3397 /* Set the height of WINDOW and all its inferiors. */
3398 void set_window_pixheight(Lisp_Object window, int new_pixheight, int nodelete)
3400 set_window_pixsize(window, new_pixheight, nodelete, 1);
3403 /* Recursively set width of WINDOW and its inferiors. */
3404 void set_window_pixwidth(Lisp_Object window, int new_pixwidth, int nodelete)
3406 set_window_pixsize(window, new_pixwidth, nodelete, 0);
3409 static int window_select_count;
3411 DEFUN("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3412 Make WINDOW display BUFFER as its contents.
3413 When WINDOW is nil, the `selected-window' is used.
3414 BUFFER can be a buffer or buffer name.
3416 With non-nil optional argument NORECORD, do not modify the
3417 global or per-frame buffer ordering.
3420 (window, buffer, norecord))
3423 struct window *w = decode_window(window);
3424 int old_buffer_local_face_property = 0;
3426 buffer = Fget_buffer(buffer);
3427 CHECK_BUFFER(buffer);
3429 if (!BUFFER_LIVE_P(XBUFFER(buffer)))
3430 error("Attempt to display deleted buffer");
3434 error("Window is deleted");
3436 /* While this seems like a logical thing to do, it causes problems
3437 because of saved window configurations. It is possible for a
3438 buffer to get restored into a window in which it is already being
3439 displayed, but start and point are actually at completely
3440 different locations. So we let this function complete fully and
3441 it will then make sure redisplay correctly updates things.
3443 #### This is a kludge. The correct approach is not to do this
3444 but to fix set-window-configuration. */
3446 else if (EQ(tem, buffer))
3449 else if (!EQ(tem, Qt)) { /* w->buffer is t when the window
3450 is first being set up. */
3451 if (!NILP(w->dedicated) && !EQ(tem, buffer))
3452 error("Window is dedicated to buffer %s",
3453 XSTRING_DATA(XBUFFER(tem)->name));
3455 old_buffer_local_face_property =
3456 XBUFFER(w->buffer)->buffer_local_face_property;
3461 w->window_end_pos[CURRENT_DISP] = 0;
3463 w->modeline_hscroll = 0;
3464 Fset_marker(w->pointm[CURRENT_DISP],
3465 make_int(BUF_PT(XBUFFER(buffer))), buffer);
3466 set_marker_restricted(w->start[CURRENT_DISP],
3467 make_int(XBUFFER(buffer)->last_window_start),
3469 Fset_marker(w->sb_point, w->start[CURRENT_DISP], buffer);
3470 /* set start_at_line_beg correctly. GE */
3471 w->start_at_line_beg = beginning_of_line_p(XBUFFER(buffer),
3475 w->force_start = 0; /* Lucid fix */
3476 SET_LAST_MODIFIED(w, 1);
3477 SET_LAST_FACECHANGE(w);
3478 MARK_WINDOWS_CHANGED(w);
3480 int new_buffer_local_face_property =
3481 XBUFFER(w->buffer)->buffer_local_face_property;
3483 if (new_buffer_local_face_property
3484 || new_buffer_local_face_property !=
3485 old_buffer_local_face_property)
3486 MARK_WINDOW_FACES_CHANGED(w);
3488 recompute_all_cached_specifiers_in_window(w);
3489 if (EQ(window, Fselected_window(Qnil))) {
3491 Frecord_buffer(buffer);
3493 Fset_buffer(buffer);
3496 run_window_configuration_hook( window );
3501 DEFUN("select-window", Fselect_window, 1, 2, 0, /*
3502 Select WINDOW. Most editing will apply to WINDOW's buffer.
3503 The main editor command loop selects the buffer of the selected window
3504 before each command.
3506 With non-nil optional argument NORECORD, do not modify the
3507 global or per-frame buffer ordering.
3512 Lisp_Object old_selected_window = Fselected_window(Qnil);
3514 CHECK_LIVE_WINDOW(window);
3515 w = XWINDOW(window);
3517 /* we have already caught dead-window errors */
3518 if (!NILP(w->hchild) || !NILP(w->vchild))
3519 error("Trying to select non-leaf window");
3521 w->use_time = make_int(++window_select_count);
3523 if (EQ(window, old_selected_window))
3526 /* deselect the old window, if it exists (it might not exist if
3527 the selected device has no frames, which occurs at startup) */
3528 if (!NILP(old_selected_window)) {
3529 struct window *ow = XWINDOW(old_selected_window);
3531 Fset_marker(ow->pointm[CURRENT_DISP],
3532 make_int(BUF_PT(XBUFFER(ow->buffer))), ow->buffer);
3534 MARK_WINDOWS_CHANGED(ow);
3537 /* now select the window's frame */
3538 set_frame_selected_window(XFRAME(WINDOW_FRAME(w)), window);
3540 select_frame_1(WINDOW_FRAME(w));
3542 /* also select the window's buffer */
3544 Frecord_buffer(w->buffer);
3545 Fset_buffer(w->buffer);
3547 /* Go to the point recorded in the window.
3548 This is important when the buffer is in more
3549 than one window. It also matters when
3550 redisplay_window has altered point after scrolling,
3551 because it makes the change only in the window. */
3553 Bufpos new_point = marker_position(w->pointm[CURRENT_DISP]);
3554 if (new_point < BUF_BEGV(current_buffer))
3555 new_point = BUF_BEGV(current_buffer);
3556 else if (new_point > BUF_ZV(current_buffer))
3557 new_point = BUF_ZV(current_buffer);
3559 BUF_SET_PT(current_buffer, new_point);
3562 MARK_WINDOWS_CHANGED(w);
3568 display_buffer(Lisp_Object buffer, Lisp_Object not_this_window_p,
3569 Lisp_Object override_frame)
3571 return call3(Qdisplay_buffer, buffer, not_this_window_p,
3575 void temp_output_buffer_show(Lisp_Object buf, Lisp_Object same_frame)
3577 /* This function can GC */
3580 struct buffer *b = XBUFFER(buf);
3582 BUF_SAVE_MODIFF(XBUFFER(buf)) = BUF_MODIFF(b);
3584 BUF_SET_PT(b, BUF_BEG(b));
3586 if (!NILP(Vtemp_buffer_show_function))
3587 call1(Vtemp_buffer_show_function, buf);
3589 window = display_buffer(buf, Qnil, same_frame);
3591 if (!EQ(XWINDOW(window)->frame, Fselected_frame(Qnil)))
3592 Fmake_frame_visible(WINDOW_FRAME(XWINDOW(window)));
3594 Vminibuffer_scroll_window = window;
3595 w = XWINDOW(window);
3597 w->modeline_hscroll = 0;
3598 set_marker_restricted(w->start[CURRENT_DISP], make_int(1), buf);
3599 set_marker_restricted(w->pointm[CURRENT_DISP], make_int(1),
3601 set_marker_restricted(w->sb_point, make_int(1), buf);
3603 /* Run temp-buffer-show-hook, with the chosen window selected. */
3604 if (!preparing_for_armageddon) {
3606 tem = Fboundp(Qtemp_buffer_show_hook);
3608 tem = Fsymbol_value(Qtemp_buffer_show_hook);
3610 int count = specpdl_depth();
3612 /* Select the window that was chosen, for running
3614 record_unwind_protect
3615 (save_window_excursion_unwind,
3616 Fcurrent_window_configuration
3619 Fselect_window(window, Qnil);
3620 run_hook(Qtemp_buffer_show_hook);
3621 unbind_to(count, Qnil);
3628 static void make_dummy_parent(Lisp_Object window)
3631 struct window *o = XWINDOW(window);
3632 struct window *p = alloc_lcrecord_type(struct window, &lrecord_window);
3635 copy_lcrecord(p, o);
3637 /* Don't copy the pointers to the line start cache or the face
3639 p->line_start_cache = Dynarr_new(line_start_cache);
3640 p->face_cachels = Dynarr_new(face_cachel);
3641 p->glyph_cachels = Dynarr_new(glyph_cachel);
3642 p->subwindow_instance_cache = make_image_instance_cache_hash_table();
3644 /* Put new into window structure in place of window */
3645 replace_window(window, new);
3653 p->start[CURRENT_DISP] = Qnil;
3654 p->start[DESIRED_DISP] = Qnil;
3655 p->start[CMOTION_DISP] = Qnil;
3656 p->pointm[CURRENT_DISP] = Qnil;
3657 p->pointm[DESIRED_DISP] = Qnil;
3658 p->pointm[CMOTION_DISP] = Qnil;
3663 DEFUN("split-window", Fsplit_window, 0, 3, "", /*
3664 Split WINDOW, putting SIZE lines in the first of the pair.
3665 WINDOW defaults to the selected one and SIZE to half its size.
3666 If optional third arg HORFLAG is non-nil, split side by side and put
3667 SIZE columns in the first of the pair. The newly created window is
3671 (window, size, horflag))
3674 struct window *o, *p;
3680 window = Fselected_window(Qnil);
3682 CHECK_LIVE_WINDOW(window);
3684 o = XWINDOW(window);
3685 f = XFRAME(WINDOW_FRAME(o));
3689 /* In the new scheme, we are symmetric with respect to separators
3690 so there is no need to do weird things here. */
3693 (WINDOW_WIDTH(o) + window_divider_width(o)) >> 1;
3694 csize = window_pixel_width_to_char_width(o, psize, 0);
3696 psize = WINDOW_HEIGHT(o) >> 1;
3697 csize = window_pixel_height_to_char_height(o, psize, 1);
3703 psize = window_char_width_to_pixel_width(o, csize, 0);
3705 psize = window_char_height_to_pixel_height(o, csize, 1);
3708 if (MINI_WINDOW_P(o))
3709 error("Attempt to split minibuffer window");
3710 else if (FRAME_NO_SPLIT_P(XFRAME(WINDOW_FRAME(o))))
3711 error("Attempt to split unsplittable frame");
3713 check_min_window_sizes();
3715 if (NILP(horflag)) {
3716 if (csize < window_min_height)
3717 error("Window height %d too small (after splitting)",
3719 if (csize + window_min_height > window_char_height(o, 1))
3720 error("Window height %d too small (after splitting)",
3721 window_char_height(o, 1) - csize);
3723 || NILP(XWINDOW(o->parent)->vchild)) {
3724 make_dummy_parent(window);
3726 /* #### I can't understand why you have to reset face
3727 cachels here. This can cause crash so let's disable it
3728 and see the difference. See redisplay-tests.el --yh */
3729 reset_face_cachels(XWINDOW(window));
3732 XWINDOW(new)->vchild = window;
3733 XFRAME(o->frame)->mirror_dirty = 1;
3736 if (csize < window_min_width)
3737 error("Window width %d too small (after splitting)",
3739 if (csize + window_min_width > window_char_width(o, 0))
3740 error("Window width %d too small (after splitting)",
3741 window_char_width(o, 0) - csize);
3743 || NILP(XWINDOW(o->parent)->hchild)) {
3744 make_dummy_parent(window);
3746 /* #### See above. */
3747 reset_face_cachels(XWINDOW(window));
3750 XWINDOW(new)->hchild = window;
3751 XFRAME(o->frame)->mirror_dirty = 1;
3755 /* Now we know that window's parent is a vertical combination
3756 if we are dividing vertically, or a horizontal combination
3757 if we are making side-by-side windows */
3759 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
3760 new = allocate_window();
3763 p->frame = o->frame;
3766 XWINDOW(p->next)->prev = new;
3769 p->parent = o->parent;
3772 reset_face_cachels(p);
3773 reset_glyph_cachels(p);
3775 /* Apportion the available frame space among the two new windows */
3777 if (!NILP(horflag)) {
3778 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o);
3779 WINDOW_TOP(p) = WINDOW_TOP(o);
3780 WINDOW_WIDTH(p) = WINDOW_WIDTH(o) - psize;
3781 WINDOW_WIDTH(o) = psize;
3782 WINDOW_LEFT(p) = WINDOW_LEFT(o) + psize;
3784 WINDOW_LEFT(p) = WINDOW_LEFT(o);
3785 WINDOW_WIDTH(p) = WINDOW_WIDTH(o);
3786 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(o) - psize;
3787 WINDOW_HEIGHT(o) = psize;
3788 WINDOW_TOP(p) = WINDOW_TOP(o) + psize;
3791 XFRAME(p->frame)->mirror_dirty = 1;
3792 /* do this last (after the window is completely initialized and
3793 the mirror-dirty flag is set) so that specifier recomputation
3794 caused as a result of this will work properly and not abort. */
3795 Fset_window_buffer(new, o->buffer, Qt);
3797 /* window-configuration-hook is called indirectly, in
3798 set-window-buffer. */
3803 DEFUN("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3804 Make the selected window COUNT lines taller.
3805 From program, optional second arg HORIZONTALP non-nil means grow
3806 sideways COUNT columns, and optional third arg WINDOW specifies the
3807 window to change instead of the selected window.
3810 (count, horizontalp, window))
3813 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3818 DEFUN("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3819 Make the selected window COUNT pixels taller.
3820 From program, optional second arg HORIZONTALP non-nil means grow
3821 sideways COUNT pixels, and optional third arg WINDOW specifies the
3822 window to change instead of the selected window.
3825 (count, horizontalp, window))
3828 change_window_height(window, XINT(count), horizontalp, /* inpixels */
3833 DEFUN("shrink-window", Fshrink_window, 1, 3, "_p", /*
3834 Make the selected window COUNT lines shorter.
3835 From program, optional second arg HORIZONTALP non-nil means shrink
3836 sideways COUNT columns, and optional third arg WINDOW specifies the
3837 window to change instead of the selected window.
3840 (count, horizontalp, window))
3843 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3848 DEFUN("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3849 Make the selected window COUNT pixels smaller.
3850 From program, optional second arg HORIZONTALP non-nil means shrink
3851 sideways COUNT pixels, and optional third arg WINDOW specifies the
3852 window to change instead of the selected window.
3855 (count, horizontalp, window))
3858 change_window_height(window, -XINT(count), horizontalp, /* inpixels */
3864 window_pixel_height_to_char_height(struct window *w, int pixel_height,
3865 int include_gutters_p)
3868 int defheight, defwidth;
3872 XSETWINDOW(window, w);
3874 avail_height = (pixel_height -
3875 (include_gutters_p ? 0 :
3876 window_top_window_gutter_height(w) +
3877 window_bottom_window_gutter_height(w)));
3879 default_face_height_and_width(window, &defheight, &defwidth);
3881 char_height = avail_height / defheight;
3883 /* It's the calling function's responsibility to check these values
3884 and make sure they're not out of range.
3886 #### We need to go through the calling functions and actually
3888 return max(0, char_height);
3892 window_char_height_to_pixel_height(struct window *w, int char_height,
3893 int include_gutters_p)
3896 int defheight, defwidth;
3901 XSETWINDOW(window, w);
3903 default_face_height_and_width(window, &defheight, &defwidth);
3905 avail_height = char_height * defheight;
3906 pixel_height = (avail_height +
3907 (include_gutters_p ? 0 :
3908 window_top_window_gutter_height(w) +
3909 window_bottom_window_gutter_height(w)));
3911 /* It's the calling function's responsibility to check these values
3912 and make sure they're not out of range.
3914 #### We need to go through the calling functions and actually
3916 return max(0, pixel_height);
3919 /* Return number of default lines of text can fit in the window W.
3920 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3921 horizontal scrollbar) in the space that is used for the calculation.
3922 This doesn't include space used by the frame gutters.
3924 int window_char_height(struct window *w, int include_gutters_p)
3926 return window_pixel_height_to_char_height(w, window_pixel_height(w),
3931 * Return number of lines currently displayed in window w. If
3932 * end-of-buffer is displayed then the area below end-of-buffer is assume
3933 * to be blank lines of default height.
3934 * Does not include the modeline.
3936 int window_displayed_height(struct window *w)
3938 struct buffer *b = XBUFFER(w->buffer);
3939 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
3942 (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV(b)
3943 ? -1 : w->window_end_pos[CURRENT_DISP]);
3945 if (!Dynarr_length(dla))
3946 return window_char_height(w, 0);
3948 num_lines = Dynarr_length(dla);
3950 /* #### Document and assert somewhere that w->window_end_pos == -1
3951 indicates that end-of-buffer is being displayed. */
3952 if (end_pos == -1) {
3953 struct display_line *dl = Dynarr_atp(dla, 0);
3954 int ypos1 = dl->ypos + dl->descent;
3955 int ypos2 = WINDOW_TEXT_BOTTOM(w);
3957 int defheight, defwidth;
3959 XSETWINDOW(window, w);
3964 if (Dynarr_length(dla) == 1)
3965 ypos1 = WINDOW_TEXT_TOP(w);
3967 dl = Dynarr_atp(dla, Dynarr_length(dla) - 1);
3968 /* If this line is clipped then we know that there is no
3969 blank room between eob and the modeline. If we are
3970 scrolling on clipped lines just know off the clipped
3971 line and return . */
3972 if (scroll_on_clipped_lines && dl->clip)
3973 return num_lines - 1;
3974 ypos1 = dl->ypos + dl->descent - dl->clip;
3978 default_face_height_and_width(window, &defheight, &defwidth);
3979 /* #### This probably needs to know about the clipping area once a
3980 final definition is decided on. */
3981 num_lines += ((ypos2 - ypos1) / defheight);
3983 if (num_lines > 1 && Dynarr_atp(dla, 0)->modeline)
3986 if (scroll_on_clipped_lines
3987 && Dynarr_atp(dla, Dynarr_length(dla) - 1)->clip)
3994 static int window_pixel_width(Lisp_Object window)
3996 return WINDOW_WIDTH(XWINDOW(window));
3999 /* Calculate the pixel of a window, optionally including margin space
4000 but no vertical gutters. */
4002 window_pixel_width_to_char_width(struct window *w, int pixel_width,
4003 int include_margins_p)
4007 int defheight, defwidth;
4010 XSETWINDOW(window, w);
4012 avail_width = (pixel_width -
4013 window_left_gutter_width(w, 0) -
4014 window_right_gutter_width(w, 0) -
4015 (include_margins_p ? 0 : window_left_margin_width(w)) -
4016 (include_margins_p ? 0 : window_right_margin_width(w)));
4018 default_face_height_and_width(window, &defheight, &defwidth);
4020 char_width = (avail_width / defwidth);
4022 /* It's the calling function's responsibility to check these values
4023 and make sure they're not out of range.
4025 #### We need to go through the calling functions and actually
4027 return max(0, char_width);
4031 window_char_width_to_pixel_width(struct window *w, int char_width,
4032 int include_margins_p)
4036 int defheight, defwidth;
4039 XSETWINDOW(window, w);
4041 default_face_height_and_width(window, &defheight, &defwidth);
4043 avail_width = char_width * defwidth;
4044 pixel_width = (avail_width +
4045 window_left_window_gutter_width(w, 0) +
4046 window_right_window_gutter_width(w, 0) +
4047 (include_margins_p ? 0 : window_left_margin_width(w)) +
4048 (include_margins_p ? 0 : window_right_margin_width(w)));
4050 /* It's the calling function's responsibility to check these values
4051 and make sure they're not out of range.
4053 #### We need to go through the calling functions and actually
4055 return max(0, pixel_width);
4058 /* This returns the usable space which doesn't include space needed by
4059 scrollbars or divider lines. */
4060 int window_char_width(struct window *w, int include_margins_p)
4062 return window_pixel_width_to_char_width(w, WINDOW_WIDTH(w),
4066 #define MINSIZE(w) \
4068 ? window_min_width * defwidth \
4069 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4072 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4074 #define CURSIZE(w) \
4075 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4077 #define CURCHARSIZE(w) \
4078 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4080 #define MINCHARSIZE(window) \
4081 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4082 ? 1 : window_min_height)
4084 static int window_pixheight(Lisp_Object w)
4086 return window_pixel_height(XWINDOW(w));
4089 /* Unlike set_window_pixheight, this function
4090 also changes the heights of the siblings so as to
4091 keep everything consistent. */
4094 change_window_height(Lisp_Object window, int delta, Lisp_Object horizontalp,
4097 struct window *win = decode_window(window);
4098 int widthflag = !NILP(horizontalp);
4103 int (*sizefun) (Lisp_Object) = (widthflag
4104 ? window_pixel_width
4105 : window_pixheight);
4106 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4107 ? set_window_pixwidth
4108 : set_window_pixheight);
4110 int defheight, defwidth;
4115 check_min_window_sizes();
4117 XSETWINDOW(window, win);
4118 f = XFRAME(win->frame);
4119 if (EQ(window, FRAME_ROOT_WINDOW(f)))
4120 error("Won't change only window");
4122 /* #### This is very likely incorrect and instead the char_to_pixel_
4123 functions should be called. */
4124 default_face_height_and_width(window, &defheight, &defwidth);
4127 w = XWINDOW(window);
4132 sizep = &CURSIZE (w);
4133 dim = CURCHARSIZE (w);
4134 new_pixsize = inpixels?(*sizep + delta):(dim+delta);
4135 set_window_pixsize (window, new_pixsize, 0, 0);
4140 if (widthflag ? !NILP(XWINDOW(parent)->hchild)
4141 : !NILP(XWINDOW(parent)->vchild))
4146 sizep = &CURSIZE(w);
4147 dim = CURCHARSIZE(w);
4149 if ((inpixels && (*sizep + delta) < MINSIZE(window)) ||
4150 (!inpixels && (dim + delta) < MINCHARSIZE(window))) {
4151 if (MINI_WINDOW_P(XWINDOW(window)))
4153 else if (!NILP(parent)) {
4154 Fdelete_window(window, Qnil);
4160 delta *= (widthflag ? defwidth : defheight);
4165 maxdelta = ((!NILP(parent))
4166 ? (*sizefun) (parent) - *sizep : ((!NILP(w->next))
4176 /* This is a frame with only one window,
4177 a minibuffer-only or a minibufferless frame. */
4181 if (delta > maxdelta)
4182 /* This case traps trying to make the minibuffer
4183 the full frame, or make the only window aside from the
4184 minibuffer the full frame. */
4191 /* #### Chuck: is this correct? */
4192 if (*sizep + delta < MINSIZE(window)) {
4193 Fdelete_window(window);
4199 if (!NILP(w->next) &&
4200 (*sizefun) (w->next) - delta >= (int)MINSIZE(w->next)) {
4201 CURBEG(XWINDOW(w->next)) += delta;
4202 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4203 (*setsizefun) (window, *sizep + delta, 0);
4204 } else if (!NILP(w->prev) &&
4205 (*sizefun) (w->prev) - delta >= (int)MINSIZE(w->prev)) {
4206 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4208 (*setsizefun) (window, *sizep + delta, 0);
4211 int opht = (*sizefun) (parent);
4213 /* If trying to grow this window to or beyond size of the parent,
4214 make delta1 so big that, on shrinking back down,
4215 all the siblings end up with less than one line and are deleted. */
4216 if (opht <= *sizep + delta)
4217 delta1 = opht * opht * 2;
4218 /* Otherwise, make delta1 just right so that if we add delta1
4219 lines to this window and to the parent, and then shrink
4220 the parent back to its original size, the new proportional
4221 size of this window will increase by delta. */
4224 (delta * opht * 100) / ((opht - *sizep - delta) *
4227 /* Add delta1 lines or columns to this window, and to the parent,
4228 keeping things consistent while not affecting siblings. */
4229 CURSIZE(XWINDOW(parent)) = opht + delta1;
4230 (*setsizefun) (window, *sizep + delta1, 0);
4232 /* Squeeze out delta1 lines or columns from our parent,
4233 shrinking this window and siblings proportionately.
4234 This brings parent back to correct size.
4235 Delta1 was calculated so this makes this window the desired size,
4236 taking it all out of the siblings. */
4237 (*setsizefun) (parent, opht, 0);
4240 SET_LAST_MODIFIED(w, 0);
4241 SET_LAST_FACECHANGE(w);
4242 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
4243 /* overkill maybe, but better to be correct */
4244 MARK_FRAME_GUTTERS_CHANGED(f);
4246 run_window_configuration_hook( window );
4255 /* Scroll contents of window WINDOW up COUNT lines.
4256 If COUNT < (top line height / average line height) then we just adjust
4259 window_scroll(Lisp_Object window, Lisp_Object count, int direction,
4260 Error_behavior errb)
4262 struct window *w = XWINDOW(window);
4263 struct buffer *b = XBUFFER(w->buffer);
4264 int selected = EQ(window, Fselected_window(Qnil));
4266 Lisp_Object point, tem;
4267 display_line_dynarr *dla;
4268 int fheight, fwidth, modeline = 0;
4269 struct display_line *dl;
4272 point = make_int(BUF_PT(b));
4274 Bufpos pos = marker_position(w->pointm[CURRENT_DISP]);
4276 if (pos < BUF_BEGV(b))
4278 else if (pos > BUF_ZV(b))
4281 point = make_int(pos);
4284 /* Always set force_start so that redisplay_window will run
4285 the window-scroll-functions. */
4288 /* #### When the fuck does this happen? I'm so glad that history has
4289 completely documented the behavior of the scrolling functions under
4290 all circumstances. */
4291 tem = Fpos_visible_in_window_p(point, window);
4293 Fvertical_motion(make_int(-window_char_height(w, 0) / 2),
4295 Fset_marker(w->start[CURRENT_DISP], point, w->buffer);
4296 w->start_at_line_beg = beginning_of_line_p(b, XINT(point));
4297 WINDOW_TEXT_TOP_CLIP(w) = 0;
4298 MARK_WINDOWS_CHANGED(w);
4302 if (EQ(count, Qminus))
4305 count = Fprefix_numeric_value(count);
4306 value = XINT(count) * direction;
4309 return; /* someone just made a pointless call */
4313 /* If the user didn't specify how far to scroll then we have to figure it
4314 out by ourselves. */
4315 if (NILP(count) || EQ(count, Qminus)) {
4316 /* Going forwards is easy. If that is what we are doing then just
4317 set value and the section which handles the user specifying a
4318 positive value will work. */
4319 if (direction == 1) {
4321 window_displayed_height(w) -
4322 next_screen_context_lines;
4323 value = (value < 1 ? 1 : value);
4326 /* Going backwards is hard. We can't use the same loop used if the
4327 user specified a negative value because we care about
4328 next_screen_context_lines. In a variable height world you don't
4329 know how many lines above you can actually be displayed and still
4330 have the context lines appear. So we leave value set to 0 and add
4331 a separate section to deal with this. */
4335 if (direction == 1 && !value) {
4339 /* Determine parameters to test for partial line scrolling with. */
4340 dla = window_display_lines(w, CURRENT_DISP);
4342 if (INTP(Vwindow_pixel_scroll_increment))
4343 fheight = XINT(Vwindow_pixel_scroll_increment);
4344 else if (!NILP(Vwindow_pixel_scroll_increment))
4345 default_face_height_and_width(window, &fheight, &fwidth);
4347 if (Dynarr_length(dla) >= 1)
4348 modeline = Dynarr_atp(dla, 0)->modeline;
4350 dl = Dynarr_atp(dla, modeline);
4353 /* Go for partial display line scrolling. This just means bumping
4354 the clip by a reasonable amount and redisplaying, everything else
4355 remains unchanged. */
4356 if (!NILP(Vwindow_pixel_scroll_increment)
4357 && Dynarr_length(dla) >= (1 + modeline)
4358 && (dl->ascent - dl->top_clip) > fheight * value) {
4359 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4360 MARK_WINDOWS_CHANGED(w);
4363 Bufpos startp, old_start;
4365 if (WINDOW_TEXT_TOP_CLIP(w)) {
4366 WINDOW_TEXT_TOP_CLIP(w) = 0;
4367 MARK_WINDOWS_CHANGED(w);
4370 old_start = marker_position(w->start[CURRENT_DISP]);
4371 startp = vmotion(w, old_start, value, &vtarget);
4373 if (vtarget < value &&
4374 (w->window_end_pos[CURRENT_DISP] == -1
4375 || (BUF_Z(b) - w->window_end_pos[CURRENT_DISP] >
4377 maybe_signal_error(Qend_of_buffer, Qnil,
4381 set_marker_restricted(w->start[CURRENT_DISP],
4385 w->start_at_line_beg =
4386 beginning_of_line_p(b, startp);
4387 MARK_WINDOWS_CHANGED(w);
4389 if (!point_would_be_visible
4390 (w, startp, XINT(point))) {
4392 BUF_SET_PT(b, startp);
4394 set_marker_restricted(w->
4404 } else if (value < 0) {
4405 /* Go for partial display line scrolling. This just means bumping
4406 the clip by a reasonable amount and redisplaying, everything else
4407 remains unchanged. */
4408 if (!NILP(Vwindow_pixel_scroll_increment)
4409 && Dynarr_length(dla) >= (1 + modeline)
4411 (dl->ascent - dl->top_clip) - fheight * value <
4412 (dl->ascent + dl->descent - dl->clip)
4413 && WINDOW_TEXT_TOP_CLIP(w) + value * fheight > 0) {
4414 WINDOW_TEXT_TOP_CLIP(w) += value * fheight;
4415 MARK_WINDOWS_CHANGED(w);
4418 Bufpos startp, old_start;
4420 if (WINDOW_TEXT_TOP_CLIP(w)) {
4421 WINDOW_TEXT_TOP_CLIP(w) = 0;
4422 MARK_WINDOWS_CHANGED(w);
4425 old_start = marker_position(w->start[CURRENT_DISP]);
4426 startp = vmotion(w, old_start, value, &vtarget);
4429 && marker_position(w->start[CURRENT_DISP]) ==
4431 maybe_signal_error(Qbeginning_of_buffer, Qnil,
4435 set_marker_restricted(w->start[CURRENT_DISP],
4439 w->start_at_line_beg =
4440 beginning_of_line_p(b, startp);
4441 MARK_WINDOWS_CHANGED(w);
4443 /* #### Scroll back by less than a line. This code was
4444 originally for scrolling over large pixmaps and it
4445 loses when a line being *exposed* at the top of the
4446 window is bigger than the current one. However, for
4447 pixel based scrolling in general we can guess that
4448 the line we are going to display is probably the same
4449 size as the one we are on. In that instance we can
4450 have a reasonable stab at a suitable top clip. Fixing
4451 this properly is hard (and probably slow) as we would
4452 have to call redisplay to figure out the exposed line
4454 if (!NILP(Vwindow_pixel_scroll_increment)
4455 && Dynarr_length(dla) >= (1 + modeline)
4456 && dl->ascent + fheight * value > 0) {
4457 WINDOW_TEXT_TOP_CLIP(w) =
4458 (dl->ascent + fheight * value);
4461 if (!point_would_be_visible
4462 (w, startp, XINT(point))) {
4465 if (MINI_WINDOW_P(w))
4469 start_of_last_line(w,
4473 BUF_SET_PT(b, new_point);
4475 set_marker_restricted(w->
4485 } else { /* value == 0 && direction == -1 */
4487 if (WINDOW_TEXT_TOP_CLIP(w)) {
4488 WINDOW_TEXT_TOP_CLIP(w) = 0;
4489 MARK_WINDOWS_CHANGED(w);
4491 if (marker_position(w->start[CURRENT_DISP]) == BUF_BEGV(b)) {
4492 maybe_signal_error(Qbeginning_of_buffer, Qnil, Qwindow,
4497 int movement = next_screen_context_lines - 1;
4499 marker_position(w->start[CURRENT_DISP]);
4501 vmotion(w, old_startp, movement, &vtarget);
4503 start_with_point_on_display_line(w, bottom,
4507 if (startp >= old_startp)
4508 startp = vmotion(w, old_startp, -1, NULL);
4510 set_marker_restricted(w->start[CURRENT_DISP],
4511 make_int(startp), w->buffer);
4513 w->start_at_line_beg = beginning_of_line_p(b, startp);
4514 MARK_WINDOWS_CHANGED(w);
4516 if (!point_would_be_visible(w, startp, XINT(point))) {
4518 start_of_last_line(w, startp);
4521 BUF_SET_PT(b, new_point);
4523 set_marker_restricted(w->
4534 DEFUN("scroll-up", Fscroll_up, 0, 1, "_P", /*
4535 Scroll text of current window up COUNT lines; or near full screen if no arg.
4536 A near full screen is `next-screen-context-lines' less than a full screen.
4537 Negative COUNT means scroll downward.
4538 When calling from a program, supply an integer as argument or nil.
4539 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4540 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4543 The characters that are moved over may be added to the current selection
4544 \(i.e. active region) if the Shift key is held down, a motion key is used
4545 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4546 the documentation for this variable for more details.
4550 window_scroll(Fselected_window(Qnil), count, 1, ERROR_ME);
4554 DEFUN("scroll-down", Fscroll_down, 0, 1, "_P", /*
4555 Scroll text of current window down COUNT lines; or near full screen if no arg.
4556 A near full screen is `next-screen-context-lines' less than a full screen.
4557 Negative COUNT means scroll upward.
4558 When calling from a program, supply a number as argument or nil.
4559 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4560 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4563 The characters that are moved over may be added to the current selection
4564 \(i.e. active region) if the Shift key is held down, a motion key is used
4565 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4566 the documentation for this variable for more details.
4570 window_scroll(Fselected_window(Qnil), count, -1, ERROR_ME);
4574 DEFUN("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4575 Return the other window for "other window scroll" commands.
4576 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4577 specifies the window.
4578 If `other-window-scroll-buffer' is non-nil, a window
4579 showing that buffer is used.
4584 Lisp_Object selected_window = Fselected_window(Qnil);
4586 if (MINI_WINDOW_P(XWINDOW(selected_window))
4587 && !NILP(Vminibuffer_scroll_window))
4588 window = Vminibuffer_scroll_window;
4589 /* If buffer is specified, scroll that buffer. */
4590 else if (!NILP(Vother_window_scroll_buffer)) {
4592 Fget_buffer_window(Vother_window_scroll_buffer, Qnil, Qnil);
4595 display_buffer(Vother_window_scroll_buffer, Qt,
4598 /* Nothing specified; look for a neighboring window on the same
4600 window = Fnext_window(selected_window, Qnil, Qnil, Qnil);
4602 if (EQ(window, selected_window))
4603 /* That didn't get us anywhere; look for a window on another
4606 window = Fnext_window(window, Qnil, Qt, Qnil);
4607 while (!FRAME_VISIBLE_P
4608 (XFRAME(WINDOW_FRAME(XWINDOW(window))))
4609 && !EQ(window, selected_window));
4612 CHECK_LIVE_WINDOW(window);
4614 if (EQ(window, selected_window))
4615 error("There is no other window");
4620 DEFUN("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4621 Scroll next window upward COUNT lines; or near full frame if no arg.
4622 The next window is the one below the current one; or the one at the top
4623 if the current one is at the bottom. Negative COUNT means scroll downward.
4624 When calling from a program, supply a number as argument or nil.
4626 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4627 specifies the window to scroll.
4628 If `other-window-scroll-buffer' is non-nil, scroll the window
4629 showing that buffer, popping the buffer up if necessary.
4633 window_scroll(Fother_window_for_scrolling(), count, 1, ERROR_ME);
4637 DEFUN("scroll-left", Fscroll_left, 0, 1, "_P", /*
4638 Scroll selected window display COUNT columns left.
4639 Default for COUNT is window width minus 2.
4641 The characters that are moved over may be added to the current selection
4642 \(i.e. active region) if the Shift key is held down, a motion key is used
4643 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4644 the documentation for this variable for more details.
4648 Lisp_Object window = Fselected_window(Qnil);
4649 struct window *w = XWINDOW(window);
4650 int n = (NILP(count) ?
4651 window_char_width(w, 0) - 2 :
4652 XINT(Fprefix_numeric_value(count)));
4654 return Fset_window_hscroll(window, make_int(w->hscroll + n));
4657 DEFUN("scroll-right", Fscroll_right, 0, 1, "_P", /*
4658 Scroll selected window display COUNT columns right.
4659 Default for COUNT is window width minus 2.
4661 The characters that are moved over may be added to the current selection
4662 \(i.e. active region) if the Shift key is held down, a motion key is used
4663 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4664 the documentation for this variable for more details.
4668 Lisp_Object window = Fselected_window(Qnil);
4669 struct window *w = XWINDOW(window);
4670 int n = (NILP(count) ?
4671 window_char_width(w, 0) - 2 :
4672 XINT(Fprefix_numeric_value(count)));
4674 return Fset_window_hscroll(window, make_int(w->hscroll - n));
4677 DEFUN("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4678 Center point in WINDOW. With N, put point on line N.
4679 The desired position of point is always relative to the window.
4680 If WINDOW is nil, the selected window is used.
4684 struct window *w = decode_window(window);
4685 struct buffer *b = XBUFFER(w->buffer);
4686 Bufpos opoint = BUF_PT(b);
4691 start_with_line_at_pixpos(w, opoint, window_half_pixpos(w));
4693 n = Fprefix_numeric_value(n);
4695 startp = start_with_point_on_display_line(w, opoint, XINT(n));
4698 Fset_marker(w->start[CURRENT_DISP], make_int(startp), w->buffer);
4700 w->start_at_line_beg = beginning_of_line_p(b, startp);
4702 MARK_WINDOWS_CHANGED(w);
4706 DEFUN("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4707 Position point relative to WINDOW.
4708 With no argument, position text at center of window.
4709 An argument specifies window line; zero means top of window,
4710 negative means relative to bottom of window.
4711 If WINDOW is nil, the selected window is used.
4718 Bufpos start, new_point;
4721 /* Don't use decode_window() because we need the new value of
4724 window = Fselected_window(Qnil);
4726 CHECK_LIVE_WINDOW(window);
4727 w = XWINDOW(window);
4728 b = XBUFFER(w->buffer);
4730 height = window_displayed_height(w);
4731 selected = EQ(window, Fselected_window(w->frame));
4736 if (XINT(w->last_modified[CURRENT_DISP]) >= BUF_MODIFF(b)
4737 && XINT(w->last_facechange[CURRENT_DISP]) >=
4738 BUF_FACECHANGE(b)) {
4739 new_point = point_at_center(w, CURRENT_DISP, 0, 0);
4742 BUF_SET_PT(b, new_point);
4744 Fset_window_point(window, make_int(new_point));
4746 retval = line_at_center(w, CURRENT_DISP, 0, 0);
4748 start = marker_position(w->start[CURRENT_DISP]);
4749 if (start < BUF_BEGV(b))
4750 start = BUF_BEGV(b);
4751 else if (start > BUF_ZV(b))
4755 new_point = BUF_PT(b);
4758 marker_position(w->pointm[CURRENT_DISP]);
4761 point_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4764 BUF_SET_PT(b, new_point);
4766 Fset_window_point(window, make_int(new_point));
4769 line_at_center(w, CMOTION_DISP, start, BUF_PT(b));
4772 return make_int(retval);
4774 /* #### Is this going to work right when at eob? */
4775 arg = Fprefix_numeric_value(arg);
4777 XSETINT(arg, XINT(arg) + height);
4780 start = marker_position(w->start[CURRENT_DISP]);
4781 if (start < BUF_BEGV(b) || start > BUF_ZV(b)) {
4783 new_point = BUF_PT(b);
4785 new_point = marker_position(w->pointm[CURRENT_DISP]);
4787 new_point = vmotion(XWINDOW(window), new_point, -height / 2, 0);
4790 BUF_SET_PT(b, new_point);
4792 Fset_window_point(window, make_int(new_point));
4794 Fset_marker(w->start[CURRENT_DISP], make_int(new_point),
4796 w->start_at_line_beg = beginning_of_line_p(b, new_point);
4800 BUF_SET_PT(b, start);
4802 Fset_window_point(window, make_int(start));
4806 return Fvertical_motion(arg, window, Qnil);
4809 new_point = vmotion(XWINDOW(window),
4810 marker_position(w->pointm[CURRENT_DISP]),
4812 Fset_window_point(window, make_int(new_point));
4813 return make_int(vpos);
4818 map_windows_1(Lisp_Object window,
4819 int (*mapfun) (struct window * w, void *closure), void *closure)
4821 for (; !NILP(window); window = XWINDOW(window)->next) {
4823 struct window *w = XWINDOW(window);
4825 if (!NILP(w->vchild))
4826 retval = map_windows_1(w->vchild, mapfun, closure);
4827 else if (!NILP(w->hchild))
4828 retval = map_windows_1(w->hchild, mapfun, closure);
4830 retval = (mapfun) (w, closure);
4839 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4840 invocation of MAPFUN. If any invocation of MAPFUN returns
4841 non-zero, the mapping is halted. Otherwise, map_windows() maps
4842 over all windows in F.
4844 If MAPFUN creates or deletes windows, the behavior is undefined. */
4847 map_windows(struct frame *f, int (*mapfun) (struct window * w, void *closure),
4851 return map_windows_1(FRAME_ROOT_WINDOW(f), mapfun, closure);
4853 Lisp_Object frmcons, devcons, concons;
4855 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
4857 map_windows_1(FRAME_ROOT_WINDOW
4858 (XFRAME(XCAR(frmcons))),
4869 modeline_shadow_thickness_changed(Lisp_Object specifier, struct window *w,
4872 w->shadow_thickness_changed = 1;
4873 MARK_WINDOWS_CHANGED(w);
4877 vertical_divider_changed_in_window(Lisp_Object specifier,
4878 struct window *w, Lisp_Object oldval)
4880 MARK_WINDOWS_CHANGED(w);
4881 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(XFRAME(WINDOW_FRAME(w)));
4884 /* also used in scrollbar.c */
4886 some_window_value_changed(Lisp_Object specifier, struct window *w,
4889 MARK_WINDOWS_CHANGED(w);
4892 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
4894 struct window_stats {
4897 #ifdef HAVE_SCROLLBARS
4901 int other_redisplay;
4906 compute_window_mirror_usage(struct window_mirror *mir,
4907 struct window_stats *stats,
4908 struct overhead_stats *ovstats)
4912 stats->other += malloced_storage_size(mir, sizeof(struct window_mirror),
4914 #ifdef HAVE_SCROLLBARS
4916 struct device *d = XDEVICE(FRAME_DEVICE(mir->frame));
4919 compute_scrollbar_instance_usage(d,
4921 scrollbar_vertical_instance,
4924 compute_scrollbar_instance_usage(d,
4926 scrollbar_horizontal_instance,
4929 #endif /* HAVE_SCROLLBARS */
4930 stats->other_redisplay +=
4931 compute_display_line_dynarr_usage(mir->current_display_lines,
4933 stats->other_redisplay +=
4934 compute_display_line_dynarr_usage(mir->desired_display_lines,
4939 compute_window_usage(struct window *w, struct window_stats *stats,
4940 struct overhead_stats *ovstats)
4944 malloced_storage_size(w, sizeof(struct window), ovstats);
4945 stats->face += compute_face_cachel_usage(w->face_cachels, ovstats);
4946 stats->glyph += compute_glyph_cachel_usage(w->glyph_cachels, ovstats);
4947 stats->line_start +=
4948 compute_line_start_cache_dynarr_usage(w->line_start_cache, ovstats);
4949 compute_window_mirror_usage(find_window_mirror(w), stats, ovstats);
4952 DEFUN("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4953 Return stats about the memory usage of window WINDOW.
4954 The values returned are in the form of an alist of usage types and byte
4955 counts. The byte counts attempt to encompass all the memory used
4956 by the window (separate from the memory logically associated with a
4957 buffer or frame), including internal structures and any malloc()
4958 overhead associated with them. In practice, the byte counts are
4959 underestimated because certain memory usage is very hard to determine
4960 \(e.g. the amount of memory used inside the Xt library or inside the
4961 X server) and because there is other stuff that might logically
4962 be associated with a window, buffer, or frame (e.g. window configurations,
4963 glyphs) but should not obviously be included in the usage counts.
4965 Multiple slices of the total memory usage may be returned, separated
4966 by a nil. Each slice represents a particular view of the memory, a
4967 particular way of partitioning it into groups. Within a slice, there
4968 is no overlap between the groups of memory, and each slice collectively
4969 represents all the memory concerned.
4973 struct window_stats stats;
4974 struct overhead_stats ovstats;
4975 Lisp_Object val = Qnil;
4977 CHECK_WINDOW(window); /* dead windows should be allowed, no? */
4979 compute_window_usage(XWINDOW(window), &stats, &ovstats);
4981 val = acons(Qface_cache, make_int(stats.face), val);
4982 val = acons(Qglyph_cache, make_int(stats.glyph), val);
4983 #ifdef HAVE_SCROLLBARS
4984 val = acons(Qscrollbar_instances, make_int(stats.scrollbar), val);
4986 val = acons(Qline_start_cache, make_int(stats.line_start), val);
4987 val = acons(Qother_redisplay, make_int(stats.other_redisplay), val);
4988 val = acons(Qother, make_int(stats.other), val);
4989 val = Fcons(Qnil, val);
4990 val = acons(Qactually_requested, make_int(ovstats.was_requested), val);
4991 val = acons(Qmalloc_overhead, make_int(ovstats.malloc_overhead), val);
4992 val = acons(Qdynarr_overhead, make_int(ovstats.dynarr_overhead), val);
4994 return Fnreverse(val);
4997 #endif /* MEMORY_USAGE_STATS */
4999 /************************************************************************/
5000 /* Window configurations */
5001 /************************************************************************/
5003 /* #### This window configuration stuff has had serious bugs lurking in it
5004 for years; it would be a -huge- win if this was reimplemented in lisp.
5007 /* If you add anything to this structure make sure saved_window_equal
5009 struct saved_window {
5010 Lisp_Object window; /* window */
5011 Lisp_Object buffer; /* buffer */
5012 Lisp_Object start; /* copied marker */
5013 Lisp_Object pointm; /* copied marker */
5014 Lisp_Object sb_point; /* copied marker */
5015 Lisp_Object mark; /* copied marker */
5021 Charcount modeline_hscroll;
5022 int parent_index; /* index into saved_windows */
5023 int prev_index; /* index into saved_windows */
5024 char start_at_line_beg; /* boolean */
5026 #define WINDOW_SLOT_DECLARATION
5027 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5028 #include "winslots.h"
5031 /* If you add anything to this structure make sure window_config_equal
5033 struct window_config {
5034 struct lcrecord_header header;
5035 /* int frame_width; No longer needed, JV
5036 int frame_height; */
5038 Lisp_Object selected_frame;
5040 Lisp_Object current_window;
5041 Lisp_Object current_buffer;
5042 Lisp_Object minibuffer_scroll_window;
5043 Lisp_Object root_window;
5044 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5045 /* Record the values of window-min-width and window-min-height
5046 so that window sizes remain consistent with them. */
5047 int min_width, min_height;
5048 unsigned int saved_windows_count;
5049 /* Zero-sized arrays aren't ANSI C */
5050 struct saved_window saved_windows[1];
5053 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5054 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5055 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5056 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5057 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5059 static Lisp_Object mark_window_config(Lisp_Object obj)
5061 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5063 mark_object(config->current_window);
5064 mark_object(config->current_buffer);
5065 mark_object(config->minibuffer_scroll_window);
5066 mark_object(config->root_window);
5068 for (i = 0; i < config->saved_windows_count; i++) {
5069 struct saved_window *s = SAVED_WINDOW_N(config, i);
5070 mark_object(s->window);
5071 mark_object(s->buffer);
5072 mark_object(s->start);
5073 mark_object(s->pointm);
5074 mark_object(s->sb_point);
5075 mark_object(s->mark);
5077 /* #### This looked like this. I do not see why specifier cached
5078 values should not be marked, as such specifiers as toolbars
5079 might have GC-able instances. Freed configs are not marked,
5080 aren't they? -- kkm */
5081 mark_object(s->dedicated);
5083 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5084 #include "winslots.h"
5090 inline static size_t sizeof_window_config_for_n_windows(unsigned int n)
5092 return FLEXIBLE_ARRAY_STRUCT_SIZEOF(struct window_config,
5093 struct saved_window, saved_windows,
5097 static size_t sizeof_window_config(const void *h)
5099 const struct window_config *c = (const struct window_config *)h;
5100 return sizeof_window_config_for_n_windows(c->saved_windows_count);
5104 print_window_config(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5106 struct window_config *config = XWINDOW_CONFIGURATION(obj);
5108 error("printing unreadable object #<window-configuration 0x%x>",
5109 config->header.uid);
5110 write_fmt_str(printcharfun, "#<window-configuration 0x%x>", config->header.uid);
5113 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("window-configuration",
5114 window_configuration,
5116 print_window_config,
5117 0, 0, 0, 0, sizeof_window_config,
5118 struct window_config);
5120 /* Returns a boolean indicating whether the two saved windows are
5123 saved_window_equal(struct saved_window *win1, struct saved_window *win2)
5125 #define WINDOW_SLOT(slot, compare) \
5126 if (!compare (win1->slot, win2->slot)) \
5128 #include "winslots.h"
5131 EQ(win1->window, win2->window) &&
5132 EQ(win1->buffer, win2->buffer) &&
5133 internal_equal(win1->start, win2->start, 0) &&
5134 internal_equal(win1->pointm, win2->pointm, 0) &&
5135 internal_equal(win1->sb_point, win2->sb_point, 0) &&
5136 internal_equal(win1->mark, win2->mark, 0) &&
5137 win1->pixel_left == win2->pixel_left &&
5138 win1->pixel_top == win2->pixel_top &&
5139 win1->pixel_width == win2->pixel_width &&
5140 win1->pixel_height == win2->pixel_height &&
5141 win1->hscroll == win2->hscroll &&
5142 win1->modeline_hscroll == win2->modeline_hscroll &&
5143 win1->parent_index == win2->parent_index &&
5144 win1->prev_index == win2->prev_index &&
5145 win1->start_at_line_beg == win2->start_at_line_beg;
5148 /* Returns a boolean indicating whether the two given configurations
5150 static int window_config_equal(Lisp_Object conf1, Lisp_Object conf2)
5152 struct window_config *fig1, *fig2;
5155 /* First check if they are truly the same. */
5156 if (EQ(conf1, conf2))
5159 fig1 = XWINDOW_CONFIGURATION(conf1);
5160 fig2 = XWINDOW_CONFIGURATION(conf2);
5162 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5163 EQ(fig1->current_window, fig2->current_window) &&
5164 EQ(fig1->current_buffer, fig2->current_buffer) &&
5165 EQ(fig1->root_window, fig2->root_window) &&
5166 EQ(fig1->minibuffer_scroll_window,
5167 fig2->minibuffer_scroll_window)))
5169 fig1->frame_width == fig2->frame_width &&
5170 fig1->frame_height == fig2->frame_height)) */
5173 for (i = 0; i < fig1->saved_windows_count; i++) {
5174 if (!saved_window_equal(SAVED_WINDOW_N(fig1, i),
5175 SAVED_WINDOW_N(fig2, i)))
5182 DEFUN("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5183 Return t if OBJECT is a window-configuration object.
5187 return WINDOW_CONFIGURATIONP(object) ? Qt : Qnil;
5190 static int mark_windows_in_use_closure(struct window *w, void *closure)
5192 int mark = *(int *)closure;
5193 w->config_mark = mark;
5197 static void mark_windows_in_use(struct frame *f, int mark)
5199 map_windows(f, mark_windows_in_use_closure, &mark);
5202 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5203 static Lisp_Object free_window_configuration(Lisp_Object window_config)
5206 struct window_config *config = XWINDOW_CONFIGURATION(window_config);
5208 /* Free all the markers. It's not completely necessary that
5209 we do this (window configs sitting in a free list aren't
5210 marked normally so the markers wouldn't be marked anyway)
5211 but it's more efficient. */
5212 for (i = 0; i < config->saved_windows_count; i++) {
5213 struct saved_window *p = SAVED_WINDOW_N(config, i);
5215 if (!NILP(p->pointm)) {
5216 free_marker(XMARKER(p->pointm));
5219 if (!NILP(p->start)) {
5220 free_marker(XMARKER(p->start));
5223 if (!NILP(p->sb_point)) {
5224 free_marker(XMARKER(p->sb_point));
5227 if (!NILP(p->mark)) {
5228 free_marker(XMARKER(p->mark));
5233 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5234 xfree(window_config);
5237 if (config->saved_windows_count <=
5238 countof(Vwindow_configuration_free_list)) {
5239 free_managed_lcrecord(Vwindow_configuration_free_list
5240 [config->saved_windows_count - 1],
5247 DEFUN("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5248 Set the configuration of windows and buffers as specified by CONFIGURATION.
5249 CONFIGURATION must be a value previously returned
5250 by `current-window-configuration' (which see).
5255 struct window_config *config;
5256 struct saved_window *p;
5257 Lisp_Object new_current_buffer;
5261 struct gcpro gcpro1;
5262 Lisp_Object old_window_config;
5263 /* int previous_frame_height;
5264 int previous_frame_width; */
5265 int previous_pixel_top;
5266 int previous_pixel_height;
5267 int previous_pixel_left;
5268 int previous_pixel_width;
5269 int previous_minibuf_height, previous_minibuf_top,
5270 previous_minibuf_width;
5271 int real_font_height;
5272 int converted_minibuf_height, target_minibuf_height;
5273 int specpdl_count = specpdl_depth();
5275 GCPRO1(configuration);
5277 CHECK_WINDOW_CONFIGURATION(configuration);
5278 config = XWINDOW_CONFIGURATION(configuration);
5280 frame = XWINDOW(SAVED_WINDOW_N(config, 0)->window)->frame;
5283 /* Do not signal an error here if the frame was deleted. There are
5284 reasonable cases where we could get here with a deleted frame and
5285 just want to do close to nothing instead. */
5287 if (FRAME_LIVE_P(f)) {
5288 /* restore the frame characteristics */
5290 new_current_buffer = config->current_buffer;
5291 if (!BUFFER_LIVE_P(XBUFFER(new_current_buffer)))
5292 new_current_buffer = Qnil;
5295 * Assumed precondition: w->config_mark = 0 for all w
5296 * This procedure should ensure this is true by the time it exits
5297 * to ensure the precondition for future calls.
5299 * We use w->config_mark to know whether we're modifying a
5300 * window that is currently visible on the frame (#### we
5301 * should just be able to check whether the window is dead
5302 * or not, but this way is safer?). As we process each
5303 * window, we set its config_mark to 0. At the end, we
5304 * go through all the windows that used to be on the frame,
5305 * set each one's config_mark to 0 (to maintain the
5306 * assumed precondition) and delete each one that's no
5309 * #### Using a window-configuration to keep track of
5310 * the current windows is wasteful. All we need is the
5311 * list of windows, so we could just use a dynarr.
5313 old_window_config = Fcurrent_window_configuration(frame);
5315 /* If the new configuration is already equal to the old, then stop
5316 right here. This saves the work below and it also saves
5317 triggering a full redisplay of this window. This is a huge win
5318 when using the mouse since the mode motion code uses
5319 save-window-excursion extensively but will rarely cause the
5320 configuration to actually change. */
5321 if (window_config_equal(configuration, old_window_config)) {
5322 free_window_configuration(old_window_config);
5327 /* We can't quit or even check for quit because that may cause
5328 investigation of the frame state, which may crash if the frame is
5329 in an inconsistent state. */
5330 begin_dont_check_for_quit();
5331 record_unwind_protect(free_window_configuration,
5334 mark_windows_in_use(f, 1);
5335 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5336 /* Force subwindows to be remapped. This is overkill but saves
5337 us having to rely on the redisplay code to unmap any extant
5340 #### It does cause some extra flashing though which we could
5341 possibly avoid. So consider trying to get redisplay to work
5344 Removing the instances from the frame cache is wrong because
5345 an instance is only put in the frame cache when it is
5346 instantiated. So if we do this there is a chance that stuff
5347 will never get put back in the frame cache. */
5348 reset_frame_subwindow_instance_cache(f);
5351 /* JV: This is bogus,
5352 First of all, the units are inconsistent. The frame sizes are measured
5353 in characters but the window sizes are stored in pixels. So if a
5354 font size change happened between saving and restoring, the
5355 frame "sizes" maybe equal but the windows still should be
5356 resized. This is tickled a lot by the new "character size
5357 stays constant" policy in 21.0. It leads to very weird
5358 glitches (and possibly crashes when asserts are tickled).
5360 Just changing the units doesn't help because changing the
5361 toolbar configuration can also change the pixel positions.
5362 Luckily there is a much simpler way of doing this, see below.
5364 previous_frame_width = FRAME_WIDTH(f);
5365 previous_frame_height = FRAME_HEIGHT(f);
5366 /* If the frame has been resized since this window configuration was
5367 made, we change the frame to the size specified in the
5368 configuration, restore the configuration, and then resize it
5369 back. We keep track of the prevailing height in these variables. */
5370 if (config->frame_height != FRAME_HEIGHT(f)
5371 || config->frame_width != FRAME_WIDTH(f))
5372 change_frame_size(f, config->frame_height,
5373 config->frame_width, 0);
5376 previous_pixel_top = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top;
5377 previous_pixel_height =
5378 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_height;
5379 previous_pixel_left = XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left;
5380 previous_pixel_width =
5381 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_width;
5383 /* remember some properties of the minibuffer */
5385 default_face_height_and_width(frame, &real_font_height, 0);
5386 assert(real_font_height > 0);
5388 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f)) {
5389 previous_minibuf_height
5390 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5391 previous_minibuf_top
5392 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5393 previous_minibuf_width
5394 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5396 previous_minibuf_height = 0;
5397 previous_minibuf_top = 0;
5398 previous_minibuf_width = 0;
5400 converted_minibuf_height = (previous_minibuf_height % real_font_height) == 0 ? -(previous_minibuf_height / real_font_height) : /* lines */
5401 previous_minibuf_height; /* pixels */
5403 /* Temporarily avoid any problems with windows that are smaller
5404 than they are supposed to be. */
5405 window_min_height = 1;
5406 window_min_width = 1;
5408 /* OK, now restore all the windows in the window config.
5409 This may involve "undeleting" windows, since the
5410 windows in the window config may be deleted.
5412 for (k = 0; k < config->saved_windows_count; k++) {
5413 p = SAVED_WINDOW_N(config, k);
5414 w = XWINDOW(p->window);
5417 /* The window might be dead. In this case, its redisplay
5418 structures were freed, so we need to reallocate them. */
5419 if (!w->face_cachels) {
5420 w->face_cachels = Dynarr_new(face_cachel);
5421 reset_face_cachels(w);
5423 if (!w->glyph_cachels)
5424 w->glyph_cachels = Dynarr_new(glyph_cachel);
5425 if (!w->line_start_cache)
5426 w->line_start_cache =
5427 Dynarr_new(line_start_cache);
5428 w->gutter_extent_modiff[0] = 0;
5429 w->gutter_extent_modiff[1] = 0;
5430 w->gutter_extent_modiff[2] = 0;
5431 w->gutter_extent_modiff[3] = 0;
5434 if (p->parent_index >= 0)
5436 SAVED_WINDOW_N(config,
5437 p->parent_index)->window;
5441 if (p->prev_index >= 0) {
5443 SAVED_WINDOW_N(config,
5444 p->prev_index)->window;
5446 /* This is true for a minibuffer-only frame. */
5447 if (!NILP(w->mini_p) && EQ(w->prev, p->window))
5450 XWINDOW(w->prev)->next = p->window;
5453 if (!NILP(w->parent)) {
5454 if (WINDOW_WIDTH(p) ==
5455 WINDOW_WIDTH(XWINDOW(w->parent))) {
5456 XWINDOW(w->parent)->vchild =
5458 XWINDOW(w->parent)->hchild =
5461 XWINDOW(w->parent)->hchild =
5463 XWINDOW(w->parent)->vchild =
5468 if (!w->config_mark) {
5469 /* #### This should be equivalent to the window previously
5470 having been dead. If we're brave, we'll put in an
5471 assertion to this effect. */
5472 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
5473 } else { /* if (!EQ (w->buffer, p->buffer)) */
5475 /* With the new redisplay we let it know that a change has
5476 been made and it will take care of the rest. If we don't
5477 tell it something has possibly changed it could lead to
5478 incorrect display. */
5479 MARK_WINDOWS_CHANGED(w);
5482 WINDOW_LEFT(w) = WINDOW_LEFT(p);
5483 WINDOW_TOP(w) = WINDOW_TOP(p);
5484 WINDOW_WIDTH(w) = WINDOW_WIDTH(p);
5485 WINDOW_HEIGHT(w) = WINDOW_HEIGHT(p);
5486 w->hscroll = p->hscroll;
5487 w->modeline_hscroll = p->modeline_hscroll;
5488 w->line_cache_last_updated = Qzero;
5489 /* When we restore a window's configuration, the identity of
5490 the window hasn't actually changed - so there is no
5491 reason why we shouldn't preserve the instance cache for
5492 it - unless it was originally deleted. This will often
5493 buy us something as we will not have to re-instantiate
5494 all the instances. This is because this is an instance
5495 cache - not a display cache. Preserving the display cache
5496 would definitely be wrong.
5498 We specifically want to do this for tabs, since for some
5499 reason finding a file will cause the configuration to be
5501 if (NILP(w->subwindow_instance_cache))
5502 w->subwindow_instance_cache =
5503 make_image_instance_cache_hash_table();
5505 SET_LAST_MODIFIED(w, 1);
5506 SET_LAST_FACECHANGE(w);
5509 /* #### Consider making the instance cache a winslot. */
5510 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5511 #include "winslots.h"
5513 /* Reinstall the saved buffer and pointers into it. */
5514 if (NILP(p->buffer))
5515 w->buffer = p->buffer;
5517 if (BUFFER_LIVE_P(XBUFFER(p->buffer)))
5518 /* If saved buffer is alive, install it. */
5520 w->buffer = p->buffer;
5521 w->start_at_line_beg =
5522 p->start_at_line_beg;
5523 set_marker_restricted(w->
5529 set_marker_restricted(w->
5535 set_marker_restricted(w->sb_point,
5539 Fset_marker(XBUFFER(w->buffer)->mark,
5540 Fmarker_position(p->mark),
5543 /* As documented in Fcurrent_window_configuration, don't
5544 save the location of point in the buffer which was current
5545 when the window configuration was recorded. */
5546 if (!EQ(p->buffer, new_current_buffer)
5547 && XBUFFER(p->buffer) ==
5550 pointm[CURRENT_DISP],
5552 } else if (NILP(w->buffer)
5554 !BUFFER_LIVE_P(XBUFFER(w->buffer)))
5555 /* Else if window's old buffer is dead too, get a live one. */
5557 /* #### The following line makes me nervous... */
5558 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist)); */
5560 Fget_buffer_create(QSscratch);
5561 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5562 /* This will set the markers to beginning of visible
5564 set_marker_restricted(w->
5568 set_marker_restricted(w->
5572 set_marker_restricted(w->sb_point,
5574 w->start_at_line_beg = 1;
5576 /* Keeping window's old buffer; make sure the markers
5579 /* Set window markers at start of visible range. */
5580 if (XMARKER(w->start[CURRENT_DISP])->
5582 set_marker_restricted(w->
5588 if (XMARKER(w->sb_point)->buffer == 0)
5589 set_marker_restricted(w->
5594 if (XMARKER(w->pointm[CURRENT_DISP])->
5596 set_marker_restricted(w->
5606 w->start_at_line_beg = 1;
5611 FRAME_ROOT_WINDOW(f) = config->root_window;
5612 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5613 then calls do_switch_frame() below to select the frame that was
5614 recorded in the window config as being selected.
5616 Instead, we don't ever change the selected frame, and either
5617 call Fselect_window() below if the window config's frame is
5618 currently selected, or just set the selected window of the
5619 window config's frame. */
5622 /* Set the frame height to the value it had before this function. */
5623 if (previous_frame_height != FRAME_HEIGHT(f)
5624 || previous_frame_width != FRAME_WIDTH(f))
5625 change_frame_size(f, previous_frame_height,
5626 previous_frame_width, 0);
5628 /* We just reset the size and position of the minibuffer, to its old
5629 value, which needn't be valid. So we do some magic to see which value
5630 to actually take. Then we set it.
5633 We take the old value if is in the same units but differs from the
5636 #### Now we get more cases correct then ever before, but
5637 are we treating all? For instance what if the frames minibuf window
5638 is no longer the same one?
5640 target_minibuf_height = previous_minibuf_height;
5641 if (converted_minibuf_height &&
5642 (converted_minibuf_height * config->minibuf_height) > 0 &&
5643 (converted_minibuf_height != config->minibuf_height)) {
5644 target_minibuf_height = config->minibuf_height < 0 ?
5645 -(config->minibuf_height * real_font_height) :
5646 config->minibuf_height;
5647 target_minibuf_height =
5648 max(target_minibuf_height, real_font_height);
5650 if (previous_minibuf_height) {
5651 XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top
5652 = previous_minibuf_top -
5653 (target_minibuf_height - previous_minibuf_height);
5654 set_window_pixheight(FRAME_MINIBUF_WINDOW(f),
5655 target_minibuf_height, 0);
5656 set_window_pixwidth(FRAME_MINIBUF_WINDOW(f),
5657 previous_minibuf_width, 0);
5660 /* This is a better way to deal with frame resizing, etc.
5661 What we _actually_ want is for the old (just restored)
5663 into the place of the new one. So we just do that. Simple! */
5664 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_top = previous_pixel_top;
5665 /* Note that this function also updates the subwindow
5667 set_window_pixheight(FRAME_ROOT_WINDOW(f),
5668 previous_pixel_height -
5669 (target_minibuf_height -
5670 previous_minibuf_height), 0);
5671 XWINDOW(FRAME_ROOT_WINDOW(f))->pixel_left = previous_pixel_left;
5672 /* Note that this function also updates the subwindow
5674 set_window_pixwidth(FRAME_ROOT_WINDOW(f), previous_pixel_width,
5677 /* If restoring in the current frame make the window current,
5678 otherwise just update the frame selected_window slot to be
5679 the restored current_window. */
5680 if (f == selected_frame()) {
5682 /* When using `pop-window-configuration', often the minibuffer
5683 ends up as the selected window even though it's not active ...
5684 I really don't know the cause of this, but it should never
5685 happen. This kludge should fix it.
5687 #### Find out why this is really going wrong. */
5688 if (!minibuf_level &&
5689 MINI_WINDOW_P(XWINDOW(config->current_window)))
5691 Fnext_window(config->current_window, Qnil,
5694 window_to_select = config->current_window;
5696 /* Do this last so that buffer stacking is calculated
5698 Fselect_window(config->current_window, Qnil);
5700 if (!NILP(new_current_buffer)) {
5701 Fset_buffer(new_current_buffer);
5702 Frecord_buffer(new_current_buffer);
5704 Fset_buffer(XWINDOW(config->current_window)->
5706 Frecord_buffer(XWINDOW(config->current_window)->
5710 set_frame_selected_window(f, config->current_window);
5712 old_window_config = Qnil; /* Warning suppression */
5714 /* Restore the minimum heights recorded in the configuration. */
5715 window_min_height = config->min_height;
5716 window_min_width = config->min_width;
5719 /* see above comment */
5720 /* Fselect_window will have made f the selected frame, so we
5721 reselect the proper frame here. Fhandle_switch_frame will change the
5722 selected window too, but that doesn't make the call to
5723 Fselect_window above totally superfluous; it still sets f's
5725 if (FRAME_LIVE_P(XFRAME(config->selected_frame)))
5726 do_switch_frame(config->selected_frame, Qnil, 0);
5729 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5731 if (FRAME_LIVE_P(f)) {
5732 /* Do this before calling recompute_all_cached_specifiers_in_window()
5733 so that things like redisplay_redraw_cursor() won't abort due
5734 to no window mirror present. */
5735 f->mirror_dirty = 1;
5737 config = XWINDOW_CONFIGURATION(old_window_config);
5738 for (k = 0; k < config->saved_windows_count; k++) {
5739 p = SAVED_WINDOW_N(config, k);
5740 w = XWINDOW(p->window);
5741 /* Remember, we set w->config_mark on all currently visible
5742 windows, and reset it on all newly visible windows.
5743 Any windows still marked need to be deleted. */
5744 if (w->config_mark) {
5745 mark_window_as_deleted(w);
5748 /* We just potentially changed the window's buffer and
5749 potentially turned a dead window into a live one,
5750 so we need to recompute the cached specifier values. */
5751 recompute_all_cached_specifiers_in_window(w);
5756 /* Now restore things, when everything else if OK. */
5758 unbind_to(specpdl_count, Qnil);
5765 /* Mark all subwindows of a window as deleted. The argument
5766 W is actually the subwindow tree of the window in question. */
5768 void delete_all_subwindows(struct window *w)
5771 delete_all_subwindows(XWINDOW(w->next));
5772 if (!NILP(w->vchild))
5773 delete_all_subwindows(XWINDOW(w->vchild));
5774 if (!NILP(w->hchild))
5775 delete_all_subwindows(XWINDOW(w->hchild));
5777 mark_window_as_deleted(w);
5780 static unsigned int count_windows(struct window *window)
5783 (!NILP(window->next) ? count_windows(XWINDOW(window->next)) : 0) +
5784 (!NILP(window->vchild) ? count_windows(XWINDOW(window->vchild)) : 0)
5786 (!NILP(window->hchild) ? count_windows(XWINDOW(window->hchild)) :
5791 saved_window_index(Lisp_Object window, struct window_config *config, int lim)
5794 for (j = 0; j < lim; j++) {
5795 if (EQ(SAVED_WINDOW_N(config, j)->window, window))
5799 return 0; /* suppress compiler warning */
5803 save_window_save(Lisp_Object window, struct window_config *config, int i)
5807 for (; !NILP(window); window = w->next) {
5808 struct saved_window *p = SAVED_WINDOW_N(config, i);
5810 w = XWINDOW(window);
5813 p->buffer = w->buffer;
5814 WINDOW_LEFT(p) = WINDOW_LEFT(w);
5815 WINDOW_TOP(p) = WINDOW_TOP(w);
5816 WINDOW_WIDTH(p) = WINDOW_WIDTH(w);
5817 WINDOW_HEIGHT(p) = WINDOW_HEIGHT(w);
5818 p->hscroll = w->hscroll;
5819 p->modeline_hscroll = w->modeline_hscroll;
5821 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5822 #include "winslots.h"
5824 if (!NILP(w->buffer)) {
5825 /* Save w's value of point in the window configuration.
5826 If w is the selected window, then get the value of point
5827 from the buffer; pointm is garbage in the selected window. */
5828 if (EQ(window, Fselected_window(Qnil))) {
5829 p->pointm = noseeum_make_marker();
5830 Fset_marker(p->pointm,
5832 (XBUFFER(w->buffer))),
5836 noseeum_copy_marker(w->pointm[CURRENT_DISP],
5840 noseeum_copy_marker(w->start[CURRENT_DISP], Qnil);
5841 p->sb_point = noseeum_copy_marker(w->sb_point, Qnil);
5842 p->start_at_line_beg = w->start_at_line_beg;
5845 noseeum_copy_marker(XBUFFER(w->buffer)->mark, Qnil);
5851 p->start_at_line_beg = 0;
5854 if (NILP(w->parent))
5855 p->parent_index = -1;
5858 saved_window_index(w->parent, config, i);
5862 p->prev_index = saved_window_index(w->prev, config, i);
5863 if (!NILP(w->vchild))
5864 i = save_window_save(w->vchild, config, i);
5865 if (!NILP(w->hchild))
5866 i = save_window_save(w->hchild, config, i);
5873 /* Added to doc string:
5875 This also records the currently selected frame, and FRAME's focus
5876 redirection (see `redirect-frame-focus').
5881 DEFUN("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5882 Return an object representing the current window configuration of FRAME.
5883 If FRAME is nil or omitted, use the selected frame.
5884 This describes the number of windows, their sizes and current buffers,
5885 and for each window on FRAME the displayed buffer, where display
5886 starts, and the positions of point and mark.
5887 An exception is made for point in the current buffer:
5888 its value is -not- saved.
5893 struct frame *f = decode_frame(frame);
5894 struct window_config *config;
5895 unsigned int n_windows = count_windows(XWINDOW(FRAME_ROOT_WINDOW(f)));
5897 int real_font_height;
5899 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5900 config = (struct window_config *)
5901 alloc_lcrecord(sizeof_window_config_for_n_windows(
5903 &lrecord_window_configuration);
5905 if (n_windows <= countof(Vwindow_configuration_free_list)) {
5907 allocate_managed_lcrecord(
5908 Vwindow_configuration_free_list[n_windows - 1]);
5909 config = XWINDOW_CONFIGURATION(tmp);
5911 /* More than ten windows; just allocate directly */
5912 config = (struct window_config *)
5913 alloc_lcrecord(sizeof_window_config_for_n_windows(
5915 &lrecord_window_configuration);
5918 XSETWINDOW_CONFIGURATION(result, config);
5920 config->frame_width = FRAME_WIDTH (f);
5921 config->frame_height = FRAME_HEIGHT (f); */
5922 /* #### When using `push-window-configuration', often the minibuffer
5923 ends up as the selected window because functions run as the result
5924 of user interaction e.g. hyper-apropos. It seems to me the sensible
5925 thing to do is not record the minibuffer here.
5927 #### Unfortunately this is a change to previous behaviour,
5928 however logical it may be, so revert for the moment. */
5930 if (FRAME_MINIBUF_ONLY_P(f) || minibuf_level)
5931 config->current_window = FRAME_SELECTED_WINDOW(f);
5933 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW(f);
5935 config->current_window = FRAME_SELECTED_WINDOW(f);
5936 XSETBUFFER(config->current_buffer, current_buffer);
5937 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5938 config->root_window = FRAME_ROOT_WINDOW(f);
5939 config->min_height = window_min_height;
5940 config->min_width = window_min_width;
5941 config->saved_windows_count = n_windows;
5942 save_window_save(FRAME_ROOT_WINDOW(f), config, 0);
5944 /* save the minibuffer height using the heuristics from
5945 change_frame_size_1 */
5947 XSETFRAME(frame, f); /* frame could have been nil ! */
5948 default_face_height_and_width(frame, &real_font_height, 0);
5949 assert(real_font_height > 0);
5951 if (FRAME_HAS_MINIBUF_P(f) && !FRAME_MINIBUF_ONLY_P(f))
5952 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5955 config->minibuf_height = (minibuf_height % real_font_height) == 0 ? -(minibuf_height / real_font_height) : /* lines */
5956 minibuf_height; /* pixels */
5961 Lisp_Object save_window_excursion_unwind(Lisp_Object window_config)
5963 Lisp_Object val = Fset_window_configuration(window_config);
5964 free_window_configuration(window_config);
5968 DEFUN("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5969 Execute body, preserving window sizes and contents.
5970 Restores which buffer appears in which window, where display starts,
5971 as well as the current buffer.
5972 Does not restore the value of point in current buffer.
5976 /* This function can GC */
5978 int speccount = specpdl_depth();
5980 record_unwind_protect(save_window_excursion_unwind,
5981 Fcurrent_window_configuration(Qnil));
5983 return unbind_to(speccount, val);
5986 DEFUN("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5987 Return the horizontal pixel position of POS in window.
5988 Beginning of line is column 0. This is calculated using the redisplay
5989 display tables. If WINDOW is nil, the current window is assumed.
5990 If POS is nil, point is assumed. Note that POS must be visible for
5991 a non-nil result to be returned.
5995 struct window *w = decode_window(window);
5996 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
5998 struct display_line *dl = 0;
5999 struct display_block *db = 0;
6000 struct rune *rb = 0;
6001 int y = w->last_point_y[CURRENT_DISP];
6002 int x = w->last_point_x[CURRENT_DISP];
6004 if (MINI_WINDOW_P(w))
6007 if (y < 0 || x < 0 || y >= Dynarr_length(dla) || !NILP(pos)) {
6012 pos = Fwindow_point(window);
6017 if (Dynarr_length(dla) && Dynarr_atp(dla, 0)->modeline)
6022 for (i = first_line; i < Dynarr_length(dla); i++) {
6023 dl = Dynarr_atp(dla, i);
6024 /* find the vertical location first */
6025 if (point >= dl->bufpos && point <= dl->end_bufpos) {
6026 db = get_display_block_from_line(dl, TEXT);
6027 for (i = 0; i < Dynarr_length(db->runes); i++) {
6028 rb = Dynarr_atp(db->runes, i);
6029 if (point <= rb->bufpos)
6039 /* optimized case */
6040 dl = Dynarr_atp(dla, y);
6041 db = get_display_block_from_line(dl, TEXT);
6043 if (x >= Dynarr_length(db->runes))
6046 rb = Dynarr_atp(db->runes, x);
6049 return make_int(rb->xpos - WINDOW_LEFT(w));
6052 #ifdef DEBUG_SXEMACS
6053 /* This is short and simple in elisp, but... it was written to debug
6054 problems purely on the C side. That is where we need to call it so
6056 static void debug_print_window(Lisp_Object window, int level)
6059 Lisp_Object child = Fwindow_first_vchild(window);
6062 child = Fwindow_first_hchild(window);
6064 for (i = level; i > 0; i--)
6067 stderr_out("#<window");
6069 Lisp_Object buffer = XWINDOW(window)->buffer;
6070 if (!NILP(buffer) && BUFFERP(buffer))
6071 stderr_out(" on %s",
6072 XSTRING_DATA(XBUFFER(buffer)->name));
6074 stderr_out(" 0x%x>", XWINDOW(window)->header.uid);
6076 while (!NILP(child)) {
6077 debug_print_window(child, level + 1);
6078 child = Fwindow_next_child(child);
6082 void debug_print_windows(struct frame *f);
6083 void debug_print_windows(struct frame *f)
6085 debug_print_window(f->root_window, 0);
6088 #endif /* DEBUG_SXEMACS */
6090 /************************************************************************/
6091 /* initialization */
6092 /************************************************************************/
6094 void syms_of_window(void)
6096 INIT_LRECORD_IMPLEMENTATION(window);
6097 INIT_LRECORD_IMPLEMENTATION(window_configuration);
6099 defsymbol(&Qwindowp, "windowp");
6100 defsymbol(&Qwindow_live_p, "window-live-p");
6101 defsymbol(&Qwindow_configurationp, "window-configuration-p");
6102 defsymbol(&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6103 defsymbol(&Qdisplay_buffer, "display-buffer");
6105 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6106 defsymbol(&Qface_cache, "face-cache");
6107 defsymbol(&Qglyph_cache, "glyph-cache");
6108 defsymbol(&Qline_start_cache, "line-start-cache");
6109 #ifdef HAVE_SCROLLBARS
6110 defsymbol(&Qscrollbar_instances, "scrollbar-instances");
6112 defsymbol(&Qother_redisplay, "other-redisplay");
6113 /* Qother in general.c */
6116 DEFSYMBOL(Qtruncate_partial_width_windows);
6117 DEFSYMBOL (Qwindow_configuration_hook);
6119 DEFSUBR(Fselected_window);
6120 DEFSUBR(Flast_nonminibuf_window);
6121 DEFSUBR(Fminibuffer_window);
6122 DEFSUBR(Fwindow_minibuffer_p);
6124 DEFSUBR(Fwindow_live_p);
6125 DEFSUBR(Fwindow_first_hchild);
6126 DEFSUBR(Fwindow_first_vchild);
6127 DEFSUBR(Fwindow_next_child);
6128 DEFSUBR(Fwindow_previous_child);
6129 DEFSUBR(Fwindow_parent);
6130 DEFSUBR(Fwindow_lowest_p);
6131 DEFSUBR(Fwindow_truncated_p);
6132 DEFSUBR(Fwindow_highest_p);
6133 DEFSUBR(Fwindow_leftmost_p);
6134 DEFSUBR(Fwindow_rightmost_p);
6135 DEFSUBR(Fpos_visible_in_window_p);
6136 DEFSUBR(Fwindow_buffer);
6137 DEFSUBR(Fwindow_frame);
6138 DEFSUBR(Fwindow_height);
6139 DEFSUBR(Fwindow_displayed_height);
6140 DEFSUBR(Fwindow_width);
6141 DEFSUBR(Fwindow_full_width);
6142 DEFSUBR(Fwindow_pixel_height);
6143 DEFSUBR(Fwindow_pixel_width);
6144 DEFSUBR(Fwindow_text_area_height);
6145 DEFSUBR(Fwindow_text_area_pixel_height);
6146 DEFSUBR(Fwindow_displayed_text_pixel_height);
6147 DEFSUBR(Fwindow_text_area_pixel_width);
6148 DEFSUBR(Fwindow_hscroll);
6149 DEFSUBR(Fset_window_hscroll);
6150 DEFSUBR(Fmodeline_hscroll);
6151 DEFSUBR(Fset_modeline_hscroll);
6152 #if 0 /* bogus FSF crock */
6153 DEFSUBR(Fwindow_redisplay_end_trigger);
6154 DEFSUBR(Fset_window_redisplay_end_trigger);
6156 DEFSUBR(Fwindow_pixel_edges);
6157 DEFSUBR(Fwindow_text_area_pixel_edges);
6158 DEFSUBR(Fwindow_point);
6159 DEFSUBR(Fwindow_start);
6160 DEFSUBR(Fwindow_end);
6161 DEFSUBR(Fwindow_last_line_visible_height);
6162 DEFSUBR(Fset_window_point);
6163 DEFSUBR(Fset_window_start);
6164 DEFSUBR(Fwindow_dedicated_p);
6165 DEFSUBR(Fset_window_dedicated_p);
6166 DEFSUBR(Fnext_window);
6167 DEFSUBR(Fprevious_window);
6168 DEFSUBR(Fnext_vertical_window);
6169 DEFSUBR(Fother_window);
6170 DEFSUBR(Fget_lru_window);
6171 DEFSUBR(Fget_largest_window);
6172 DEFSUBR(Fget_buffer_window);
6173 DEFSUBR(Fwindow_left_margin_pixel_width);
6174 DEFSUBR(Fwindow_right_margin_pixel_width);
6175 DEFSUBR(Fdelete_other_windows);
6176 DEFSUBR(Fdelete_windows_on);
6177 DEFSUBR(Freplace_buffer_in_windows);
6178 DEFSUBR(Fdelete_window);
6179 DEFSUBR(Fset_window_buffer);
6180 DEFSUBR(Fselect_window);
6181 DEFSUBR(Fsplit_window);
6182 DEFSUBR(Fenlarge_window);
6183 DEFSUBR(Fenlarge_window_pixels);
6184 DEFSUBR(Fshrink_window);
6185 DEFSUBR(Fshrink_window_pixels);
6186 DEFSUBR(Fscroll_up);
6187 DEFSUBR(Fscroll_down);
6188 DEFSUBR(Fscroll_left);
6189 DEFSUBR(Fscroll_right);
6190 DEFSUBR(Fother_window_for_scrolling);
6191 DEFSUBR(Fscroll_other_window);
6192 DEFSUBR(Fcenter_to_window_line);
6193 DEFSUBR(Fmove_to_window_line);
6194 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
6195 DEFSUBR(Fwindow_memory_usage);
6197 DEFSUBR(Fwindow_configuration_p);
6198 DEFSUBR(Fset_window_configuration);
6199 DEFSUBR(Fcurrent_window_configuration);
6200 DEFSUBR(Fsave_window_excursion);
6201 DEFSUBR(Fcurrent_pixel_column);
6204 void reinit_vars_of_window(void)
6206 /* Make sure all windows get marked */
6207 minibuf_window = Qnil;
6208 staticpro_nodump(&minibuf_window);
6210 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
6211 for (unsigned int i = 0;
6212 i < countof(Vwindow_configuration_free_list); i++) {
6213 Vwindow_configuration_free_list[i] =
6214 make_lcrecord_list(sizeof_window_config_for_n_windows(
6216 &lrecord_window_configuration);
6217 staticpro_nodump(&Vwindow_configuration_free_list[i]);
6223 void vars_of_window(void)
6225 reinit_vars_of_window();
6227 DEFVAR_BOOL("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6228 *Non-nil means to scroll if point lands on a line which is clipped.
6230 scroll_on_clipped_lines = 1;
6232 DEFVAR_LISP("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6233 See `temp-buffer-show-function'.
6235 Vtemp_buffer_show_hook = Qnil;
6237 DEFVAR_LISP("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6238 Non-nil means call as function to display a help buffer.
6239 The function is called with one argument, the buffer to be displayed.
6240 Used by `with-output-to-temp-buffer'.
6241 If this function is used, then it must do the entire job of showing
6242 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6243 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6245 Vtemp_buffer_show_function = Qnil;
6247 DEFVAR_LISP("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6248 Non-nil means it is the window that
6249 \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should
6252 Vminibuffer_scroll_window = Qnil;
6254 DEFVAR_LISP("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6255 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6257 Vother_window_scroll_buffer = Qnil;
6259 DEFVAR_LISP("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6260 *Number of pixels to scroll by per requested line.
6261 If nil then normal line scrolling occurs regardless of line height.
6262 If t then scrolling is done in increments equal to the height of the default face.
6264 Vwindow_pixel_scroll_increment = Qt;
6266 DEFVAR_LISP ("window-configuration-hook", &Vwindow_configuration_hook /*
6267 Function(s) to call when a frame's window configuration has changed.
6269 Please see (Info-goto-node "(lispref)Window Configuration Hook") where all the
6270 details are documented.
6273 Vwindow_configuration_hook = Qnil;
6276 DEFVAR_INT("next-screen-context-lines", &next_screen_context_lines /*
6277 *Number of lines of continuity when scrolling by screenfuls.
6279 next_screen_context_lines = 2;
6281 DEFVAR_INT("window-min-height", &window_min_height /*
6282 *Delete any window less than this tall (including its modeline).
6284 window_min_height = 4;
6286 DEFVAR_INT("window-min-width", &window_min_width /*
6287 *Delete any window less than this wide.
6289 window_min_width = 10;
6292 void specifier_vars_of_window(void)
6294 DEFVAR_SPECIFIER("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6295 *How thick to draw 3D shadows around modelines.
6296 If this is set to 0, modelines will be the traditional 2D. Sizes above
6297 10 will be accepted but the maximum thickness that will be drawn is 10.
6298 This is a specifier; use `set-specifier' to change it.
6300 Vmodeline_shadow_thickness = Fmake_specifier(Qinteger);
6301 /* The initial value for modeline-shadow-thickness is 2, but if the
6302 user removes all specifications we provide a fallback value of 0,
6303 which is probably what was expected. */
6304 set_specifier_fallback(Vmodeline_shadow_thickness,
6305 list1(Fcons(Qnil, Qzero)));
6306 Fadd_spec_to_specifier(Vmodeline_shadow_thickness, make_int(2),
6308 set_specifier_caching(Vmodeline_shadow_thickness,
6309 offsetof(struct window,
6310 modeline_shadow_thickness),
6311 modeline_shadow_thickness_changed, 0, 0, 0);
6313 DEFVAR_SPECIFIER("has-modeline-p", &Vhas_modeline_p /*
6314 *Whether the modeline should be displayed.
6315 This is a specifier; use `set-specifier' to change it.
6317 Vhas_modeline_p = Fmake_specifier(Qboolean);
6318 set_specifier_fallback(Vhas_modeline_p, list1(Fcons(Qnil, Qt)));
6319 set_specifier_caching(Vhas_modeline_p,
6320 offsetof(struct window, has_modeline_p),
6321 /* #### It's strange that we need a special
6322 flag to indicate that the shadow-thickness
6323 has changed, but not one to indicate that
6324 the modeline has been turned off or on. */
6325 some_window_value_changed, 0, 0, 0);
6327 DEFVAR_SPECIFIER("vertical-divider-always-visible-p", &Vvertical_divider_always_visible_p /*
6328 *Should SXEmacs always display vertical dividers between windows.
6330 When this is non-nil, vertical dividers are always shown, and are
6331 draggable. When it is nil, vertical dividers are shown only when
6332 there are no scrollbars in between windows, and are not draggable.
6334 This is a specifier; use `set-specifier' to change it.
6336 Vvertical_divider_always_visible_p = Fmake_specifier(Qboolean);
6337 set_specifier_fallback(Vvertical_divider_always_visible_p,
6338 list1(Fcons(Qnil, Qt)));
6339 set_specifier_caching(Vvertical_divider_always_visible_p,
6340 offsetof(struct window,
6341 vertical_divider_always_visible_p),
6342 vertical_divider_changed_in_window, 0, 0, 0);
6344 DEFVAR_SPECIFIER("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6345 *How thick to draw 3D shadows around vertical dividers.
6346 This is a specifier; use `set-specifier' to change it.
6348 Vvertical_divider_shadow_thickness = Fmake_specifier(Qinteger);
6349 set_specifier_fallback(Vvertical_divider_shadow_thickness,
6350 list1(Fcons(Qnil, Qzero)));
6351 Fadd_spec_to_specifier(Vvertical_divider_shadow_thickness, make_int(2),
6353 set_specifier_caching(Vvertical_divider_shadow_thickness,
6354 offsetof(struct window,
6355 vertical_divider_shadow_thickness),
6356 vertical_divider_changed_in_window, 0, 0, 0);
6357 DEFVAR_SPECIFIER("vertical-divider-line-width", &Vvertical_divider_line_width /*
6358 *The width of the vertical dividers, not including shadows.
6360 For TTY windows, divider line is always one character wide. When
6361 instance of this specifier is zero in a TTY window, no divider is
6362 drawn at all between windows. When non-zero, a one character wide
6363 divider is displayed.
6365 This is a specifier; use `set-specifier' to change it.
6368 Vvertical_divider_line_width = Fmake_specifier(Qnatnum);
6370 Lisp_Object fb = Qnil;
6372 fb = Fcons(Fcons(list1(Qtty), make_int(1)), fb);
6375 fb = Fcons(Fcons(list1(Qgtk), make_int(3)), fb);
6377 #ifdef HAVE_X_WINDOWS
6378 fb = Fcons(Fcons(list1(Qx), make_int(3)), fb);
6380 set_specifier_fallback(Vvertical_divider_line_width, fb);
6382 set_specifier_caching(Vvertical_divider_line_width,
6383 offsetof(struct window,
6384 vertical_divider_line_width),
6385 vertical_divider_changed_in_window, 0, 0, 0);
6387 DEFVAR_SPECIFIER("vertical-divider-spacing", &Vvertical_divider_spacing /*
6388 *How much space to leave around the vertical dividers.
6390 In TTY windows, spacing is always zero, and the value of this
6391 specifier is ignored.
6393 This is a specifier; use `set-specifier' to change it.
6395 Vvertical_divider_spacing = Fmake_specifier(Qnatnum);
6397 Lisp_Object fb = Qnil;
6399 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
6401 #ifdef HAVE_X_WINDOWS
6402 /* #### 3D dividers look great on MS Windows with spacing = 0.
6403 Should not the same value be the fallback under X? - kkm */
6404 fb = Fcons(Fcons(list1(Qx), make_int(2)), fb);
6407 fb = Fcons(Fcons(list1(Qgtk), Qzero), fb);
6409 set_specifier_fallback(Vvertical_divider_spacing, fb);
6411 set_specifier_caching(Vvertical_divider_spacing,
6412 offsetof(struct window, vertical_divider_spacing),
6413 vertical_divider_changed_in_window, 0, 0, 0);