1 /* Window creation, deletion and examination for XEmacs.
2 Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1996 Chuck Thompson.
7 This file is part of XEmacs.
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
24 /* Synched up with: FSF 19.30. */
25 /* Beginning to diverge significantly. */
27 /* This file has been Mule-ized. */
37 #include "redisplay.h"
42 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
43 Lisp_Object Qscroll_up, Qscroll_down, Qdisplay_buffer;
45 #ifdef MEMORY_USAGE_STATS
46 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
47 #ifdef HAVE_SCROLLBARS
48 Lisp_Object Qscrollbar_instances;
52 EXFUN (Fnext_window, 4);
54 static int window_pixel_width_to_char_width (struct window *w,
56 int include_margins_p);
57 static int window_char_width_to_pixel_width (struct window *w,
59 int include_margins_p);
60 static int window_pixel_height_to_char_height (struct window *w,
62 int include_gutters_p);
63 static int window_char_height_to_pixel_height (struct window *w,
65 int include_gutters_p);
66 static void change_window_height (struct window *w, int delta, int widthflag,
69 /* Thickness of shadow border around 3d modelines. */
70 Lisp_Object Vmodeline_shadow_thickness;
72 /* Whether vertical dividers are draggable and displayed */
73 Lisp_Object Vvertical_divider_always_visible_p;
75 /* Whether a modeline should be displayed. */
76 Lisp_Object Vhas_modeline_p;
78 /* Thickness of shadow border around vertical dividers. */
79 Lisp_Object Vvertical_divider_shadow_thickness;
81 /* Divider surface width (not counting 3-d borders) */
82 Lisp_Object Vvertical_divider_line_width;
84 /* Spacing between outer egde of divider border and window edge */
85 Lisp_Object Vvertical_divider_spacing;
87 /* Scroll if point lands on the bottom line and that line is partially
89 int scroll_on_clipped_lines;
91 /* The minibuffer window of the selected frame.
92 Note that you cannot test for minibufferness of an arbitrary window
93 by comparing against this; but you can test for minibufferness of
94 the selected window. */
95 Lisp_Object minibuf_window;
97 /* Non-nil means it is the window for C-M-v to scroll
98 when the minibuffer is selected. */
99 Lisp_Object Vminibuffer_scroll_window;
101 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
102 Lisp_Object Vother_window_scroll_buffer;
104 /* Non-nil means it's the function to call to display temp buffers. */
105 Lisp_Object Vtemp_buffer_show_function;
107 Lisp_Object Vtemp_buffer_show_hook;
109 /* If a window gets smaller than either of these, it is removed. */
110 int window_min_height;
111 int window_min_width;
113 /* Hook run at end of temp_output_buffer_show. */
114 Lisp_Object Qtemp_buffer_show_hook;
116 /* Number of lines of continuity in scrolling by screenfuls. */
117 int next_screen_context_lines;
119 /* List of freed window configurations with 1 - 10 windows. */
120 Lisp_Object Vwindow_configuration_free_list[10];
122 #define SET_LAST_MODIFIED(w, cache_too) \
124 (w)->last_modified[CURRENT_DISP] = Qzero; \
125 (w)->last_modified[DESIRED_DISP] = Qzero; \
126 (w)->last_modified[CMOTION_DISP] = Qzero; \
128 (w)->line_cache_last_updated = Qzero; \
131 #define SET_LAST_FACECHANGE(w) \
133 (w)->last_facechange[CURRENT_DISP] = Qzero; \
134 (w)->last_facechange[DESIRED_DISP] = Qzero; \
135 (w)->last_facechange[CMOTION_DISP] = Qzero; \
139 #define MARK_DISP_VARIABLE(field) \
140 markobj (window->field[CURRENT_DISP]); \
141 markobj (window->field[DESIRED_DISP]); \
142 markobj (window->field[CMOTION_DISP]);
145 mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object))
147 struct window *window = XWINDOW (obj);
148 markobj (window->frame);
149 markobj (window->mini_p);
150 markobj (window->next);
151 markobj (window->prev);
152 markobj (window->hchild);
153 markobj (window->vchild);
154 markobj (window->parent);
155 markobj (window->buffer);
156 MARK_DISP_VARIABLE (start);
157 MARK_DISP_VARIABLE (pointm);
158 markobj (window->sb_point); /* #### move to scrollbar.c? */
159 markobj (window->use_time);
160 MARK_DISP_VARIABLE (last_modified);
161 MARK_DISP_VARIABLE (last_point);
162 MARK_DISP_VARIABLE (last_start);
163 MARK_DISP_VARIABLE (last_facechange);
164 markobj (window->line_cache_last_updated);
165 markobj (window->redisplay_end_trigger);
166 markobj (window->subwindow_instance_cache);
168 mark_face_cachels (window->face_cachels, markobj);
169 mark_glyph_cachels (window->glyph_cachels, markobj);
171 #define WINDOW_SLOT(slot, compare) ((void) (markobj (window->slot)))
172 #include "winslots.h"
178 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
183 error ("printing unreadable object #<window 0x%x>",
184 XWINDOW (obj)->header.uid);
186 write_c_string ("#<window", printcharfun);
187 if (!NILP (XWINDOW (obj)->buffer))
189 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
190 write_c_string (" on ", printcharfun);
191 print_internal (name, printcharfun, 1);
193 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
194 write_c_string (buf, printcharfun);
198 finalize_window (void *header, int for_disksave)
200 struct window *w = (struct window *) header;
202 if (w->line_start_cache)
204 Dynarr_free (w->line_start_cache);
205 w->line_start_cache = 0;
212 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
214 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
215 if (cachel->merged_faces)
217 Dynarr_free (cachel->merged_faces);
218 cachel->merged_faces = 0;
221 Dynarr_free (w->face_cachels);
225 if (w->glyph_cachels)
227 Dynarr_free (w->glyph_cachels);
228 w->glyph_cachels = 0;
232 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
233 mark_window, print_window, finalize_window,
234 0, 0, struct window);
237 #define INIT_DISP_VARIABLE(field, initialization) \
238 p->field[CURRENT_DISP] = initialization; \
239 p->field[DESIRED_DISP] = initialization; \
240 p->field[CMOTION_DISP] = initialization;
242 /* We have an implicit assertion that the first two elements (default
243 and modeline faces) are always present in the face_element_cache.
244 Normally redisplay ensures this. However, it is possible for a
245 window to get created and functions which reference these values
246 called before redisplay works with the window for the first time.
247 All callers of allocate_window should therefore call
248 reset_face_cachels on the created window. We can't do it
249 here because the window must have its frame pointer set or
250 reset_face_cachels will fail. */
252 allocate_window (void)
255 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
269 INIT_DISP_VARIABLE (start, Fmake_marker ());
270 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
271 p->sb_point = Fmake_marker ();
273 INIT_DISP_VARIABLE (last_modified, Qzero);
274 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
275 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
276 INIT_DISP_VARIABLE (last_facechange, Qzero);
277 p->face_cachels = Dynarr_new (face_cachel);
278 p->glyph_cachels = Dynarr_new (glyph_cachel);
279 p->line_start_cache = Dynarr_new (line_start_cache);
280 p->subwindow_instance_cache = make_lisp_hash_table (10,
283 p->line_cache_last_updated = Qzero;
284 INIT_DISP_VARIABLE (last_point_x, 0);
285 INIT_DISP_VARIABLE (last_point_y, 0);
286 INIT_DISP_VARIABLE (window_end_pos, 0);
287 p->redisplay_end_trigger = Qnil;
289 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
290 #include "winslots.h"
292 p->windows_changed = 1;
293 p->shadow_thickness_changed = 1;
297 #undef INIT_DISP_VARIABLE
300 * The redisplay structures used to be stored with each window. While
301 * they are logically something associated with frames they can't be
302 * stored there with a redisplay which handles variable height lines.
303 * Lines in horizontally split windows might not line up. So they get
304 * stored with the windows.
306 * The problem with this is window configurations. When restoring a
307 * window configuration it now becomes problematic to do an
308 * incremental redisplay. The solution is to store the redisplay
309 * structures with the frame as they should be but laid out in the
310 * same manner as the window structure. Thus is born the window
313 * It also becomes a convenient place to stick scrollbar instances
314 * since they extrapolate out to having the same problem described for
315 * the display structures.
318 /* Create a new window mirror structure and associated redisplay
320 static struct window_mirror *
321 new_window_mirror (struct frame *f)
323 struct window_mirror *t = xnew_and_zero (struct window_mirror);
327 t->current_display_lines = Dynarr_new (display_line);
328 t->desired_display_lines = Dynarr_new (display_line);
331 #ifdef HAVE_SCROLLBARS
332 t->scrollbar_vertical_instance = NULL;
333 t->scrollbar_horizontal_instance = NULL;
339 /* Synchronize the mirror structure with a given window structure.
340 This is normally called from update_frame_window_mirror with a
341 starting window of f->root_window. */
342 static struct window_mirror *
343 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
349 free_window_mirror (mir);
356 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
358 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
359 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
360 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
363 * If the redisplay structs are not empty and the mirror has
364 * children, then this mirror structure was formerly being used for
365 * display but is no longer. Reset its current display structs so
366 * that redisplay doesn't accidentally think they are accurate if it
367 * is later used for display purposes once again. Also, mark the
368 * scrollbar instance as not active.
370 if (mir->vchild || mir->hchild)
372 /* The redisplay structures are big. Leaving them around in
373 non-leaf windows can add up to a lot of wasted space. So
375 free_display_structs (mir);
376 mir->current_display_lines = Dynarr_new (display_line);
377 mir->desired_display_lines = Dynarr_new (display_line);
379 #ifdef HAVE_SCROLLBARS
380 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
388 /* Given a window mirror, determine which real window it contains the
389 redisplay structures for. */
391 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
392 struct window_mirror *mir)
394 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
398 if (!NILP (XWINDOW (win)->vchild))
401 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
405 if (!NILP (XWINDOW (win)->hchild))
408 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
417 /* Given a real window, find the mirror structure which contains its
418 redisplay structures. */
419 static struct window_mirror *
420 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
423 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
425 if (w == XWINDOW (win))
428 if (!NILP (XWINDOW (win)->vchild))
430 struct window_mirror *retval =
431 find_window_mirror_internal (XWINDOW (win)->vchild,
433 if (retval) return retval;
436 if (!NILP (XWINDOW (win)->hchild))
438 struct window_mirror *retval =
439 find_window_mirror_internal (XWINDOW (win)->hchild,
441 if (retval) return retval;
448 /* Update the mirror structure for the given frame. */
450 update_frame_window_mirror (struct frame *f)
452 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
456 /* Free a given mirror structure along with all of its children as
457 well as their associated display structures. */
459 free_window_mirror (struct window_mirror *mir)
463 struct window_mirror *prev = mir;
464 if (mir->hchild) free_window_mirror (mir->hchild);
465 if (mir->vchild) free_window_mirror (mir->vchild);
466 #ifdef HAVE_SCROLLBARS
467 release_window_mirror_scrollbars (mir);
469 free_display_structs (mir);
475 /* Given a mirror structure, return the window it mirrors. Calls
476 real_window_internal to do most of the work. */
478 real_window (struct window_mirror *mir, int no_abort)
480 Lisp_Object retval = real_window_internal (mir->frame->root_window,
481 mir->frame->root_mirror, mir);
482 if (NILP (retval) && !no_abort)
488 /* Given a real window, return its mirror structure. Calls
489 find_window_mirror_internal to do all of the work. */
490 struct window_mirror *
491 find_window_mirror (struct window *w)
493 struct frame *f = XFRAME (w->frame);
495 update_frame_window_mirror (f);
496 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
499 /*****************************************************************************
500 find_window_by_pixel_pos
502 Given a pixel position relative to a frame, find the window at that
504 ****************************************************************************/
506 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
511 for (; !NILP (win); win = XWINDOW (win)->next)
515 if (!NILP (XWINDOW (win)->vchild))
517 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
520 if (!NILP (XWINDOW (win)->hchild))
522 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
526 if (pix_x >= WINDOW_LEFT (w)
527 && pix_x <= WINDOW_RIGHT (w)
528 && pix_y >= WINDOW_TOP (w)
529 && pix_y <= WINDOW_BOTTOM (w))
535 /* Return a pointer to the display structures for the given window. */
536 display_line_dynarr *
537 window_display_lines (struct window *w, int which)
539 struct window_mirror *t;
541 if (XFRAME (w->frame)->mirror_dirty)
542 update_frame_window_mirror (XFRAME (w->frame));
543 t = find_window_mirror (w);
547 if (which == CURRENT_DISP)
548 return t->current_display_lines;
549 else if (which == DESIRED_DISP)
550 return t->desired_display_lines;
551 else if (which == CMOTION_DISP)
552 /* The CMOTION_DISP display lines are global. */
553 return cmotion_display_lines;
557 return 0; /* shut up compiler */
561 window_display_buffer (struct window *w)
563 struct window_mirror *t;
565 if (XFRAME (w->frame)->mirror_dirty)
566 update_frame_window_mirror (XFRAME (w->frame));
567 t = find_window_mirror (w);
575 set_window_display_buffer (struct window *w, struct buffer *b)
577 struct window_mirror *t;
579 if (XFRAME (w->frame)->mirror_dirty)
580 update_frame_window_mirror (XFRAME (w->frame));
581 t = find_window_mirror (w);
589 /* Determining a window's position based solely on its pixel
590 positioning doesn't work. Instead, we do it the intelligent way,
591 by checking its positioning in the window hierarchy. */
593 window_is_leftmost (struct window *w)
595 Lisp_Object parent, current_ancestor, window;
597 XSETWINDOW (window, w);
599 parent = XWINDOW (window)->parent;
600 current_ancestor = window;
602 while (!NILP (parent))
604 if (!NILP (XWINDOW (parent)->hchild) &&
605 !EQ (XWINDOW (parent)->hchild, current_ancestor))
608 current_ancestor = parent;
609 parent = XWINDOW (parent)->parent;
616 window_is_rightmost (struct window *w)
618 Lisp_Object parent, current_ancestor, window;
620 XSETWINDOW (window, w);
622 parent = XWINDOW (window)->parent;
623 current_ancestor = window;
625 while (!NILP (parent))
627 if (!NILP (XWINDOW (parent)->hchild)
628 && !NILP (XWINDOW (current_ancestor)->next))
631 current_ancestor = parent;
632 parent = XWINDOW (parent)->parent;
639 window_full_width_p (struct window *w)
641 return window_is_leftmost (w) && window_is_rightmost (w);
645 window_is_highest (struct window *w)
647 Lisp_Object parent, current_ancestor, window;
649 XSETWINDOW (window, w);
651 parent = XWINDOW (window)->parent;
652 current_ancestor = window;
654 while (!NILP (parent))
656 if (!NILP (XWINDOW (parent)->vchild) &&
657 !EQ (XWINDOW (parent)->vchild, current_ancestor))
660 current_ancestor = parent;
661 parent = XWINDOW (parent)->parent;
664 /* This is really to catch the minibuffer but we make it generic in
665 case we ever change things around to let the minibuffer be on top. */
666 if (NILP (XWINDOW (current_ancestor)->prev))
673 window_is_lowest (struct window *w)
675 Lisp_Object parent, current_ancestor, window;
677 XSETWINDOW (window, w);
679 parent = XWINDOW (window)->parent;
680 current_ancestor = window;
682 while (!NILP (parent))
684 if (!NILP (XWINDOW (parent)->vchild)
685 && !NILP (XWINDOW (current_ancestor)->next))
688 current_ancestor = parent;
689 parent = XWINDOW (parent)->parent;
695 #if 0 /* not currently used */
698 window_full_height_p (struct window *w)
700 return window_is_highest (w) && window_is_lowest (w);
706 window_truncation_on (struct window *w)
708 /* Horizontally scrolled windows are truncated. */
712 /* If truncate_partial_width_windows is true and the window is not
713 the full width of the frame it is truncated. */
714 if (truncate_partial_width_windows
715 && !(window_is_leftmost (w) && window_is_rightmost (w)))
718 /* If the window's buffer's value of truncate_lines is non-nil, then
719 the window is truncated. */
720 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
727 have_undivided_common_edge (struct window *w_right, void *closure)
729 struct window *w_left = (struct window *) closure;
730 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
731 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
732 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
733 #ifdef HAVE_SCROLLBARS
734 && (NILP (w_right->scrollbar_on_left_p)
735 || NILP (w_right->vertical_scrollbar_visible_p)
736 || ZEROP (w_right->scrollbar_width))
742 window_needs_vertical_divider_1 (struct window *w)
744 /* Never if we're on the right */
745 if (window_is_rightmost (w))
748 /* Always if draggable */
749 if (!NILP (w->vertical_divider_always_visible_p))
752 #ifdef HAVE_SCROLLBARS
753 /* Our right scrollbar is enough to separate us at the right */
754 if (NILP (w->scrollbar_on_left_p)
755 && !NILP (w->vertical_scrollbar_visible_p)
756 && !ZEROP (w->scrollbar_width))
760 /* Ok. to determine whether we need a divider on the left, we must
761 check that our right neighbor windows have scrollbars on their
762 left sides. We must check all such windows which have common
763 left edge with our window's right edge. */
764 return map_windows (XFRAME (WINDOW_FRAME (w)),
765 have_undivided_common_edge, (void*)w);
769 window_needs_vertical_divider (struct window *w)
771 if (!w->need_vertical_divider_valid_p)
773 w->need_vertical_divider_p =
774 window_needs_vertical_divider_1 (w);
775 w->need_vertical_divider_valid_p = 1;
777 return w->need_vertical_divider_p;
780 /* Called from invalidate_vertical_divider_cache_in_frame */
782 invalidate_vertical_divider_cache_in_window (struct window *w,
785 w->need_vertical_divider_valid_p = 0;
789 /* Calculate width of vertical divider, including its shadows
790 and spacing. The returned value is effectively the distance
791 between adjacent window edges. This function does not check
792 whether a window needs a vertical divider, so the returned
793 value is a "theoretical" one */
795 window_divider_width (struct window *w)
797 /* the shadow thickness can be negative. This means that the divider
798 will have a depressed look */
800 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
802 XINT (w->vertical_divider_line_width)
803 + 2 * XINT (w->vertical_divider_spacing)
804 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
806 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
810 window_scrollbar_width (struct window *w)
812 #ifdef HAVE_SCROLLBARS
813 if (!WINDOW_WIN_P (w)
816 || NILP (w->vertical_scrollbar_visible_p))
817 /* #### when does NILP (w->buffer) happen? */
820 return XINT (w->scrollbar_width);
823 #endif /* HAVE_SCROLLBARS */
826 /* Horizontal scrollbars are only active on windows with truncation
829 window_scrollbar_height (struct window *w)
831 #ifdef HAVE_SCROLLBARS
832 if (!WINDOW_WIN_P (w)
835 || NILP (w->horizontal_scrollbar_visible_p)
836 || !window_truncation_on (w))
839 return XINT (w->scrollbar_height);
842 #endif /* HAVE_SCROLLBARS */
846 window_modeline_height (struct window *w)
848 struct frame *f = XFRAME (w->frame);
851 if (MINI_WINDOW_P (w) || NILP (w->buffer))
855 else if (!WINDOW_HAS_MODELINE_P (w))
857 if (window_scrollbar_height (w))
861 modeline_height = FRAMEMETH (f, divider_height, ());
863 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
864 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
873 display_line_dynarr *dla;
875 /* We don't force a regeneration of the modeline here.
876 Instead it is now a precondition that any function calling
877 this should make sure that one of these structures is
878 up-to-date. In practice this only affects two internal
879 redisplay functions, regenerate_window and
880 regenerate_window_point_center. */
881 /* We check DESIRED_DISP because if it is valid it is more
882 up-to-date than CURRENT_DISP. For calls to this outside
883 of redisplay it doesn't matter which structure we check
884 since there is a redisplay condition that these
885 structures be identical outside of redisplay. */
886 dla = window_display_lines (w, DESIRED_DISP);
887 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
888 modeline_height = (Dynarr_atp (dla, 0)->ascent +
889 Dynarr_atp (dla, 0)->descent);
892 dla = window_display_lines (w, CURRENT_DISP);
893 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
894 modeline_height = (Dynarr_atp (dla, 0)->ascent +
895 Dynarr_atp (dla, 0)->descent);
897 /* This should be an abort except I'm not yet 100%
898 confident that it won't ever get hit (though I
899 haven't been able to trigger it). It is extremely
900 unlikely to cause any noticeable problem and even if
901 it does it will be a minor display glitch. */
902 /* #### Bullshit alert. It does get hit and it causes
903 noticeable glitches. real_current_modeline_height
904 is a kludge to fix this for 19.14. */
905 modeline_height = real_current_modeline_height (w);
908 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
909 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
913 return modeline_height;
916 /*****************************************************************************
917 margin_width_internal
919 For a given window, return the width in pixels of the specified margin.
920 ****************************************************************************/
922 margin_width_internal (struct window *w, int left_margin)
925 int window_cwidth = window_char_width (w, 1);
930 /* We might be getting called on a non-leaf. */
931 if (NILP (w->buffer))
934 /* The minibuffer never has margins. */
935 if (MINI_WINDOW_P (w))
938 XSETWINDOW (window, w);
939 b = XBUFFER (w->buffer);
940 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
941 XINT (w->right_margin_width));
943 default_face_height_and_width (window, 0, &font_width);
945 /* The left margin takes precedence over the right margin so we
946 subtract its width from the space available for the right
949 window_cwidth -= XINT (w->left_margin_width);
951 /* The margin cannot be wider than the window is. We allow the
952 value to be bigger since it is possible for the user to enlarge
953 the window such that the left margin value would no longer be too
954 big, but we won't return a value that is larger. */
955 if (margin_cwidth > window_cwidth)
956 margin_cwidth = window_cwidth;
958 /* At the user level the margin is always specified in characters.
959 Internally however it is manipulated in terms of pixels. */
960 return margin_cwidth * font_width;
964 window_left_margin_width (struct window *w)
966 return margin_width_internal (w, 1);
970 window_right_margin_width (struct window *w)
972 return margin_width_internal (w, 0);
976 window_top_toolbar_height (struct window *w)
978 /* #### implement this shit. */
982 /* #### Currently used in scrollbar.c. Does it actually need to be? */
984 window_bottom_toolbar_height (struct window *w)
990 window_left_toolbar_width (struct window *w)
996 window_right_toolbar_width (struct window *w)
1001 /*****************************************************************************
1004 The gutters of a window are those areas in the boundary defined by
1005 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1006 do not contain text. Items which may be in the gutters include
1007 scrollbars, toolbars and modelines. The margin areas are not
1008 included. This is an exception made because redisplay special cases
1009 the handling of those areas in many places in such a way that
1010 including them in the gutter area would make life difficult.
1012 The size functions refer to height for the bottom and top gutters and
1013 width for the left and right gutters. The starting position
1014 functions refer to the Y coord for bottom and top gutters and the X
1015 coord for left and right gutters. All starting positions are
1016 relative to the frame, not the window.
1017 ****************************************************************************/
1020 window_top_gutter_height (struct window *w)
1022 int toolbar_height = window_top_toolbar_height (w);
1024 if (!NILP (w->hchild) || !NILP (w->vchild))
1027 #ifdef HAVE_SCROLLBARS
1028 if (!NILP (w->scrollbar_on_top_p))
1029 return window_scrollbar_height (w) + toolbar_height;
1032 return toolbar_height;
1036 window_bottom_gutter_height (struct window *w)
1040 if (!NILP (w->hchild) || !NILP (w->vchild))
1044 window_modeline_height (w) + window_bottom_toolbar_height (w);
1046 #ifdef HAVE_SCROLLBARS
1047 if (NILP (w->scrollbar_on_top_p))
1048 return window_scrollbar_height (w) + other_height;
1051 return other_height;
1055 window_left_gutter_width (struct window *w, int modeline)
1057 int gutter = window_left_toolbar_width (w);
1059 if (!NILP (w->hchild) || !NILP (w->vchild))
1063 #ifdef HAVE_SCROLLBARS
1064 if (!modeline && !NILP (w->scrollbar_on_left_p))
1065 gutter += window_scrollbar_width (w);
1072 window_right_gutter_width (struct window *w, int modeline)
1074 int gutter = window_right_toolbar_width (w);
1076 if (!NILP (w->hchild) || !NILP (w->vchild))
1079 #ifdef HAVE_SCROLLBARS
1080 if (!modeline && NILP (w->scrollbar_on_left_p))
1081 gutter += window_scrollbar_width (w);
1084 if (window_needs_vertical_divider (w))
1085 gutter += window_divider_width (w);
1091 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1092 Return t if OBJ is a window.
1096 return WINDOWP (obj) ? Qt : Qnil;
1099 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1100 Return t if OBJ is a window which is currently visible.
1104 return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
1107 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1108 Return the window that the cursor now appears in and commands apply to.
1109 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1110 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1111 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1112 is a console, the selected frame on that console's selected device will
1113 be used. Otherwise, the selected frame is used.
1117 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1118 return Qnil; /* happens at startup */
1121 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1122 return FRAME_SELECTED_WINDOW (f);
1126 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1127 Return the window used now for minibuffers.
1128 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1129 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1130 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1131 is a console, the selected frame on that console's selected device will
1132 be used. Otherwise, the selected frame is used.
1136 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1139 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 1, 1, 0, /*
1140 Return non-nil if WINDOW is a minibuffer window.
1144 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1147 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1148 Return the first horizontal child of WINDOW, or nil.
1152 return decode_window (window)->hchild;
1155 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1156 Return the first vertical child of WINDOW, or nil.
1160 return decode_window (window)->vchild;
1163 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1164 Return the next window on the same level as WINDOW, or nil.
1168 return decode_window (window)->next;
1171 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1172 Return the previous window on the same level as WINDOW, or nil.
1176 return decode_window (window)->prev;
1179 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1180 Return the parent of WINDOW, or nil.
1184 return decode_window (window)->parent;
1187 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1188 Return non-nil if WINDOW is along the bottom of its frame.
1192 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1195 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1196 Return non-nil if WINDOW is along the top of its frame.
1200 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1203 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1204 Return non-nil if WINDOW is along the left edge of its frame.
1208 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1211 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1212 Return non-nil if WINDOW is along the right edge of its frame.
1216 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1219 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1220 Return t if position POS is currently on the frame in WINDOW.
1221 Returns nil if that position is scrolled vertically out of view.
1222 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1226 struct window *w = decode_window (window);
1227 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1229 struct buffer *buf = XBUFFER (w->buffer);
1232 posint = BUF_PT (buf);
1235 CHECK_INT_COERCE_MARKER (pos);
1236 posint = XINT (pos);
1239 if (posint < top || posint > BUF_ZV (buf))
1242 /* w->start can be out of range. If it is, do something reasonable. */
1243 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1246 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1251 decode_window (Lisp_Object window)
1254 return XWINDOW (Fselected_window (Qnil));
1256 CHECK_LIVE_WINDOW (window);
1257 return XWINDOW (window);
1260 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1261 Return the buffer that WINDOW is displaying.
1265 return decode_window (window)->buffer;
1268 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1269 Return the frame that window WINDOW is on.
1273 return decode_window (window)->frame;
1276 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1277 Return the number of default lines in WINDOW.
1278 This actually works by dividing the window's pixel height (including
1279 the modeline and horizontal scrollbar, if any) by the height of the
1280 default font; therefore, the number of displayed lines will probably
1282 Use `window-height' to get consistent results in geometry calculations.
1283 Use `window-displayed-height' to get the actual number of lines
1284 currently displayed in a window.
1288 return make_int (window_char_height (decode_window (window), 1));
1291 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1292 Return the number of lines currently displayed in WINDOW.
1293 This counts the actual number of lines displayed in WINDOW
1294 \(as opposed to `window-height'). The modeline and horizontal
1295 scrollbar do not count as lines. If there is some blank space
1296 between the end of the buffer and the end of the window, this
1297 function pretends that there are lines of text in the default
1302 return make_int (window_displayed_height (decode_window (window)));
1305 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1306 Return the height of WINDOW in pixels. Defaults to current window.
1307 This includes the window's modeline and horizontal scrollbar (if any).
1311 return make_int (decode_window (window)->pixel_height);
1314 DEFUN ("window-text-area-pixel-height",
1315 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1316 Return the height in pixels of the text-displaying portion of WINDOW.
1317 Unlike `window-pixel-height', the space occupied by the modeline and
1318 horizontal scrollbar, if any, is not counted.
1322 struct window *w = decode_window (window);
1324 return make_int (WINDOW_TEXT_HEIGHT (w));
1327 DEFUN ("window-displayed-text-pixel-height",
1328 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1329 Return the height in pixels of the text displayed in WINDOW.
1330 Unlike `window-text-area-pixel-height', any blank space below the
1331 end of the buffer is not included. If optional argument NOCLIPPED
1332 is non-nil, do not include space occupied by clipped lines.
1334 (window, noclipped))
1337 Bufpos start, eobuf;
1339 int hlimit, height, prev_height = -1;
1343 line_start_cache_dynarr *cache;
1346 window = Fselected_window (Qnil);
1348 CHECK_WINDOW (window);
1349 w = XWINDOW (window);
1351 start = marker_position (w->start[CURRENT_DISP]);
1352 hlimit = WINDOW_TEXT_HEIGHT (w);
1353 eobuf = BUF_ZV (XBUFFER (w->buffer));
1355 default_face_height_and_width (window, &defheight, NULL);
1357 /* guess lines needed in line start cache + a few extra */
1358 needed = (hlimit + defheight-1) / defheight + 3;
1361 elt = point_in_line_start_cache (w, start, needed);
1362 assert (elt >= 0); /* in the cache */
1364 cache = w->line_start_cache;
1365 nelt = Dynarr_length (cache);
1368 for (i = elt; i < nelt; i++) {
1369 line = Dynarr_atp (cache, i)->height;
1371 if (height + line > hlimit)
1372 return make_int (!NILP (noclipped) ? height : hlimit);
1376 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1377 return make_int (height);
1380 /* get here => need more cache lines. try again. */
1381 assert(height > prev_height); /* progress? */
1382 prev_height = height;
1384 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1387 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1390 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1391 Return the number of display columns in WINDOW.
1392 This is the width that is usable columns available for text in WINDOW.
1396 return make_int (window_char_width (decode_window (window), 0));
1399 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1400 Return the width of WINDOW in pixels. Defaults to current window.
1404 return make_int (decode_window (window)->pixel_width);
1407 DEFUN ("window-text-area-pixel-width",
1408 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1409 Return the width in pixels of the text-displaying portion of WINDOW.
1410 Unlike `window-pixel-width', the space occupied by the vertical
1411 scrollbar or divider, if any, is not counted.
1415 struct window *w = decode_window (window);
1417 return make_int (WINDOW_TEXT_WIDTH (w));
1420 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1421 Return the number of columns by which WINDOW is scrolled from left margin.
1425 return make_int (decode_window (window)->hscroll);
1428 #ifdef MODELINE_IS_SCROLLABLE
1429 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1430 Return the number of columns by which WINDOW's modeline is scrolled from
1431 left margin. If the window has no modeline, return nil.
1435 struct window *w = decode_window (window);
1437 return (WINDOW_HAS_MODELINE_P (w)) ? make_int (w->modeline_hscroll) : Qnil;
1440 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1441 Set number of columns WINDOW's modeline is scrolled from left margin to NCOL.
1442 NCOL should be zero or positive. If NCOL is negative, it will be forced to 0.
1443 If the window has no modeline, do nothing and return nil.
1447 struct window *w = decode_window (window);
1449 if (WINDOW_HAS_MODELINE_P (w))
1453 ncols = XINT (ncol);
1454 if (ncols < 0) ncols = 0;
1455 if (w->modeline_hscroll != ncols)
1456 MARK_MODELINE_CHANGED;
1457 w->modeline_hscroll = ncols;
1462 #endif /* MODELINE_IS_SCROLLABLE */
1464 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1465 Set number of columns WINDOW is scrolled from left margin to NCOL.
1466 NCOL should be zero or positive.
1474 ncols = XINT (ncol);
1475 if (ncols < 0) ncols = 0;
1476 w = decode_window (window);
1477 if (w->hscroll != ncols)
1478 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1483 #if 0 /* bogus FSF crock */
1485 xxDEFUN ("window-redisplay-end-trigger",
1486 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1487 Return WINDOW's redisplay end trigger value.
1488 See `set-window-redisplay-end-trigger' for more information.
1492 return decode_window (window)->redisplay_end_trigger;
1495 xxDEFUN ("set-window-redisplay-end-trigger",
1496 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1497 Set WINDOW's redisplay end trigger value to VALUE.
1498 VALUE should be a buffer position (typically a marker) or nil.
1499 If it is a buffer position, then if redisplay in WINDOW reaches a position
1500 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1501 with two arguments: WINDOW, and the end trigger value.
1502 Afterwards the end-trigger value is reset to nil.
1506 return (decode_window (window)->redisplay_end_trigger = value);
1511 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1512 Return a list of the pixel edge coordinates of WINDOW.
1513 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1514 The frame toolbars and menubars are considered to be outside of this area.
1518 struct window *w = decode_window (window);
1519 struct frame *f = XFRAME (w->frame);
1521 int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
1522 int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
1524 return list4 (make_int (left),
1526 make_int (left + w->pixel_width),
1527 make_int (top + w->pixel_height));
1530 DEFUN ("window-text-area-pixel-edges",
1531 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1532 Return a list of the pixel edge coordinates of the text area of WINDOW.
1533 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1534 top left corner of the window.
1538 struct window *w = decode_window (window);
1540 int left = window_left_gutter_width (w, /* modeline = */ 0);
1541 int top = window_top_gutter_height (w);
1542 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1543 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1545 return list4 (make_int (left),
1551 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1552 Return current value of point in WINDOW.
1553 For a nonselected window, this is the value point would have
1554 if that window were selected.
1556 Note that, when WINDOW is the selected window and its buffer
1557 is also currently selected, the value returned is the same as (point).
1558 It would be more strictly correct to return the `top-level' value
1559 of point, outside of any save-excursion forms.
1560 But that is hard to define.
1564 struct window *w = decode_window (window);
1566 /* The special check for current buffer is necessary for this
1567 function to work as defined when called within an excursion. */
1568 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1569 && current_buffer == XBUFFER (w->buffer))
1570 return Fpoint (Qnil);
1571 return Fmarker_position (w->pointm[CURRENT_DISP]);
1574 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1575 Return position at which display currently starts in WINDOW.
1576 This is updated by redisplay or by calling `set-window-start'.
1580 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1583 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1584 Return position at which display currently ends in WINDOW.
1585 This is updated by redisplay, when it runs to completion.
1586 Simply changing the buffer text or setting `window-start'
1587 does not update this value.
1588 If GUARANTEE is non-nil, then the return value is guaranteed to be
1589 the value of window-end at the end of the next full redisplay assuming
1590 nothing else changes in the meantime. This function is potentially much
1591 slower with this flag set.
1593 (window, guarantee))
1595 struct window *w = decode_window (window);
1597 if (NILP (guarantee))
1602 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1606 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1607 return make_int (end_of_last_line (w, startp));
1611 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1612 Make point value in WINDOW be at position POS in WINDOW's buffer.
1616 struct window *w = decode_window (window);
1618 CHECK_INT_COERCE_MARKER (pos);
1619 if (w == XWINDOW (Fselected_window (Qnil)))
1620 Fgoto_char (pos, Qnil);
1622 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1628 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1629 Make display in WINDOW start at position POS in WINDOW's buffer.
1630 Optional third arg NOFORCE non-nil inhibits next redisplay
1631 from overriding motion of point in order to display at this exact start.
1633 (window, pos, noforce))
1635 struct window *w = decode_window (window);
1637 CHECK_INT_COERCE_MARKER (pos);
1638 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1639 /* this is not right, but much easier than doing what is right. */
1640 /* w->start_at_line_beg = 0; */
1641 /* WTF is the above supposed to mean? GE */
1642 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1643 marker_position (w->start[CURRENT_DISP]));
1646 w->redo_modeline = 1;
1647 SET_LAST_MODIFIED (w, 0);
1648 SET_LAST_FACECHANGE (w);
1650 MARK_WINDOWS_CHANGED (w);
1655 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1656 Return WINDOW's dedicated object, usually t or nil.
1657 See also `set-window-dedicated-p'.
1661 return decode_window (window)->dedicated;
1664 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1665 Control whether WINDOW is dedicated to the buffer it displays.
1666 If it is dedicated, Emacs will not automatically change
1667 which buffer appears in it.
1668 The second argument is the new value for the dedication flag;
1673 struct window *w = decode_window (window);
1675 w->dedicated = NILP (arg) ? Qnil : Qt;
1677 return w->dedicated;
1680 /* FSFmacs has window-display-table here. We have display table as a
1684 /* Record info on buffer window w is displaying
1685 when it is about to cease to display that buffer. */
1687 unshow_buffer (struct window *w)
1689 Lisp_Object buf = w->buffer;
1691 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1694 /* FSF disables this check, so I'll do it too. I hope it won't
1695 break things. --ben */
1697 if (w == XWINDOW (Fselected_window (Qnil))
1698 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1699 /* Do this except when the selected window's buffer
1700 is being removed from some other window. */
1702 /* last_window_start records the start position that this buffer
1703 had in the last window to be disconnected from it.
1704 Now that this statement is unconditional,
1705 it is possible for the buffer to be displayed in the
1706 selected window, while last_window_start reflects another
1707 window which was recently showing the same buffer.
1708 Some people might say that might be a good thing. Let's see. */
1709 XBUFFER (buf)->last_window_start =
1710 marker_position (w->start[CURRENT_DISP]);
1712 /* Point in the selected window's buffer
1713 is actually stored in that buffer, and the window's pointm isn't used.
1714 So don't clobber point in that buffer. */
1715 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1717 struct buffer *b= XBUFFER (buf);
1718 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1719 marker_position (w->pointm[CURRENT_DISP]),
1724 /* Put REPLACEMENT into the window structure in place of OLD. */
1726 replace_window (Lisp_Object old, Lisp_Object replacement)
1729 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1731 /* If OLD is its frame's root_window, then replacement is the new
1732 root_window for that frame. */
1734 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1735 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1737 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1738 WINDOW_TOP (p) = WINDOW_TOP (o);
1739 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1740 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1742 p->next = tem = o->next;
1744 XWINDOW (tem)->prev = replacement;
1746 p->prev = tem = o->prev;
1748 XWINDOW (tem)->next = replacement;
1750 p->parent = tem = o->parent;
1753 if (EQ (XWINDOW (tem)->vchild, old))
1754 XWINDOW (tem)->vchild = replacement;
1755 if (EQ (XWINDOW (tem)->hchild, old))
1756 XWINDOW (tem)->hchild = replacement;
1759 /* #### Here, if replacement is a vertical combination
1760 and so is its new parent, we should make replacement's
1761 children be children of that parent instead. */
1764 /* we're deleting W; set the structure of W to indicate this. */
1767 mark_window_as_deleted (struct window *w)
1770 (while t (split-window) (delete-window))
1771 we end up with a tree of deleted windows which are all connected
1772 through the `next' slot. This might not seem so bad, as they're
1773 deleted, and will presumably be GCed - but if even *one* of those
1774 windows is still being pointed to, by the user, or by a window
1775 configuration, then *all* of those windows stick around.
1777 Since the window-configuration code doesn't need any of the
1778 pointers to other windows (they are all recreated from the
1779 window-config data), we set them all to nil so that we
1780 are able to collect more actual garbage.
1790 /* Free the extra data structures attached to windows immediately so
1791 they don't sit around consuming excess space. They will be
1792 reinitialized by the window-configuration code as necessary. */
1793 finalize_window ((void *) w, 0);
1796 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1797 Remove WINDOW from the display. Default is selected window.
1798 If window is the only one on the frame, the frame is destroyed.
1799 Normally, you cannot delete the last non-minibuffer-only frame (you must
1800 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1801 second argument FORCE is non-nil, you can delete the last frame. (This
1802 will automatically call `save-buffers-kill-emacs'.)
1806 /* This function can GC if this is the only window in the frame */
1814 /* Note: this function is called by other C code on non-leaf
1817 /* Do the equivalent of decode_window() but don't error out on
1818 deleted window; it's OK to delete an already-deleted window. */
1820 window = Fselected_window (Qnil);
1822 CHECK_WINDOW (window);
1823 w = XWINDOW (window);
1825 /* It's okay to delete an already-deleted window. */
1826 if (! WINDOW_LIVE_P (w))
1829 frame = WINDOW_FRAME (w);
1831 d = XDEVICE (FRAME_DEVICE (f));
1833 if (TOP_LEVEL_WINDOW_P (w))
1835 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1836 /* this frame isn't fully initialized yet; don't blow up. */
1839 if (MINI_WINDOW_P (XWINDOW (window)))
1840 error ("Attempt to delete the minibuffer window");
1842 /* It has been suggested that it's a good thing for C-x 0 to have this
1843 behavior, but not such a good idea for #'delete-window to have it.
1844 Maybe C-x 0 should be bound to something else, or maybe frame
1845 deletion should only happen when this is called interactively.
1847 delete_frame_internal (f, !NILP (force), 0, 0);
1851 /* At this point, we know the window has a parent. */
1853 par = XWINDOW (parent);
1855 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1857 /* Are we trying to delete any frame's selected window?
1858 Note that we could be dealing with a non-leaf window
1859 where the selected window is one of our children.
1860 So, we check by scanning all the ancestors of the
1861 frame's selected window and comparing each one with
1864 Lisp_Object pwindow;
1866 pwindow = FRAME_SELECTED_WINDOW (f);
1868 while (!NILP (pwindow))
1870 if (EQ (window, pwindow))
1872 pwindow = XWINDOW (pwindow)->parent;
1875 if (EQ (window, pwindow))
1877 /* OK, we found it. */
1878 Lisp_Object alternative;
1879 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1881 /* If we're about to delete the selected window on the
1882 selected frame, then we should use Fselect_window to select
1883 the new window. On the other hand, if we're about to
1884 delete the selected window on any other frame, we shouldn't do
1885 anything but set the frame's selected_window slot. */
1886 if (EQ (frame, Fselected_frame (Qnil)))
1887 Fselect_window (alternative, Qnil);
1889 set_frame_selected_window (f, alternative);
1893 /* w->buffer is nil in a non-leaf window; in this case,
1894 get rid of the markers we maintain that point into that buffer. */
1895 if (!NILP (w->buffer))
1898 unchain_marker (w->pointm[CURRENT_DISP]);
1899 unchain_marker (w->pointm[DESIRED_DISP]);
1900 unchain_marker (w->pointm[CMOTION_DISP]);
1901 unchain_marker (w->start[CURRENT_DISP]);
1902 unchain_marker (w->start[DESIRED_DISP]);
1903 unchain_marker (w->start[CMOTION_DISP]);
1904 unchain_marker (w->sb_point);
1905 /* This breaks set-window-configuration if windows in the saved
1906 configuration get deleted and multiple frames are in use. */
1907 /* w->buffer = Qnil; */
1910 /* close up the hole in the sibling list */
1911 if (!NILP (w->next))
1912 XWINDOW (w->next)->prev = w->prev;
1913 if (!NILP (w->prev))
1914 XWINDOW (w->prev)->next = w->next;
1915 if (EQ (window, par->hchild))
1916 par->hchild = w->next;
1917 if (EQ (window, par->vchild))
1918 par->vchild = w->next;
1920 /* Find one of our siblings to give our space to. */
1922 Lisp_Object sib = w->prev;
1925 /* If w gives its space to its next sibling, that sibling needs
1926 to have its top/left side pulled back to where w's is.
1927 set_window_{height,width} will re-position the sibling's
1930 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1931 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1934 /* Stretch that sibling. */
1935 if (!NILP (par->vchild))
1936 set_window_pixheight
1937 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1938 if (!NILP (par->hchild))
1940 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1943 /* If parent now has only one child,
1944 put the child into the parent's place. */
1946 Lisp_Object parchild = par->hchild;
1947 if (NILP (parchild))
1948 parchild = par->vchild;
1949 if (NILP (XWINDOW (parchild)->next))
1951 replace_window (parent, parchild);
1952 mark_window_as_deleted (XWINDOW (parent));
1956 /* Since we may be deleting combination windows, we must make sure that
1957 not only W but all its children have been marked as deleted. */
1958 if (!NILP (w->hchild))
1959 delete_all_subwindows (XWINDOW (w->hchild));
1960 else if (!NILP (w->vchild))
1961 delete_all_subwindows (XWINDOW (w->vchild));
1963 mark_window_as_deleted (w);
1965 f->mirror_dirty = 1;
1970 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1971 Return next window after WINDOW in canonical ordering of windows.
1972 If omitted, WINDOW defaults to the selected window.
1974 Optional second arg MINIBUF t means count the minibuffer window even
1975 if not active. MINIBUF nil or omitted means count the minibuffer iff
1976 it is active. MINIBUF neither t nor nil means not to count the
1977 minibuffer even if it is active.
1979 Several frames may share a single minibuffer; if the minibuffer
1980 counts, all windows on all frames that share that minibuffer count
1981 too. Therefore, `next-window' can be used to iterate through the
1982 set of windows even when the minibuffer is on another frame. If the
1983 minibuffer does not count, only windows from WINDOW's frame count.
1985 Optional third arg ALL-FRAMES t means include windows on all frames.
1986 ALL-FRAMES nil or omitted means cycle within the frames as specified
1987 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1988 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1989 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1990 Anything else means restrict to WINDOW's frame.
1992 Optional fourth argument CONSOLE controls which consoles or devices the
1993 returned window may be on. If CONSOLE is a console, return windows only
1994 on that console. If CONSOLE is a device, return windows only on that
1995 device. If CONSOLE is a console type, return windows only on consoles
1996 of that type. If CONSOLE is 'window-system, return any windows on any
1997 window-system consoles. If CONSOLE is nil or omitted, return windows only
1998 on WINDOW's console. Otherwise, all windows are considered.
2000 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2001 can use `next-window' to iterate through the entire cycle of acceptable
2002 windows, eventually ending up back at the window you started with.
2003 `previous-window' traverses the same cycle, in the reverse order.
2005 (window, minibuf, all_frames, console))
2008 Lisp_Object start_window;
2011 window = Fselected_window (Qnil);
2013 CHECK_LIVE_WINDOW (window);
2015 start_window = window;
2017 /* minibuf == nil may or may not include minibuffers.
2018 Decide if it does. */
2020 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2021 else if (! EQ (minibuf, Qt))
2023 /* Now minibuf can be t => count all minibuffer windows,
2024 lambda => count none of them,
2025 or a specific minibuffer window (the active one) to count. */
2027 /* all_frames == nil doesn't specify which frames to include. */
2028 if (NILP (all_frames))
2029 all_frames = (! EQ (minibuf, Qlambda)
2030 ? (FRAME_MINIBUF_WINDOW
2033 (XWINDOW (window)))))
2035 else if (EQ (all_frames, Qvisible))
2037 else if (ZEROP (all_frames))
2039 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2040 /* If all_frames is a frame and window arg isn't on that frame, just
2041 return the first window on the frame. */
2042 return frame_first_window (XFRAME (all_frames));
2043 else if (! EQ (all_frames, Qt))
2045 /* Now all_frames is t meaning search all frames,
2046 nil meaning search just current frame,
2047 visible meaning search just visible frames,
2048 0 meaning search visible and iconified frames,
2049 or a window, meaning search the frame that window belongs to. */
2051 /* Do this loop at least once, to get the next window, and perhaps
2052 again, if we hit the minibuffer and that is not acceptable. */
2055 /* Find a window that actually has a next one. This loop
2056 climbs up the tree. */
2057 while (tem = XWINDOW (window)->next, NILP (tem))
2058 if (tem = XWINDOW (window)->parent, !NILP (tem))
2060 else /* window must be minibuffer window now */
2062 /* We've reached the end of this frame.
2063 Which other frames are acceptable? */
2064 tem = WINDOW_FRAME (XWINDOW (window));
2066 if (! NILP (all_frames))
2071 tem = next_frame (tem, all_frames, console);
2072 /* In the case where the minibuffer is active,
2073 and we include its frame as well as the selected one,
2074 next_frame may get stuck in that frame.
2075 If that happens, go back to the selected frame
2076 so we can complete the cycle. */
2078 XSETFRAME (tem, selected_frame ());
2081 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2087 /* If we're in a combination window, find its first child and
2088 recurse on that. Otherwise, we've found the window we want. */
2091 if (!NILP (XWINDOW (window)->hchild))
2092 window = XWINDOW (window)->hchild;
2093 else if (!NILP (XWINDOW (window)->vchild))
2094 window = XWINDOW (window)->vchild;
2098 /* "acceptable" is the correct spelling. */
2099 /* Which windows are acceptable?
2100 Exit the loop and accept this window if
2101 this isn't a minibuffer window,
2102 or we're accepting all minibuffer windows,
2103 or this is the active minibuffer and we are accepting that one, or
2104 we've come all the way around and we're back at the original window. */
2105 while (MINI_WINDOW_P (XWINDOW (window))
2106 && ! EQ (minibuf, Qt)
2107 && ! EQ (minibuf, window)
2108 && ! EQ (window, start_window));
2113 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2114 Return the window preceding WINDOW in canonical ordering of windows.
2115 If omitted, WINDOW defaults to the selected window.
2117 Optional second arg MINIBUF t means count the minibuffer window even
2118 if not active. MINIBUF nil or omitted means count the minibuffer iff
2119 it is active. MINIBUF neither t nor nil means not to count the
2120 minibuffer even if it is active.
2122 Several frames may share a single minibuffer; if the minibuffer
2123 counts, all windows on all frames that share that minibuffer count
2124 too. Therefore, `previous-window' can be used to iterate through
2125 the set of windows even when the minibuffer is on another frame. If
2126 the minibuffer does not count, only windows from WINDOW's frame count
2128 If optional third arg ALL-FRAMES t means include windows on all frames.
2129 ALL-FRAMES nil or omitted means cycle within the frames as specified
2130 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2131 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2132 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2133 Anything else means restrict to WINDOW's frame.
2135 Optional fourth argument CONSOLE controls which consoles or devices the
2136 returned window may be on. If CONSOLE is a console, return windows only
2137 on that console. If CONSOLE is a device, return windows only on that
2138 device. If CONSOLE is a console type, return windows only on consoles
2139 of that type. If CONSOLE is 'window-system, return any windows on any
2140 window-system consoles. If CONSOLE is nil or omitted, return windows only
2141 on WINDOW's console. Otherwise, all windows are considered.
2143 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2144 can use `previous-window' to iterate through the entire cycle of acceptable
2145 windows, eventually ending up back at the window you started with.
2146 `next-window' traverses the same cycle, in the reverse order.
2148 (window, minibuf, all_frames, console))
2151 Lisp_Object start_window;
2154 window = Fselected_window (Qnil);
2156 CHECK_LIVE_WINDOW (window);
2158 start_window = window;
2160 /* minibuf == nil may or may not include minibuffers.
2161 Decide if it does. */
2163 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2164 else if (! EQ (minibuf, Qt))
2166 /* Now minibuf can be t => count all minibuffer windows,
2167 lambda => count none of them,
2168 or a specific minibuffer window (the active one) to count. */
2170 /* all_frames == nil doesn't specify which frames to include.
2171 Decide which frames it includes. */
2172 if (NILP (all_frames))
2173 all_frames = (! EQ (minibuf, Qlambda)
2174 ? (FRAME_MINIBUF_WINDOW
2177 (XWINDOW (window)))))
2179 else if (EQ (all_frames, Qvisible))
2181 else if (ZEROP (all_frames))
2183 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2184 /* If all_frames is a frame and window arg isn't on that frame, just
2185 return the first window on the frame. */
2186 return frame_first_window (XFRAME (all_frames));
2187 else if (! EQ (all_frames, Qt))
2189 /* Now all_frames is t meaning search all frames,
2190 nil meaning search just current frame,
2191 visible meaning search just visible frames,
2192 0 meaning search visible and iconified frames,
2193 or a window, meaning search the frame that window belongs to. */
2195 /* Do this loop at least once, to get the next window, and perhaps
2196 again, if we hit the minibuffer and that is not acceptable. */
2199 /* Find a window that actually has a next one. This loop
2200 climbs up the tree. */
2201 while (tem = XWINDOW (window)->prev, NILP (tem))
2202 if (tem = XWINDOW (window)->parent, !NILP (tem))
2204 else /* window must be minibuffer window now */
2206 /* We have found the top window on the frame.
2207 Which frames are acceptable? */
2208 tem = WINDOW_FRAME (XWINDOW (window));
2210 if (! NILP (all_frames))
2211 /* It's actually important that we use prev_frame here,
2212 rather than next_frame. All the windows acceptable
2213 according to the given parameters should form a ring;
2214 Fnext_window and Fprevious_window should go back and
2215 forth around the ring. If we use next_frame here,
2216 then Fnext_window and Fprevious_window take different
2217 paths through the set of acceptable windows.
2218 window_loop assumes that these `ring' requirement are
2224 tem = prev_frame (tem, all_frames, console);
2225 /* In the case where the minibuffer is active,
2226 and we include its frame as well as the selected one,
2227 next_frame may get stuck in that frame.
2228 If that happens, go back to the selected frame
2229 so we can complete the cycle. */
2231 XSETFRAME (tem, selected_frame ());
2234 /* If this frame has a minibuffer, find that window first,
2235 because it is conceptually the last window in that frame. */
2236 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2237 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2239 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2246 /* If we're in a combination window, find its first child and
2247 recurse on that. Otherwise, we've found the window we want. */
2250 if (!NILP (XWINDOW (window)->hchild))
2251 window = XWINDOW (window)->hchild;
2252 else if (!NILP (XWINDOW (window)->vchild))
2253 window = XWINDOW (window)->vchild;
2255 while (tem = XWINDOW (window)->next, !NILP (tem))
2259 /* Which windows are acceptable?
2260 Exit the loop and accept this window if
2261 this isn't a minibuffer window,
2262 or we're accepting all minibuffer windows,
2263 or this is the active minibuffer and we are accepting that one, or
2264 we've come all the way around and we're back at the original window. */
2265 while (MINI_WINDOW_P (XWINDOW (window))
2266 && ! EQ (minibuf, Qt)
2267 && ! EQ (minibuf, window)
2268 && ! EQ (window, start_window));
2273 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2274 Return the next window which is vertically after WINDOW.
2279 struct window *w = decode_window (window);
2280 XSETWINDOW (window, w);
2282 if (MINI_WINDOW_P (XWINDOW (window)))
2285 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2287 if (EQ (window, root))
2290 if (!NILP (XWINDOW (window)->hchild))
2291 window = XWINDOW (window)->hchild;
2292 else if (!NILP (XWINDOW (window)->vchild))
2293 window = XWINDOW (window)->vchild;
2300 if (!NILP (XWINDOW (window)->parent) &&
2301 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2303 if (!NILP (XWINDOW (window)->next))
2304 return XWINDOW (window)->next;
2306 window = XWINDOW (window)->parent;
2309 window = XWINDOW (window)->parent;
2311 while (!EQ (window, root));
2314 if (!NILP (XWINDOW (window)->hchild))
2315 window = XWINDOW (window)->hchild;
2316 else if (!NILP (XWINDOW (window)->vchild))
2317 window = XWINDOW (window)->vchild;
2322 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2323 Select the N'th different window on this frame.
2324 All windows on current frame are arranged in a cyclic order.
2325 This command selects the window N steps away in that order.
2326 A negative N moves in the opposite order.
2328 If optional argument FRAME is `visible', search all visible frames.
2329 If FRAME is 0, search all visible and iconified frames.
2330 If FRAME is t, search all frames.
2331 If FRAME is nil, search only the selected frame.
2332 If FRAME is a frame, search only that frame.
2334 Optional third argument CONSOLE controls which consoles or devices the
2335 returned window may be on. If CONSOLE is a console, return windows only
2336 on that console. If CONSOLE is a device, return windows only on that
2337 device. If CONSOLE is a console type, return windows only on consoles
2338 of that type. If CONSOLE is 'window-system, return any windows on any
2339 window-system consoles. If CONSOLE is nil or omitted, return windows only
2340 on FRAME'S console, or on the selected console if FRAME is not a frame.
2341 Otherwise, all windows are considered.
2343 (n, frame, console))
2349 w = Fselected_window (Qnil);
2354 w = Fnext_window (w, Qnil, frame, console);
2359 w = Fprevious_window (w, Qnil, frame, console);
2362 Fselect_window (w, Qnil);
2367 /* Look at all windows, performing an operation specified by TYPE
2370 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2371 frame. If FRAMES is a frame, just look at windows on that frame.
2372 If MINI is non-zero, perform the operation on minibuffer windows too.
2378 GET_BUFFER_WINDOW, /* Arg is buffer */
2379 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2380 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2381 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2383 UNSHOW_BUFFER, /* Arg is buffer */
2384 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2385 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2389 window_loop (enum window_loop type,
2394 Lisp_Object console)
2396 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2398 Lisp_Object best_window = Qnil;
2399 Lisp_Object next_window;
2400 Lisp_Object last_window;
2401 struct frame *frame;
2402 Lisp_Object frame_arg = Qt;
2403 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2404 /* #### I think the change of "precomputing" last_window and next_window
2405 * #### catch the lossage this is meant(?) to punt on...
2408 Lisp_Object devcons, concons;
2410 /* FRAME_ARG is Qlambda to stick to one frame,
2411 Qvisible to consider all visible frames,
2414 /* If we're only looping through windows on a particular frame,
2415 FRAME points to that frame. If we're looping through windows
2416 on all frames, FRAME is 0. */
2418 if (FRAMEP (frames))
2419 frame = XFRAME (frames);
2420 else if (NILP (frames))
2421 frame = selected_frame ();
2425 frame_arg = Qlambda;
2426 else if (ZEROP (frames))
2428 else if (EQ (frames, Qvisible))
2431 DEVICE_LOOP_NO_BREAK (devcons, concons)
2433 Lisp_Object device = XCAR (devcons);
2434 Lisp_Object the_frame;
2437 XSETFRAME (the_frame, frame);
2439 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2441 if (NILP (the_frame))
2444 if (!device_matches_console_spec (the_frame, device, console))
2447 /* Pick a window to start with. */
2451 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2453 /* Figure out the last window we're going to mess with. Since
2454 Fnext_window, given the same options, is guaranteed to go in a
2455 ring, we can just use Fprevious_window to find the last one.
2457 We can't just wait until we hit the first window again,
2458 because it might be deleted. */
2460 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2465 struct window *p = XWINDOW (w);
2466 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2468 /* Pick the next window now, since some operations will delete
2469 the current window. */
2470 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2472 /* #### Still needed ?? */
2473 /* Given the outstanding quality of the rest of this code,
2474 I feel no shame about putting this piece of shit in. */
2475 if (++lose_lose >= 500)
2478 /* Note that we do not pay attention here to whether
2479 the frame is visible, since Fnext_window skips non-visible frames
2480 if that is desired, under the control of frame_arg. */
2481 if (! MINI_WINDOW_P (p)
2482 || (mini && minibuf_level > 0))
2485 case GET_BUFFER_WINDOW:
2487 if (XBUFFER (p->buffer) == XBUFFER (obj))
2492 case GET_BUFFER_WINDOW_COUNT:
2494 if (XBUFFER (p->buffer) == XBUFFER (obj))
2499 case GET_LRU_WINDOW:
2501 /* t as arg means consider only full-width windows */
2503 && !window_full_width_p (p))
2505 /* Ignore dedicated windows and minibuffers. */
2506 if (MINI_WINDOW_P (p)
2507 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2509 if (NILP (best_window)
2510 || (XINT (XWINDOW (best_window)->use_time)
2511 > XINT (p->use_time)))
2516 case GET_BUFFER_MRU_WINDOW:
2518 /* #### what about the first check in GET_LRU_WINDOW? */
2519 /* Ignore dedicated windows and minibuffers. */
2520 if (MINI_WINDOW_P (p)
2521 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2524 if (XBUFFER (p->buffer) == XBUFFER (obj))
2526 if (NILP (best_window)
2527 || (XINT (XWINDOW (best_window)->use_time)
2528 < XINT (p->use_time)))
2534 case DELETE_OTHER_WINDOWS:
2536 /* Don't delete the last window on a frame; this can
2537 happen when the minibuffer is selected, and would
2538 cause the frame to be deleted. */
2539 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2540 Fdelete_window (w, Qnil);
2544 case DELETE_BUFFER_WINDOWS:
2546 if (EQ (p->buffer, obj))
2548 struct frame *f = XFRAME (WINDOW_FRAME (p));
2550 /* If this window is dedicated, and in a frame
2551 of its own, kill the frame. */
2552 if (EQ (w, FRAME_ROOT_WINDOW (f))
2553 && !NILP (p->dedicated)
2554 && other_visible_frames (f))
2556 /* Skip the other windows on this frame.
2557 There might be one, the minibuffer! */
2558 if (! EQ (w, last_window))
2559 while (f == XFRAME (WINDOW_FRAME
2560 (XWINDOW (next_window))))
2562 /* As we go, check for the end of the
2563 loop. We mustn't start going
2564 around a second time. */
2565 if (EQ (next_window, last_window))
2570 next_window = Fnext_window (next_window,
2574 /* Now we can safely delete the frame. */
2575 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2578 /* If we're deleting the buffer displayed in
2579 the only window on the frame, find a new
2580 buffer to display there. */
2581 if (NILP (p->parent))
2583 Lisp_Object new_buffer;
2584 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2585 if (NILP (new_buffer))
2586 new_buffer = Fget_buffer_create (QSscratch);
2587 Fset_window_buffer (w, new_buffer);
2588 if (EQ (w, Fselected_window (Qnil)))
2589 Fset_buffer (p->buffer);
2592 Fdelete_window (w, Qnil);
2597 case GET_LARGEST_WINDOW:
2599 /* Ignore dedicated windows and minibuffers. */
2600 if (MINI_WINDOW_P (p)
2601 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2604 /* write the check as follows to avoid tripping
2605 error_check_window() --ben */
2606 struct window *b = NILP (best_window) ? 0 :
2607 XWINDOW (best_window);
2608 if (NILP (best_window)
2609 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2610 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2618 if (EQ (p->buffer, obj))
2620 /* Find another buffer to show in this window. */
2621 Lisp_Object another_buffer =
2622 Fother_buffer (obj, Qnil, Qnil);
2623 if (NILP (another_buffer))
2625 = Fget_buffer_create (QSscratch);
2626 /* If this window is dedicated, and in a frame
2627 of its own, kill the frame. */
2628 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2629 && !NILP (p->dedicated)
2630 && other_visible_frames (w_frame))
2632 /* Skip the other windows on this frame.
2633 There might be one, the minibuffer! */
2634 if (! EQ (w, last_window))
2635 while (w_frame == XFRAME (WINDOW_FRAME
2636 (XWINDOW (next_window))))
2638 /* As we go, check for the end of the
2639 loop. We mustn't start going
2640 around a second time. */
2641 if (EQ (next_window, last_window))
2646 next_window = Fnext_window (next_window,
2650 /* Now we can safely delete the frame. */
2651 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2656 /* Otherwise show a different buffer in the
2658 p->dedicated = Qnil;
2659 Fset_window_buffer (w, another_buffer);
2660 if (EQ (w, Fselected_window (Qnil)))
2661 Fset_buffer (p->buffer);
2671 if (EQ (w, last_window))
2678 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2681 #if 0 /* not currently used */
2684 buffer_window_count (struct buffer *b, struct frame *f)
2686 Lisp_Object buffer, frame;
2688 XSETFRAME (frame, f);
2689 XSETBUFFER (buffer, b);
2691 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2696 buffer_window_mru (struct window *w)
2698 Lisp_Object window =
2699 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2703 else if (XWINDOW (window) == w)
2712 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2713 Return the window least recently selected or used for display.
2714 If optional argument FRAME is `visible', search all visible frames.
2715 If FRAME is 0, search all visible and iconified frames.
2716 If FRAME is t, search all frames.
2717 If FRAME is nil, search only the selected frame.
2718 If FRAME is a frame, search only that frame.
2720 Optional second argument CONSOLE controls which consoles or devices the
2721 returned window may be on. If CONSOLE is a console, return windows only
2722 on that console. If CONSOLE is a device, return windows only on that
2723 device. If CONSOLE is a console type, return windows only on consoles
2724 of that type. If CONSOLE is 'window-system, return any windows on any
2725 window-system consoles. If CONSOLE is nil or omitted, return windows only
2726 on FRAME'S console, or on the selected console if FRAME is not a frame.
2727 Otherwise, all windows are considered.
2732 /* First try for a non-dedicated window that is full-width */
2733 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2734 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2737 /* Then try for any non-dedicated window */
2738 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2739 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2743 /* FSFmacs never returns a dedicated window here. If we do,
2744 it makes `display-buffer' not work right. #### All of this
2745 shit is so disgusting and awful that it needs to be rethought
2747 /* then try for a dedicated window that is full-width */
2748 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2749 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2752 /* If none of them, then all windows, dedicated or not. */
2753 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2755 /* At this point we damn well better have found something. */
2756 if (NILP (w)) abort ();
2762 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2763 Return the window largest in area.
2764 If optional argument FRAME is `visible', search all visible frames.
2765 If FRAME is 0, search all visible and iconified frames.
2766 If FRAME is t, search all frames.
2767 If FRAME is nil, search only the selected frame.
2768 If FRAME is a frame, search only that frame.
2770 Optional second argument CONSOLE controls which consoles or devices the
2771 returned window may be on. If CONSOLE is a console, return windows only
2772 on that console. If CONSOLE is a device, return windows only on that
2773 device. If CONSOLE is a console type, return windows only on consoles
2774 of that type. If CONSOLE is 'window-system, return any windows on any
2775 window-system consoles. If CONSOLE is nil or omitted, return windows only
2776 on FRAME'S console, or on the selected console if FRAME is not a frame.
2777 Otherwise, all windows are considered.
2781 /* Don't search dedicated windows because FSFmacs doesn't.
2782 This stuff is all black magic so don't try to apply common
2784 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2787 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2788 Return a window currently displaying BUFFER, or nil if none.
2789 If optional argument FRAME is `visible', search all visible frames.
2790 If optional argument FRAME is 0, search all visible and iconified frames.
2791 If FRAME is t, search all frames.
2792 If FRAME is nil, search only the selected frame.
2793 If FRAME is a frame, search only that frame.
2795 Optional third argument CONSOLE controls which consoles or devices the
2796 returned window may be on. If CONSOLE is a console, return windows only
2797 on that console. If CONSOLE is a device, return windows only on that
2798 device. If CONSOLE is a console type, return windows only on consoles
2799 of that type. If CONSOLE is 'window-system, return any windows on any
2800 window-system consoles. If CONSOLE is nil or omitted, return windows only
2801 on FRAME'S console, or on the selected console if FRAME is not a frame.
2802 Otherwise, all windows are considered.
2804 (buffer, frame, console))
2806 buffer = Fget_buffer (buffer);
2807 if (BUFFERP (buffer))
2808 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2809 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2814 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2815 but there is no sensible way to implement those functions, since
2816 you can't in general derive a window from a buffer. */
2818 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2820 Return the width in pixels of the left outside margin of window WINDOW.
2821 If WINDOW is nil, the selected window is assumed.
2825 return make_int (window_left_margin_width (decode_window (window)));
2828 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2830 Return the width in pixels of the right outside margin of window WINDOW.
2831 If WINDOW is nil, the selected window is assumed.
2835 return make_int (window_right_margin_width (decode_window (window)));
2838 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2839 Make WINDOW (or the selected window) fill its frame.
2840 Only the frame WINDOW is on is affected.
2841 This function tries to reduce display jumps
2842 by keeping the text previously visible in WINDOW
2843 in the same place on the frame. Doing this depends on
2844 the value of (window-start WINDOW), so if calling this function
2845 in a program gives strange scrolling, make sure the window-start
2846 value is reasonable when this function is called.
2850 struct window *w = decode_window (window);
2851 struct buffer *b = XBUFFER (w->buffer);
2853 int old_top = WINDOW_TOP (w);
2855 XSETWINDOW (window, w);
2857 if (MINI_WINDOW_P (w) && old_top > 0)
2858 error ("Can't expand minibuffer to full frame");
2860 /* Ignore dedicated windows. */
2861 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2863 start_pos = marker_position (w->start[CURRENT_DISP]);
2865 /* Try to minimize scrolling, by setting the window start to the
2866 point which will cause the text at the old window start to be at
2867 the same place on the frame. But don't try to do this if the
2868 window start is outside the visible portion (as might happen when
2869 the display is not current, due to typeahead). */
2870 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2871 && !MINI_WINDOW_P (w))
2873 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2875 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2877 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2879 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2881 /* We need to do this, so that the window-scroll-functions
2889 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2890 "bDelete windows on (buffer): ", /*
2891 Delete all windows showing BUFFER.
2892 Optional second argument FRAME controls which frames are affected.
2893 If nil or omitted, delete all windows showing BUFFER in any frame.
2894 If t, delete only windows showing BUFFER in the selected frame.
2895 If `visible', delete all windows showing BUFFER in any visible frame.
2896 If a frame, delete only windows showing BUFFER in that frame.
2898 Optional third argument CONSOLE controls which consoles or devices the
2899 returned window may be on. If CONSOLE is a console, return windows only
2900 on that console. If CONSOLE is a device, return windows only on that
2901 device. If CONSOLE is a console type, return windows only on consoles
2902 of that type. If CONSOLE is 'window-system, return any windows on any
2903 window-system consoles. If CONSOLE is nil or omitted, return windows only
2904 on FRAME'S console, or on the selected console if FRAME is not a frame.
2905 Otherwise, all windows are considered.
2907 (buffer, frame, console))
2909 /* This function can GC */
2910 /* FRAME uses t and nil to mean the opposite of what window_loop
2912 if (!FRAMEP (frame))
2913 frame = NILP (frame) ? Qt : Qnil;
2917 buffer = Fget_buffer (buffer);
2918 CHECK_BUFFER (buffer);
2919 /* Ignore dedicated windows. */
2920 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2925 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2926 "bReplace buffer in windows: ", /*
2927 Replace BUFFER with some other buffer in all windows showing it.
2931 /* This function can GC */
2934 buffer = Fget_buffer (buffer);
2935 CHECK_BUFFER (buffer);
2936 /* Ignore dedicated windows. */
2937 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2942 /* The smallest acceptable dimensions for a window. Anything smaller
2943 might crash Emacs. */
2944 #define MIN_SAFE_WINDOW_WIDTH (2)
2945 #define MIN_SAFE_WINDOW_HEIGHT (2)
2947 /* Make sure that window_min_height and window_min_width are
2948 not too small; if they are, set them to safe minima. */
2951 check_min_window_sizes (void)
2953 /* Smaller values might permit a crash. */
2954 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2955 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2956 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2957 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2960 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2961 minimum allowable size. */
2963 check_frame_size (struct frame *frame, int *rows, int *cols)
2965 /* For height, we have to see whether the frame has a minibuffer, and
2966 whether it wants a modeline. */
2968 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2969 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2970 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2972 if (*rows < min_height)
2974 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2975 *cols = MIN_SAFE_WINDOW_WIDTH;
2978 /* Normally the window is deleted if it gets too small.
2979 nodelete nonzero means do not do this.
2980 (The caller should check later and do so if appropriate) */
2982 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
2985 struct window *w = XWINDOW (window);
2986 struct frame *f = XFRAME (w->frame);
2988 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
2989 Lisp_Object child, minor_kid, major_kid;
2992 int defheight, defwidth;
2994 /* #### This is very likely incorrect and instead the char_to_pixel_
2995 functions should be called. */
2996 default_face_height_and_width (window, &defheight, &defwidth);
2997 line_size = (set_height ? defheight : defwidth);
2999 check_min_window_sizes ();
3001 minsize = (set_height ? window_min_height : window_min_width);
3002 minsize *= line_size;
3005 && !TOP_LEVEL_WINDOW_P (w)
3006 && new_pixsize < minsize)
3008 Fdelete_window (window, Qnil);
3012 SET_LAST_MODIFIED (w, 0);
3013 SET_LAST_FACECHANGE (w);
3014 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3017 WINDOW_HEIGHT (w) = new_pixsize;
3018 major_kid = w->vchild;
3019 minor_kid = w->hchild;
3023 WINDOW_WIDTH (w) = new_pixsize;
3024 major_kid = w->hchild;
3025 minor_kid = w->vchild;
3028 if (!NILP (minor_kid))
3030 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3033 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3035 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3037 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3040 else if (!NILP (major_kid))
3042 int last_pos, last_old_pos, pos, old_pos, first;
3043 int pixel_adj_left = new_pixsize - old_pixsize;
3044 int div_val = old_pixsize << 1;
3047 * Previously we bailed out here if there was no size change.
3048 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3049 * toolbar appears or disappears, windows may not change size,
3050 * but their top and left coordinates need to be updated.
3052 * So we don't bail until after the loop below.
3055 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3058 for (child = major_kid; !NILP (child); child = c->next)
3060 c = XWINDOW (child);
3064 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3065 WINDOW_TOP (c) = last_pos;
3069 old_pos = last_old_pos + WINDOW_WIDTH (c);
3070 WINDOW_LEFT (c) = last_pos;
3073 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3074 /* All but the last window should have a height which is
3075 a multiple of the default line height. */
3076 if (!NILP (c->next))
3077 pos = (pos / line_size) * line_size;
3079 /* Avoid confusion: don't delete child if it becomes too small */
3080 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3082 last_pos = pos + first;
3083 last_old_pos = old_pos;
3086 /* Sometimes we may get called with our old size. In that case
3087 we don't need to do anything else. */
3088 if (!pixel_adj_left)
3091 /* Now delete any children that became too small. */
3093 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3096 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3098 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3103 /* Set the height of WINDOW and all its inferiors. */
3105 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3107 set_window_pixsize (window, new_pixheight, nodelete, 1);
3110 /* Recursively set width of WINDOW and its inferiors. */
3112 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3114 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3118 static int window_select_count;
3120 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3121 Make WINDOW display BUFFER as its contents.
3122 BUFFER can be a buffer or buffer name.
3127 struct window *w = decode_window (window);
3129 buffer = Fget_buffer (buffer);
3130 CHECK_BUFFER (buffer);
3132 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3133 error ("Attempt to display deleted buffer");
3137 error ("Window is deleted");
3139 /* While this seems like a logical thing to do, it causes problems
3140 because of saved window configurations. It is possible for a
3141 buffer to get restored into a window in which it is already being
3142 displayed, but start and point are actually at completely
3143 different locations. So we let this function complete fully and
3144 it will then make sure redisplay correctly updates things.
3146 #### This is a kludge. The correct approach is not to do this
3147 but to fix set-window-configuration. */
3149 else if (EQ (tem, buffer))
3152 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3153 is first being set up. */
3155 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3156 error ("Window is dedicated to buffer %s",
3157 XSTRING_DATA (XBUFFER (tem)->name));
3163 w->window_end_pos[CURRENT_DISP] = 0;
3165 w->modeline_hscroll = 0;
3166 Fset_marker (w->pointm[CURRENT_DISP],
3167 make_int (BUF_PT (XBUFFER (buffer))),
3169 set_marker_restricted (w->start[CURRENT_DISP],
3170 make_int (XBUFFER (buffer)->last_window_start),
3172 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3173 /* set start_at_line_beg correctly. GE */
3174 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3175 marker_position (w->start[CURRENT_DISP]));
3176 w->force_start = 0; /* Lucid fix */
3177 SET_LAST_MODIFIED (w, 1);
3178 SET_LAST_FACECHANGE (w);
3179 MARK_WINDOWS_CHANGED (w);
3180 recompute_all_cached_specifiers_in_window (w);
3181 if (EQ (window, Fselected_window (Qnil)))
3183 Fset_buffer (buffer);
3188 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3189 Select WINDOW. Most editing will apply to WINDOW's buffer.
3190 The main editor command loop selects the buffer of the selected window
3191 before each command.
3193 With non-nil optional argument `norecord', do not modify the
3194 global or per-frame buffer ordering.
3199 Lisp_Object old_selected_window = Fselected_window (Qnil);
3201 CHECK_LIVE_WINDOW (window);
3202 w = XWINDOW (window);
3204 /* we have already caught dead-window errors */
3205 if (!NILP (w->hchild) || !NILP (w->vchild))
3206 error ("Trying to select non-leaf window");
3208 w->use_time = make_int (++window_select_count);
3209 if (EQ (window, old_selected_window))
3212 /* deselect the old window, if it exists (it might not exist if
3213 the selected device has no frames, which occurs at startup) */
3214 if (!NILP (old_selected_window))
3216 struct window *ow = XWINDOW (old_selected_window);
3218 Fset_marker (ow->pointm[CURRENT_DISP],
3219 make_int (BUF_PT (XBUFFER (ow->buffer))),
3222 MARK_WINDOWS_CHANGED (ow);
3225 /* now select the window's frame */
3226 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3228 select_frame_1 (WINDOW_FRAME (w));
3230 /* also select the window's buffer */
3231 if (NILP (norecord))
3232 Frecord_buffer (w->buffer);
3233 Fset_buffer (w->buffer);
3235 /* Go to the point recorded in the window.
3236 This is important when the buffer is in more
3237 than one window. It also matters when
3238 redisplay_window has altered point after scrolling,
3239 because it makes the change only in the window. */
3241 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3242 if (new_point < BUF_BEGV (current_buffer))
3243 new_point = BUF_BEGV (current_buffer);
3244 else if (new_point > BUF_ZV (current_buffer))
3245 new_point = BUF_ZV (current_buffer);
3247 BUF_SET_PT (current_buffer, new_point);
3250 MARK_WINDOWS_CHANGED (w);
3256 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3257 Lisp_Object override_frame)
3259 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3263 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3265 /* This function can GC */
3268 struct buffer *b = XBUFFER (buf);
3270 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3271 widen_buffer (b, 0);
3272 BUF_SET_PT (b, BUF_BEG (b));
3274 if (!NILP (Vtemp_buffer_show_function))
3275 call1 (Vtemp_buffer_show_function, buf);
3278 window = display_buffer (buf, Qnil, same_frame);
3280 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3281 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3283 Vminibuffer_scroll_window = window;
3284 w = XWINDOW (window);
3286 w->modeline_hscroll = 0;
3287 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3288 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3289 set_marker_restricted (w->sb_point, make_int (1), buf);
3291 /* Run temp-buffer-show-hook, with the chosen window selected. */
3292 if (!preparing_for_armageddon)
3295 tem = Fboundp (Qtemp_buffer_show_hook);
3298 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3301 int count = specpdl_depth ();
3303 /* Select the window that was chosen, for running
3305 record_unwind_protect (save_window_excursion_unwind,
3306 Fcurrent_window_configuration (Qnil));
3308 Fselect_window (window, Qnil);
3309 run_hook (Qtemp_buffer_show_hook);
3310 unbind_to (count, Qnil);
3318 make_dummy_parent (Lisp_Object window)
3321 struct window *o = XWINDOW (window);
3322 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
3324 XSETWINDOW (new, p);
3325 copy_lcrecord (p, o);
3327 /* Don't copy the pointers to the line start cache or the face
3329 p->line_start_cache = Dynarr_new (line_start_cache);
3330 p->face_cachels = Dynarr_new (face_cachel);
3331 p->glyph_cachels = Dynarr_new (glyph_cachel);
3333 /* Put new into window structure in place of window */
3334 replace_window (window, new);
3342 p->start[CURRENT_DISP] = Qnil;
3343 p->start[DESIRED_DISP] = Qnil;
3344 p->start[CMOTION_DISP] = Qnil;
3345 p->pointm[CURRENT_DISP] = Qnil;
3346 p->pointm[DESIRED_DISP] = Qnil;
3347 p->pointm[CMOTION_DISP] = Qnil;
3352 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3353 Split WINDOW, putting SIZE lines in the first of the pair.
3354 WINDOW defaults to selected one and SIZE to half its size.
3355 If optional third arg HOR-FLAG is non-nil, split side by side
3356 and put SIZE columns in the first of the pair.
3358 (window, chsize, horflag))
3361 struct window *o, *p;
3367 window = Fselected_window (Qnil);
3369 CHECK_WINDOW (window);
3371 o = XWINDOW (window);
3372 f = XFRAME (WINDOW_FRAME (o));
3376 if (!NILP (horflag))
3377 /* In the new scheme, we are symmetric with respect to separators
3378 so there is no need to do weird things here. */
3380 psize = WINDOW_WIDTH (o) >> 1;
3381 size = window_pixel_width_to_char_width (o, psize, 0);
3385 psize = WINDOW_HEIGHT (o) >> 1;
3386 size = window_pixel_height_to_char_height (o, psize, 1);
3392 size = XINT (chsize);
3393 if (!NILP (horflag))
3394 psize = window_char_width_to_pixel_width (o, size, 0);
3396 psize = window_char_height_to_pixel_height (o, size, 1);
3399 if (MINI_WINDOW_P (o))
3400 error ("Attempt to split minibuffer window");
3401 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3402 error ("Attempt to split unsplittable frame");
3404 check_min_window_sizes ();
3408 if (size < window_min_height)
3409 error ("Window height %d too small (after splitting)", size);
3410 if (size + window_min_height > window_char_height (o, 1))
3411 error ("Window height %d too small (after splitting)",
3412 window_char_height (o, 1) - size);
3413 if (NILP (o->parent)
3414 || NILP (XWINDOW (o->parent)->vchild))
3416 make_dummy_parent (window);
3417 reset_face_cachels (XWINDOW (window));
3419 XWINDOW (new)->vchild = window;
3420 XFRAME (o->frame)->mirror_dirty = 1;
3425 if (size < window_min_width)
3426 error ("Window width %d too small (after splitting)", size);
3427 if (size + window_min_width > window_char_width (o, 0))
3428 error ("Window width %d too small (after splitting)",
3429 window_char_width (o, 0) - size);
3430 if (NILP (o->parent)
3431 || NILP (XWINDOW (o->parent)->hchild))
3433 make_dummy_parent (window);
3434 reset_face_cachels (XWINDOW (window));
3436 XWINDOW (new)->hchild = window;
3437 XFRAME (o->frame)->mirror_dirty = 1;
3441 /* Now we know that window's parent is a vertical combination
3442 if we are dividing vertically, or a horizontal combination
3443 if we are making side-by-side windows */
3445 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3446 new = allocate_window ();
3449 p->frame = o->frame;
3451 if (!NILP (p->next))
3452 XWINDOW (p->next)->prev = new;
3455 p->parent = o->parent;
3458 reset_face_cachels (p);
3459 reset_glyph_cachels (p);
3462 /* Apportion the available frame space among the two new windows */
3464 if (!NILP (horflag))
3466 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3467 WINDOW_TOP (p) = WINDOW_TOP (o);
3468 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3469 WINDOW_WIDTH (o) = psize;
3470 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3474 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3475 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3476 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3477 WINDOW_HEIGHT (o) = psize;
3478 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3481 XFRAME (p->frame)->mirror_dirty = 1;
3482 /* do this last (after the window is completely initialized and
3483 the mirror-dirty flag is set) so that specifier recomputation
3484 caused as a result of this will work properly and not abort. */
3485 Fset_window_buffer (new, o->buffer);
3490 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3491 Make the selected window N lines bigger.
3492 From program, optional second arg SIDE non-nil means grow sideways N columns,
3493 and optional third arg WINDOW specifies the window to change instead of the
3498 struct window *w = decode_window (window);
3500 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3504 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3505 Make the selected window N pixels bigger.
3506 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3507 and optional third arg WINDOW specifies the window to change instead of the
3512 struct window *w = decode_window (window);
3514 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3518 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3519 Make the selected window N lines smaller.
3520 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3521 and optional third arg WINDOW specifies the window to change instead of the
3527 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3532 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3533 Make the selected window N pixels smaller.
3534 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3535 and optional third arg WINDOW specifies the window to change instead of the
3541 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3547 window_pixel_height (Lisp_Object window)
3549 return WINDOW_HEIGHT (XWINDOW (window));
3553 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3554 int include_gutters_p)
3557 int defheight, defwidth;
3561 XSETWINDOW (window, w);
3563 avail_height = (pixel_height -
3564 (include_gutters_p ? 0 :
3565 window_top_gutter_height (w) +
3566 window_bottom_gutter_height (w)));
3568 default_face_height_and_width (window, &defheight, &defwidth);
3570 char_height = avail_height / defheight;
3572 /* It's the calling function's responsibility to check these values
3573 and make sure they're not out of range.
3575 #### We need to go through the calling functions and actually
3577 return max (0, char_height);
3581 window_char_height_to_pixel_height (struct window *w, int char_height,
3582 int include_gutters_p)
3585 int defheight, defwidth;
3590 XSETWINDOW (window, w);
3592 default_face_height_and_width (window, &defheight, &defwidth);
3594 avail_height = char_height * defheight;
3595 pixel_height = (avail_height +
3596 (include_gutters_p ? 0 :
3597 window_top_gutter_height (w) +
3598 window_bottom_gutter_height (w)));
3600 /* It's the calling function's responsibility to check these values
3601 and make sure they're not out of range.
3603 #### We need to go through the calling functions and actually
3605 return max (0, pixel_height);
3608 /* Return number of default lines of text can fit in the window W.
3609 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3610 horizontal scrollbar) in the space that is used for the calculation.
3613 window_char_height (struct window *w, int include_gutters_p)
3615 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3620 * Return number of lines currently displayed in window w. If
3621 * end-of-buffer is displayed then the area below end-of-buffer is assume
3622 * to be blank lines of default height.
3623 * Does not include the modeline.
3626 window_displayed_height (struct window *w)
3628 struct buffer *b = XBUFFER (w->buffer);
3629 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3631 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3633 : w->window_end_pos[CURRENT_DISP]);
3635 if (!Dynarr_length (dla))
3636 return window_char_height (w, 0);
3638 num_lines = Dynarr_length (dla);
3640 /* #### Document and assert somewhere that w->window_end_pos == -1
3641 indicates that end-of-buffer is being displayed. */
3644 struct display_line *dl = Dynarr_atp (dla, 0);
3645 int ypos1 = dl->ypos + dl->descent;
3646 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3648 int defheight, defwidth;
3650 XSETWINDOW (window, w);
3656 if (Dynarr_length (dla) == 1)
3657 ypos1 = WINDOW_TEXT_TOP (w);
3660 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3661 /* If this line is clipped then we know that there is no
3662 blank room between eob and the modeline. If we are
3663 scrolling on clipped lines just know off the clipped
3665 if (scroll_on_clipped_lines && dl->clip)
3666 return num_lines - 1;
3667 ypos1 = dl->ypos + dl->descent - dl->clip;
3671 default_face_height_and_width (window, &defheight, &defwidth);
3672 /* #### This probably needs to know about the clipping area once a
3673 final definition is decided on. */
3674 num_lines += ((ypos2 - ypos1) / defheight);
3678 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3681 if (scroll_on_clipped_lines
3682 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3690 window_pixel_width (Lisp_Object window)
3692 return WINDOW_WIDTH (XWINDOW (window));
3696 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3697 int include_margins_p)
3701 int defheight, defwidth;
3704 XSETWINDOW (window, w);
3706 avail_width = (pixel_width -
3707 window_left_gutter_width (w, 0) -
3708 window_right_gutter_width (w, 0) -
3709 (include_margins_p ? 0 : window_left_margin_width (w)) -
3710 (include_margins_p ? 0 : window_right_margin_width (w)));
3712 default_face_height_and_width (window, &defheight, &defwidth);
3714 char_width = (avail_width / defwidth);
3716 /* It's the calling function's responsibility to check these values
3717 and make sure they're not out of range.
3719 #### We need to go through the calling functions and actually
3721 return max (0, char_width);
3725 window_char_width_to_pixel_width (struct window *w, int char_width,
3726 int include_margins_p)
3730 int defheight, defwidth;
3733 XSETWINDOW (window, w);
3735 default_face_height_and_width (window, &defheight, &defwidth);
3737 avail_width = char_width * defwidth;
3738 pixel_width = (avail_width +
3739 window_left_gutter_width (w, 0) +
3740 window_right_gutter_width (w, 0) +
3741 (include_margins_p ? 0 : window_left_margin_width (w)) +
3742 (include_margins_p ? 0 : window_right_margin_width (w)));
3744 /* It's the calling function's responsibility to check these values
3745 and make sure they're not out of range.
3747 #### We need to go through the calling functions and actually
3749 return max (0, pixel_width);
3752 /* This returns the usable space which doesn't include space needed by
3753 scrollbars or divider lines. */
3755 window_char_width (struct window *w, int include_margins_p)
3757 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3761 #define MINSIZE(w) \
3763 ? window_min_width * defwidth \
3764 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3767 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3769 #define CURSIZE(w) \
3770 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3772 #define CURCHARSIZE(w) \
3773 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3775 #define MINCHARSIZE(window) \
3776 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3777 ? 1 : window_min_height)
3779 /* Unlike set_window_pixheight, this function
3780 also changes the heights of the siblings so as to
3781 keep everything consistent. */
3784 change_window_height (struct window *win, int delta, int widthflag,
3792 int (*sizefun) (Lisp_Object) = (widthflag
3793 ? window_pixel_width
3794 : window_pixel_height);
3795 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3796 ? set_window_pixwidth
3797 : set_window_pixheight);
3799 int defheight, defwidth;
3804 check_min_window_sizes ();
3806 XSETWINDOW (window, win);
3807 f = XFRAME (win->frame);
3808 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3809 error ("Won't change only window");
3811 /* #### This is very likely incorrect and instead the char_to_pixel_
3812 functions should be called. */
3813 default_face_height_and_width (window, &defheight, &defwidth);
3817 w = XWINDOW (window);
3822 error ("No other window to side of this one");
3826 ? !NILP (XWINDOW (parent)->hchild)
3827 : !NILP (XWINDOW (parent)->vchild))
3832 sizep = &CURSIZE (w);
3833 dim = CURCHARSIZE (w);
3835 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3836 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3838 if (MINI_WINDOW_P (XWINDOW (window)))
3840 else if (!NILP (parent))
3842 Fdelete_window (window, Qnil);
3848 delta *= (widthflag ? defwidth : defheight);
3853 maxdelta = ((!NILP (parent))
3854 ? (*sizefun) (parent) - *sizep
3855 : ((!NILP (w->next))
3856 ? (*sizefun) (w->next) - MINSIZE (w->next)
3857 : ((!NILP (w->prev))
3858 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3859 /* This is a frame with only one window,
3860 a minibuffer-only or a minibufferless frame. */
3863 if (delta > maxdelta)
3864 /* This case traps trying to make the minibuffer
3865 the full frame, or make the only window aside from the
3866 minibuffer the full frame. */
3873 /* #### Chuck: is this correct? */
3874 if (*sizep + delta < MINSIZE (window))
3876 Fdelete_window (window);
3882 if (!NILP (w->next) &&
3883 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3885 CURBEG (XWINDOW (w->next)) += delta;
3886 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3887 (*setsizefun) (window, *sizep + delta, 0);
3889 else if (!NILP (w->prev) &&
3890 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3892 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3893 CURBEG (w) -= delta;
3894 (*setsizefun) (window, *sizep + delta, 0);
3899 int opht = (*sizefun) (parent);
3901 /* If trying to grow this window to or beyond size of the parent,
3902 make delta1 so big that, on shrinking back down,
3903 all the siblings end up with less than one line and are deleted. */
3904 if (opht <= *sizep + delta)
3905 delta1 = opht * opht * 2;
3906 /* Otherwise, make delta1 just right so that if we add delta1
3907 lines to this window and to the parent, and then shrink
3908 the parent back to its original size, the new proportional
3909 size of this window will increase by delta. */
3911 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3913 /* Add delta1 lines or columns to this window, and to the parent,
3914 keeping things consistent while not affecting siblings. */
3915 CURSIZE (XWINDOW (parent)) = opht + delta1;
3916 (*setsizefun) (window, *sizep + delta1, 0);
3918 /* Squeeze out delta1 lines or columns from our parent,
3919 shrinking this window and siblings proportionately.
3920 This brings parent back to correct size.
3921 Delta1 was calculated so this makes this window the desired size,
3922 taking it all out of the siblings. */
3923 (*setsizefun) (parent, opht, 0);
3926 SET_LAST_MODIFIED (w, 0);
3927 SET_LAST_FACECHANGE (w);
3928 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3938 /* Scroll contents of window WINDOW up N lines. */
3940 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3941 Error_behavior errb)
3943 struct window *w = XWINDOW (window);
3944 struct buffer *b = XBUFFER (w->buffer);
3945 int selected = EQ (window, Fselected_window (Qnil));
3947 Lisp_Object point, tem;
3950 point = make_int (BUF_PT (b));
3953 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3955 if (pos < BUF_BEGV (b))
3957 else if (pos > BUF_ZV (b))
3960 point = make_int (pos);
3963 /* Always set force_start so that redisplay_window will run
3964 the window-scroll-functions. */
3967 /* #### When the fuck does this happen? I'm so glad that history has
3968 completely documented the behavior of the scrolling functions under
3969 all circumstances. */
3970 tem = Fpos_visible_in_window_p (point, window);
3973 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
3975 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
3976 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
3977 MARK_WINDOWS_CHANGED (w);
3986 n = Fprefix_numeric_value (n);
3987 value = XINT (n) * direction;
3990 return; /* someone just made a pointless call */
3994 /* If the user didn't specify how far to scroll then we have to figure it
3995 out by ourselves. */
3996 if (NILP (n) || EQ (n, Qminus))
3998 /* Going forwards is easy. If that is what we are doing then just
3999 set value and the section which handles the user specifying a
4000 positive value will work. */
4003 value = window_displayed_height (w) - next_screen_context_lines;
4004 value = (value < 1 ? 1 : value);
4007 /* Going backwards is hard. We can't use the same loop used if the
4008 user specified a negative value because we care about
4009 next_screen_context_lines. In a variable height world you don't
4010 know how many lines above you can actually be displayed and still
4011 have the context lines appear. So we leave value set to 0 and add
4012 a separate section to deal with this. */
4016 if (direction == 1 && !value)
4023 Bufpos startp, old_start;
4025 old_start = marker_position (w->start[CURRENT_DISP]);
4026 startp = vmotion (w, old_start, value, &vtarget);
4028 if (vtarget < value &&
4029 (w->window_end_pos[CURRENT_DISP] == -1
4030 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4032 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4037 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4040 w->start_at_line_beg = beginning_of_line_p (b, startp);
4041 MARK_WINDOWS_CHANGED (w);
4043 if (!point_would_be_visible (w, startp, XINT (point)))
4046 BUF_SET_PT (b, startp);
4048 set_marker_restricted (w->pointm[CURRENT_DISP],
4057 Bufpos startp, old_start;
4059 old_start = marker_position (w->start[CURRENT_DISP]);
4060 startp = vmotion (w, old_start, value, &vtarget);
4063 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4065 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4070 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4073 w->start_at_line_beg = beginning_of_line_p (b, startp);
4074 MARK_WINDOWS_CHANGED (w);
4076 if (!point_would_be_visible (w, startp, XINT (point)))
4080 if (MINI_WINDOW_P (w))
4083 new_point = start_of_last_line (w, startp);
4086 BUF_SET_PT (b, new_point);
4088 set_marker_restricted (w->pointm[CURRENT_DISP],
4089 make_int (new_point),
4094 else /* value == 0 && direction == -1 */
4096 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4098 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4104 int movement = next_screen_context_lines - 1;
4105 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4106 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4108 start_with_point_on_display_line (w, bottom,
4109 -1 - (movement - vtarget));
4111 if (startp >= old_startp)
4112 startp = vmotion (w, old_startp, -1, NULL);
4114 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4117 w->start_at_line_beg = beginning_of_line_p (b, startp);
4118 MARK_WINDOWS_CHANGED (w);
4120 if (!point_would_be_visible (w, startp, XINT (point)))
4122 Bufpos new_point = start_of_last_line (w, startp);
4125 BUF_SET_PT (b, new_point);
4127 set_marker_restricted (w->pointm[CURRENT_DISP],
4128 make_int (new_point),
4136 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4137 Scroll text of current window upward N lines; or near full screen if no arg.
4138 A near full screen is `next-screen-context-lines' less than a full screen.
4139 Negative N means scroll downward.
4140 When calling from a program, supply an integer as argument or nil.
4141 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4142 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4147 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4151 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4152 Scroll text of current window downward N lines; or near full screen if no arg.
4153 A near full screen is `next-screen-context-lines' less than a full screen.
4154 Negative N means scroll upward.
4155 When calling from a program, supply a number as argument or nil.
4156 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4157 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4162 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4166 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4167 Return the other window for "other window scroll" commands.
4168 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4169 specifies the window.
4170 If `other-window-scroll-buffer' is non-nil, a window
4171 showing that buffer is used.
4176 Lisp_Object selected_window = Fselected_window (Qnil);
4178 if (MINI_WINDOW_P (XWINDOW (selected_window))
4179 && !NILP (Vminibuffer_scroll_window))
4180 window = Vminibuffer_scroll_window;
4181 /* If buffer is specified, scroll that buffer. */
4182 else if (!NILP (Vother_window_scroll_buffer))
4184 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4186 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4190 /* Nothing specified; look for a neighboring window on the same
4192 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4194 if (EQ (window, selected_window))
4195 /* That didn't get us anywhere; look for a window on another
4198 window = Fnext_window (window, Qnil, Qt, Qnil);
4199 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4200 && ! EQ (window, selected_window));
4203 CHECK_LIVE_WINDOW (window);
4205 if (EQ (window, selected_window))
4206 error ("There is no other window");
4211 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4212 Scroll next window upward N lines; or near full frame if no arg.
4213 The next window is the one below the current one; or the one at the top
4214 if the current one is at the bottom. Negative N means scroll downward.
4215 When calling from a program, supply a number as argument or nil.
4217 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4218 specifies the window to scroll.
4219 If `other-window-scroll-buffer' is non-nil, scroll the window
4220 showing that buffer, popping the buffer up if necessary.
4224 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4228 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4229 Scroll selected window display N columns left.
4230 Default for N is window width minus 2.
4234 Lisp_Object window = Fselected_window (Qnil);
4235 struct window *w = XWINDOW (window);
4236 int count = (NILP (n) ?
4237 window_char_width (w, 0) - 2 :
4238 XINT (Fprefix_numeric_value (n)));
4240 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4243 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4244 Scroll selected window display N columns right.
4245 Default for N is window width minus 2.
4249 Lisp_Object window = Fselected_window (Qnil);
4250 struct window *w = XWINDOW (window);
4251 int count = (NILP (n) ?
4252 window_char_width (w, 0) - 2 :
4253 XINT (Fprefix_numeric_value (n)));
4255 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4258 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4259 Center point in WINDOW. With N, put point on line N.
4260 The desired position of point is always relative to the window.
4261 If WINDOW is nil, the selected window is used.
4265 struct window *w = decode_window (window);
4266 struct buffer *b = XBUFFER (w->buffer);
4267 Bufpos opoint = BUF_PT (b);
4271 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4274 n = Fprefix_numeric_value (n);
4276 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4279 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4281 w->start_at_line_beg = beginning_of_line_p (b, startp);
4283 MARK_WINDOWS_CHANGED (w);
4287 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4288 Position point relative to WINDOW.
4289 With no argument, position text at center of window.
4290 An argument specifies window line; zero means top of window,
4291 negative means relative to bottom of window.
4292 If WINDOW is nil, the selected window is used.
4299 Bufpos start, new_point;
4302 /* Don't use decode_window() because we need the new value of
4305 window = Fselected_window (Qnil);
4307 CHECK_WINDOW (window);
4308 w = XWINDOW (window);
4309 b = XBUFFER (w->buffer);
4311 height = window_displayed_height (w);
4312 selected = EQ (window, Fselected_window (w->frame));
4318 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4319 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4321 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4324 BUF_SET_PT (b, new_point);
4326 Fset_window_point (window, make_int (new_point));
4328 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4332 start = marker_position (w->start[CURRENT_DISP]);
4333 if (start < BUF_BEGV (b))
4334 start = BUF_BEGV (b);
4335 else if (start > BUF_ZV (b))
4339 new_point = BUF_PT (b);
4341 new_point = marker_position (w->pointm[CURRENT_DISP]);
4343 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4346 BUF_SET_PT (b, new_point);
4348 Fset_window_point (window, make_int (new_point));
4350 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4353 return make_int (retval);
4357 /* #### Is this going to work right when at eob? */
4358 arg = Fprefix_numeric_value (arg);
4360 XSETINT (arg, XINT (arg) + height);
4363 start = marker_position (w->start[CURRENT_DISP]);
4364 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4367 new_point = BUF_PT (b);
4369 new_point = marker_position (w->pointm[CURRENT_DISP]);
4371 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4374 BUF_SET_PT (b, new_point);
4376 Fset_window_point (window, make_int (new_point));
4378 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4380 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4386 BUF_SET_PT (b, start);
4388 Fset_window_point (window, make_int (start));
4392 return Fvertical_motion (arg, window, Qnil);
4396 new_point = vmotion (XWINDOW (window),
4397 marker_position (w->pointm[CURRENT_DISP]),
4399 Fset_window_point (window, make_int (new_point));
4400 return make_int (vpos);
4406 map_windows_1 (Lisp_Object window,
4407 int (*mapfun) (struct window *w, void *closure),
4410 for (; !NILP (window); window = XWINDOW (window)->next)
4413 struct window *w = XWINDOW (window);
4415 if (!NILP (w->vchild))
4416 retval = map_windows_1 (w->vchild, mapfun, closure);
4417 else if (!NILP (w->hchild))
4418 retval = map_windows_1 (w->hchild, mapfun, closure);
4420 retval = (mapfun) (w, closure);
4429 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4430 invocation of MAPFUN. If any invocation of MAPFUN returns
4431 non-zero, the mapping is halted. Otherwise, map_windows() maps
4432 over all windows in F.
4434 If MAPFUN creates or deletes windows, the behavior is undefined. */
4437 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4441 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4444 Lisp_Object frmcons, devcons, concons;
4446 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4448 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4460 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4463 w->shadow_thickness_changed = 1;
4464 MARK_WINDOWS_CHANGED (w);
4468 vertical_divider_changed_in_window (Lisp_Object specifier,
4472 MARK_WINDOWS_CHANGED (w);
4473 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4476 /* also used in scrollbar.c */
4478 some_window_value_changed (Lisp_Object specifier, struct window *w,
4481 MARK_WINDOWS_CHANGED (w);
4484 #ifdef MEMORY_USAGE_STATS
4490 #ifdef HAVE_SCROLLBARS
4494 int other_redisplay;
4499 compute_window_mirror_usage (struct window_mirror *mir,
4500 struct window_stats *stats,
4501 struct overhead_stats *ovstats)
4505 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4507 #ifdef HAVE_SCROLLBARS
4509 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4512 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4515 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4518 #endif /* HAVE_SCROLLBARS */
4519 stats->other_redisplay +=
4520 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4521 stats->other_redisplay +=
4522 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4526 compute_window_usage (struct window *w, struct window_stats *stats,
4527 struct overhead_stats *ovstats)
4530 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4531 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4532 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4533 stats->line_start +=
4534 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4535 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4538 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4539 Return stats about the memory usage of window WINDOW.
4540 The values returned are in the form of an alist of usage types and byte
4541 counts. The byte counts attempt to encompass all the memory used
4542 by the window (separate from the memory logically associated with a
4543 buffer or frame), including internal structures and any malloc()
4544 overhead associated with them. In practice, the byte counts are
4545 underestimated because certain memory usage is very hard to determine
4546 \(e.g. the amount of memory used inside the Xt library or inside the
4547 X server) and because there is other stuff that might logically
4548 be associated with a window, buffer, or frame (e.g. window configurations,
4549 glyphs) but should not obviously be included in the usage counts.
4551 Multiple slices of the total memory usage may be returned, separated
4552 by a nil. Each slice represents a particular view of the memory, a
4553 particular way of partitioning it into groups. Within a slice, there
4554 is no overlap between the groups of memory, and each slice collectively
4555 represents all the memory concerned.
4559 struct window_stats stats;
4560 struct overhead_stats ovstats;
4561 Lisp_Object val = Qnil;
4563 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4565 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4567 val = acons (Qface_cache, make_int (stats.face), val);
4568 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4569 #ifdef HAVE_SCROLLBARS
4570 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4572 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4573 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4574 val = acons (Qother, make_int (stats.other), val);
4575 val = Fcons (Qnil, val);
4576 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4577 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4578 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4580 return Fnreverse (val);
4583 #endif /* MEMORY_USAGE_STATS */
4586 /************************************************************************/
4587 /* Window configurations */
4588 /************************************************************************/
4590 /* #### This window configuration stuff has had serious bugs lurking in it
4591 for years; it would be a -huge- win if this was reimplemented in lisp.
4594 /* If you add anything to this structure make sure saved_window_equal
4598 Lisp_Object window; /* window */
4599 Lisp_Object buffer; /* buffer */
4600 Lisp_Object start; /* copied marker */
4601 Lisp_Object pointm; /* copied marker */
4602 Lisp_Object sb_point; /* copied marker */
4603 Lisp_Object mark; /* copied marker */
4609 int modeline_hscroll;
4610 int parent_index; /* index into saved_windows */
4611 int prev_index; /* index into saved_windows */
4612 char start_at_line_beg; /* boolean */
4614 #define WINDOW_SLOT_DECLARATION
4615 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4616 #include "winslots.h"
4619 /* If you add anything to this structure make sure window_config_equal
4621 struct window_config
4623 struct lcrecord_header header;
4627 Lisp_Object selected_frame;
4629 Lisp_Object current_window;
4630 Lisp_Object current_buffer;
4631 Lisp_Object minibuffer_scroll_window;
4632 Lisp_Object root_window;
4633 /* Record the values of window-min-width and window-min-height
4634 so that window sizes remain consistent with them. */
4635 int min_width, min_height;
4636 int saved_windows_count;
4637 /* Zero-sized arrays aren't ANSI C */
4638 struct saved_window saved_windows[1];
4641 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4642 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4643 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4644 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4645 #define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
4646 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4649 mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
4651 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4653 markobj (config->current_window);
4654 markobj (config->current_buffer);
4655 markobj (config->minibuffer_scroll_window);
4656 markobj (config->root_window);
4658 for (i = 0; i < config->saved_windows_count; i++)
4660 struct saved_window *s = SAVED_WINDOW_N (config, i);
4661 markobj (s->window);
4662 markobj (s->buffer);
4664 markobj (s->pointm);
4665 markobj (s->sb_point);
4668 /* #### This looked like this. I do not see why specifier cached
4669 values should not be marked, as such specifiers as toolbars
4670 might have GC-able instances. Freed configs are not marked,
4671 aren't they? -- kkm */
4672 markobj (s->dedicated);
4674 #define WINDOW_SLOT(slot, compare) ((void) (markobj (s->slot)))
4675 #include "winslots.h"
4682 sizeof_window_config_for_n_windows (int n)
4684 return (sizeof (struct window_config) +
4685 /* n - 1 because zero-sized arrays aren't ANSI C */
4686 (n - 1) *sizeof (struct saved_window));
4690 sizeof_window_config (CONST void *h)
4692 CONST struct window_config *c = (CONST struct window_config *) h;
4693 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4697 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4699 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4702 error ("printing unreadable object #<window-configuration 0x%x>",
4703 config->header.uid);
4704 write_c_string ("#<window-configuration ", printcharfun);
4705 sprintf (buf, "0x%x>", config->header.uid);
4706 write_c_string (buf, printcharfun);
4709 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4710 window_configuration,
4712 print_window_config,
4713 0, 0, 0, sizeof_window_config,
4714 struct window_config);
4717 /* Returns a boolean indicating whether the two saved windows are
4720 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4722 #define WINDOW_SLOT(slot, compare) \
4723 if (!compare (win1->slot, win2->slot)) \
4725 #include "winslots.h"
4728 EQ (win1->window, win2->window) &&
4729 EQ (win1->buffer, win2->buffer) &&
4730 internal_equal (win1->start, win2->start, 0) &&
4731 internal_equal (win1->pointm, win2->pointm, 0) &&
4732 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4733 internal_equal (win1->mark, win2->mark, 0) &&
4734 win1->pixel_left == win2->pixel_left &&
4735 win1->pixel_top == win2->pixel_top &&
4736 win1->pixel_width == win2->pixel_width &&
4737 win1->pixel_height == win2->pixel_height &&
4738 win1->hscroll == win2->hscroll &&
4739 win1->modeline_hscroll == win2->modeline_hscroll &&
4740 win1->parent_index == win2->parent_index &&
4741 win1->prev_index == win2->prev_index &&
4742 win1->start_at_line_beg == win2->start_at_line_beg;
4745 /* Returns a boolean indicating whether the two given configurations
4748 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4750 struct window_config *fig1, *fig2;
4753 /* First check if they are truly the same. */
4754 if (EQ (conf1, conf2))
4757 fig1 = XWINDOW_CONFIGURATION (conf1);
4758 fig2 = XWINDOW_CONFIGURATION (conf2);
4760 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4761 EQ (fig1->current_window, fig2->current_window) &&
4762 EQ (fig1->current_buffer, fig2->current_buffer) &&
4763 EQ (fig1->root_window, fig2->root_window) &&
4764 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window) &&
4765 fig1->frame_width == fig2->frame_width &&
4766 fig1->frame_height == fig2->frame_height))
4769 for (i = 0; i < fig1->saved_windows_count; i++)
4771 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4772 SAVED_WINDOW_N (fig2, i)))
4779 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4780 Return t if OBJECT is a window-configuration object.
4784 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4788 mark_windows_in_use_closure (struct window *w, void *closure)
4790 int mark = *(int *)closure;
4791 w->config_mark = mark;
4796 mark_windows_in_use (struct frame *f, int mark)
4798 map_windows (f, mark_windows_in_use_closure, &mark);
4801 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4803 free_window_configuration (Lisp_Object window_config)
4806 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4808 /* Free all the markers. It's not completely necessary that
4809 we do this (window configs sitting in a free list aren't
4810 marked normally so the markers wouldn't be marked anyway)
4811 but it's more efficient. */
4812 for (i = 0; i < config->saved_windows_count; i++)
4814 struct saved_window *p = SAVED_WINDOW_N (config, i);
4816 if (!NILP (p->pointm))
4818 free_marker (XMARKER (p->pointm));
4821 if (!NILP (p->start))
4823 free_marker (XMARKER (p->start));
4826 if (!NILP (p->sb_point))
4828 free_marker (XMARKER (p->sb_point));
4831 if (!NILP (p->mark))
4833 free_marker (XMARKER (p->mark));
4838 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4839 free_managed_lcrecord (Vwindow_configuration_free_list
4840 [config->saved_windows_count - 1],
4846 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4847 Set the configuration of windows and buffers as specified by CONFIGURATION.
4848 CONFIGURATION must be a value previously returned
4849 by `current-window-configuration' (which see).
4854 struct window_config *config;
4855 struct saved_window *p;
4856 Lisp_Object new_current_buffer;
4860 struct gcpro gcpro1;
4861 Lisp_Object old_window_config;
4862 int previous_frame_height;
4863 int previous_frame_width;
4864 int specpdl_count = specpdl_depth ();
4866 GCPRO1 (configuration);
4868 CHECK_WINDOW_CONFIGURATION (configuration);
4869 config = XWINDOW_CONFIGURATION (configuration);
4871 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4874 /* Do not signal an error here if the frame was deleted. There are
4875 reasonable cases where we could get here with a deleted frame and
4876 just want to do close to nothing instead. */
4878 if (FRAME_LIVE_P (f))
4880 /* restore the frame characteristics */
4882 new_current_buffer = config->current_buffer;
4883 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4884 new_current_buffer = Qnil;
4887 * Assumed precondition: w->config_mark = 0 for all w
4888 * This procedure should ensure this is true by the time it exits
4889 * to ensure the precondition for future calls.
4891 * We use w->config_mark to know whether we're modifying a
4892 * window that is currently visible on the frame (#### we
4893 * should just be able to check whether the window is dead
4894 * or not, but this way is safer?). As we process each
4895 * window, we set its config_mark to 0. At the end, we
4896 * go through all the windows that used to be on the frame,
4897 * set each one's config_mark to 0 (to maintain the
4898 * assumed precondition) and delete each one that's no
4901 * #### Using a window-configuration to keep track of
4902 * the current windows is wasteful. All we need is the
4903 * list of windows, so we could just use a dynarr.
4905 old_window_config = Fcurrent_window_configuration (frame);
4907 /* If the new configuration is already equal to the old, then stop
4908 right here. This saves the work below and it also saves
4909 triggering a full redisplay of this window. This is a huge win
4910 when using the mouse since the mode motion code uses
4911 save-window-excursion extensively but will rarely cause the
4912 configuration to actually change. */
4913 if (window_config_equal (configuration, old_window_config))
4915 free_window_configuration (old_window_config);
4920 /* We can't quit or even check for quit because that may cause
4921 investigation of the frame state, which may crash if the frame is
4922 in an inconsistent state. */
4923 begin_dont_check_for_quit ();
4924 record_unwind_protect (free_window_configuration, old_window_config);
4926 mark_windows_in_use (f, 1);
4928 previous_frame_width = FRAME_WIDTH (f);
4929 previous_frame_height = FRAME_HEIGHT (f);
4930 /* If the frame has been resized since this window configuration was
4931 made, we change the frame to the size specified in the
4932 configuration, restore the configuration, and then resize it
4933 back. We keep track of the prevailing height in these variables. */
4934 if (config->frame_height != FRAME_HEIGHT (f)
4935 || config->frame_width != FRAME_WIDTH (f))
4936 change_frame_size (f, config->frame_height, config->frame_width, 0);
4938 /* Temporarily avoid any problems with windows that are smaller
4939 than they are supposed to be. */
4940 window_min_height = 1;
4941 window_min_width = 1;
4943 /* OK, now restore all the windows in the window config.
4944 This may involve "undeleting" windows, since the
4945 windows in the window config may be deleted.
4947 for (k = 0; k < config->saved_windows_count; k++)
4949 p = SAVED_WINDOW_N (config, k);
4950 w = XWINDOW (p->window);
4953 /* The window might be dead. In this case, its redisplay
4954 structures were freed, so we need to reallocate them. */
4955 if (!w->face_cachels)
4957 w->face_cachels = Dynarr_new (face_cachel);
4958 reset_face_cachels (w);
4960 if (!w->glyph_cachels)
4961 w->glyph_cachels = Dynarr_new (glyph_cachel);
4962 if (!w->line_start_cache)
4963 w->line_start_cache = Dynarr_new (line_start_cache);
4966 if (p->parent_index >= 0)
4967 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
4971 if (p->prev_index >= 0)
4973 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
4975 /* This is true for a minibuffer-only frame. */
4976 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
4979 XWINDOW (w->prev)->next = p->window;
4984 if (!NILP (w->parent))
4986 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
4988 XWINDOW (w->parent)->vchild = p->window;
4989 XWINDOW (w->parent)->hchild = Qnil;
4993 XWINDOW (w->parent)->hchild = p->window;
4994 XWINDOW (w->parent)->vchild = Qnil;
4998 if (!w->config_mark)
5000 /* #### This should be equivalent to the window previously
5001 having been dead. If we're brave, we'll put in an
5002 assertion to this effect. */
5003 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5005 else /* if (!EQ (w->buffer, p->buffer)) */
5007 /* With the new redisplay we let it know that a change has
5008 been made and it will take care of the rest. If we don't
5009 tell it something has possibly changed it could lead to
5010 incorrect display. */
5011 MARK_WINDOWS_CHANGED (w);
5014 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5015 WINDOW_TOP (w) = WINDOW_TOP (p);
5016 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5017 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5018 w->hscroll = p->hscroll;
5019 w->modeline_hscroll = p->modeline_hscroll;
5020 w->line_cache_last_updated = Qzero;
5021 SET_LAST_MODIFIED (w, 1);
5022 SET_LAST_FACECHANGE (w);
5025 #define WINDOW_SLOT(slot, compare) w->slot = p->slot;
5026 #include "winslots.h"
5028 /* Reinstall the saved buffer and pointers into it. */
5029 if (NILP (p->buffer))
5030 w->buffer = p->buffer;
5033 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5034 /* If saved buffer is alive, install it. */
5036 w->buffer = p->buffer;
5037 w->start_at_line_beg = p->start_at_line_beg;
5038 set_marker_restricted (w->start[CURRENT_DISP],
5039 Fmarker_position (p->start),
5041 set_marker_restricted (w->pointm[CURRENT_DISP],
5042 Fmarker_position (p->pointm),
5044 set_marker_restricted (w->sb_point,
5045 Fmarker_position (p->sb_point),
5047 Fset_marker (XBUFFER (w->buffer)->mark,
5048 Fmarker_position (p->mark), w->buffer);
5050 /* As documented in Fcurrent_window_configuration, don't
5051 save the location of point in the buffer which was current
5052 when the window configuration was recorded. */
5053 if (!EQ (p->buffer, new_current_buffer) &&
5054 XBUFFER (p->buffer) == current_buffer)
5055 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5057 else if (NILP (w->buffer) ||
5058 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5059 /* Else if window's old buffer is dead too, get a live one. */
5061 /* #### The following line makes me nervous... */
5062 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5063 w->buffer = Fget_buffer_create (QSscratch);
5064 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5065 /* This will set the markers to beginning of visible
5067 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5068 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5070 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5071 w->start_at_line_beg = 1;
5074 /* Keeping window's old buffer; make sure the markers
5077 /* Set window markers at start of visible range. */
5078 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5079 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5081 if (XMARKER (w->sb_point)->buffer == 0)
5082 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5083 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5084 set_marker_restricted (w->pointm[CURRENT_DISP],
5086 (BUF_PT (XBUFFER (w->buffer))),
5088 w->start_at_line_beg = 1;
5093 FRAME_ROOT_WINDOW (f) = config->root_window;
5094 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5095 then calls do_switch_frame() below to select the frame that was
5096 recorded in the window config as being selected.
5098 Instead, we don't ever change the selected frame, and either
5099 call Fselect_window() below if the window config's frame is
5100 currently selected, or just set the selected window of the
5101 window config's frame. */
5103 /* Set the frame height to the value it had before this function. */
5104 if (previous_frame_height != FRAME_HEIGHT (f)
5105 || previous_frame_width != FRAME_WIDTH (f))
5106 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5108 /* If restoring in the current frame make the window current,
5109 otherwise just update the frame selected_window slot to be
5110 the restored current_window. */
5111 if (f == selected_frame ())
5113 /* When using `pop-window-configuration', often the minibuffer
5114 ends up as the selected window even though it's not active ...
5115 I really don't know the cause of this, but it should never
5116 happen. This kludge should fix it.
5118 #### Find out why this is really going wrong. */
5119 if (!minibuf_level &&
5120 MINI_WINDOW_P (XWINDOW (config->current_window)))
5121 Fselect_window (Fnext_window (config->current_window,
5125 Fselect_window (config->current_window, Qnil);
5126 if (!NILP (new_current_buffer))
5127 Fset_buffer (new_current_buffer);
5129 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5132 set_frame_selected_window (f, config->current_window);
5135 old_window_config = Qnil; /* Warning suppression */
5137 /* Restore the minimum heights recorded in the configuration. */
5138 window_min_height = config->min_height;
5139 window_min_width = config->min_width;
5142 /* see above comment */
5143 /* Fselect_window will have made f the selected frame, so we
5144 reselect the proper frame here. Fhandle_switch_frame will change the
5145 selected window too, but that doesn't make the call to
5146 Fselect_window above totally superfluous; it still sets f's
5148 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5149 do_switch_frame (config->selected_frame, Qnil, 0);
5152 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5154 if (FRAME_LIVE_P (f))
5156 /* Do this before calling recompute_all_cached_specifiers_in_window()
5157 so that things like redisplay_redraw_cursor() won't abort due
5158 to no window mirror present. */
5159 f->mirror_dirty = 1;
5161 config = XWINDOW_CONFIGURATION (old_window_config);
5162 for (k = 0; k < config->saved_windows_count; k++)
5164 p = SAVED_WINDOW_N (config, k);
5165 w = XWINDOW (p->window);
5166 /* Remember, we set w->config_mark on all currently visible
5167 windows, and reset it on all newly visible windows.
5168 Any windows still marked need to be deleted. */
5171 mark_window_as_deleted (w);
5176 /* We just potentially changed the window's buffer and
5177 potentially turned a dead window into a live one,
5178 so we need to recompute the cached specifier values. */
5179 recompute_all_cached_specifiers_in_window (w);
5184 /* Now restore things, when everything else if OK. */
5186 unbind_to (specpdl_count, Qnil);
5193 /* Mark all subwindows of a window as deleted. The argument
5194 W is actually the subwindow tree of the window in question. */
5197 delete_all_subwindows (struct window *w)
5199 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5200 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5201 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5203 mark_window_as_deleted (w);
5208 count_windows (struct window *window)
5211 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5212 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5213 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5217 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5220 for (j = 0; j < lim; j++)
5222 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5226 return 0; /* suppress compiler warning */
5230 save_window_save (Lisp_Object window, struct window_config *config, int i)
5234 for (; !NILP (window); window = w->next)
5236 struct saved_window *p = SAVED_WINDOW_N (config, i);
5238 w = XWINDOW (window);
5241 p->buffer = w->buffer;
5242 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5243 WINDOW_TOP (p) = WINDOW_TOP (w);
5244 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5245 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5246 p->hscroll = w->hscroll;
5247 p->modeline_hscroll = w->modeline_hscroll;
5249 #define WINDOW_SLOT(slot, compare) p->slot = w->slot;
5250 #include "winslots.h"
5252 if (!NILP (w->buffer))
5254 /* Save w's value of point in the window configuration.
5255 If w is the selected window, then get the value of point
5256 from the buffer; pointm is garbage in the selected window. */
5257 if (EQ (window, Fselected_window (Qnil)))
5259 p->pointm = noseeum_make_marker ();
5260 Fset_marker (p->pointm,
5261 make_int (BUF_PT (XBUFFER (w->buffer))),
5265 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5267 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5268 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5269 p->start_at_line_beg = w->start_at_line_beg;
5271 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5279 p->start_at_line_beg = 0;
5282 if (NILP (w->parent))
5283 p->parent_index = -1;
5285 p->parent_index = saved_window_index (w->parent, config, i);
5289 p->prev_index = saved_window_index (w->prev, config, i);
5290 if (!NILP (w->vchild))
5291 i = save_window_save (w->vchild, config, i);
5292 if (!NILP (w->hchild))
5293 i = save_window_save (w->hchild, config, i);
5300 /* Added to doc string:
5302 This also records the currently selected frame, and FRAME's focus
5303 redirection (see `redirect-frame-focus').
5308 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5309 Return an object representing the current window configuration of FRAME.
5310 If FRAME is nil or omitted, use the selected frame.
5311 This describes the number of windows, their sizes and current buffers,
5312 and for each displayed buffer, where display starts, and the positions of
5313 point and mark. An exception is made for point in the current buffer:
5314 its value is -not- saved.
5319 struct frame *f = decode_frame (frame);
5320 struct window_config *config;
5321 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5323 if (n_windows <= countof (Vwindow_configuration_free_list))
5324 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5325 (Vwindow_configuration_free_list
5328 /* More than ten windows; just allocate directly */
5329 config = (struct window_config *)
5330 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5331 lrecord_window_configuration);
5332 XSETWINDOW_CONFIGURATION (result, config);
5334 config->frame_width = FRAME_WIDTH (f);
5335 config->frame_height = FRAME_HEIGHT (f);
5336 config->current_window = FRAME_SELECTED_WINDOW (f);
5337 XSETBUFFER (config->current_buffer, current_buffer);
5338 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5339 config->root_window = FRAME_ROOT_WINDOW (f);
5340 config->min_height = window_min_height;
5341 config->min_width = window_min_width;
5342 config->saved_windows_count = n_windows;
5343 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5348 save_window_excursion_unwind (Lisp_Object window_config)
5350 Lisp_Object val = Fset_window_configuration (window_config);
5351 free_window_configuration (window_config);
5355 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5356 Execute body, preserving window sizes and contents.
5357 Restores which buffer appears in which window, where display starts,
5358 as well as the current buffer.
5359 Does not restore the value of point in current buffer.
5363 /* This function can GC */
5365 int speccount = specpdl_depth ();
5367 record_unwind_protect (save_window_excursion_unwind,
5368 Fcurrent_window_configuration (Qnil));
5369 val = Fprogn (args);
5370 return unbind_to (speccount, val);
5375 /* This is short and simple in elisp, but... it was written to debug
5376 problems purely on the C side. That is where we need to call it so
5379 debug_print_window (Lisp_Object window, int level)
5382 Lisp_Object child = Fwindow_first_vchild (window);
5385 child = Fwindow_first_hchild (window);
5387 for (i = level; i > 0; i--)
5388 putc ('\t', stderr);
5390 fputs ("#<window", stderr);
5392 Lisp_Object buffer = XWINDOW (window)->buffer;
5393 if (!NILP (buffer) && BUFFERP (buffer))
5394 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5396 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5398 while (!NILP (child))
5400 debug_print_window (child, level + 1);
5401 child = Fwindow_next_child (child);
5405 void debug_print_windows (struct frame *f);
5407 debug_print_windows (struct frame *f)
5409 debug_print_window (f->root_window, 0);
5410 putc ('\n', stderr);
5412 #endif /* DEBUG_XEMACS */
5415 /************************************************************************/
5416 /* initialization */
5417 /************************************************************************/
5420 syms_of_window (void)
5422 defsymbol (&Qwindowp, "windowp");
5423 defsymbol (&Qwindow_live_p, "window-live-p");
5424 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5425 defsymbol (&Qscroll_up, "scroll-up");
5426 defsymbol (&Qscroll_down, "scroll-down");
5427 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5428 defsymbol (&Qdisplay_buffer, "display-buffer");
5430 #ifdef MEMORY_USAGE_STATS
5431 defsymbol (&Qface_cache, "face-cache");
5432 defsymbol (&Qglyph_cache, "glyph-cache");
5433 defsymbol (&Qline_start_cache, "line-start-cache");
5434 #ifdef HAVE_SCROLLBARS
5435 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5437 defsymbol (&Qother_redisplay, "other-redisplay");
5438 /* Qother in general.c */
5441 DEFSUBR (Fselected_window);
5442 DEFSUBR (Fminibuffer_window);
5443 DEFSUBR (Fwindow_minibuffer_p);
5445 DEFSUBR (Fwindow_live_p);
5446 DEFSUBR (Fwindow_first_hchild);
5447 DEFSUBR (Fwindow_first_vchild);
5448 DEFSUBR (Fwindow_next_child);
5449 DEFSUBR (Fwindow_previous_child);
5450 DEFSUBR (Fwindow_parent);
5451 DEFSUBR (Fwindow_lowest_p);
5452 DEFSUBR (Fwindow_highest_p);
5453 DEFSUBR (Fwindow_leftmost_p);
5454 DEFSUBR (Fwindow_rightmost_p);
5455 DEFSUBR (Fpos_visible_in_window_p);
5456 DEFSUBR (Fwindow_buffer);
5457 DEFSUBR (Fwindow_frame);
5458 DEFSUBR (Fwindow_height);
5459 DEFSUBR (Fwindow_displayed_height);
5460 DEFSUBR (Fwindow_width);
5461 DEFSUBR (Fwindow_pixel_height);
5462 DEFSUBR (Fwindow_pixel_width);
5463 DEFSUBR (Fwindow_text_area_pixel_height);
5464 DEFSUBR (Fwindow_displayed_text_pixel_height);
5465 DEFSUBR (Fwindow_text_area_pixel_width);
5466 DEFSUBR (Fwindow_hscroll);
5467 #ifdef MODELINE_IS_SCROLLABLE
5468 DEFSUBR (Fmodeline_hscroll);
5469 DEFSUBR (Fset_modeline_hscroll);
5470 #endif /* MODELINE_IS_SCROLLABLE */
5471 #if 0 /* bogus FSF crock */
5472 DEFSUBR (Fwindow_redisplay_end_trigger);
5473 DEFSUBR (Fset_window_redisplay_end_trigger);
5475 DEFSUBR (Fset_window_hscroll);
5476 DEFSUBR (Fwindow_pixel_edges);
5477 DEFSUBR (Fwindow_text_area_pixel_edges);
5478 DEFSUBR (Fwindow_point);
5479 DEFSUBR (Fwindow_start);
5480 DEFSUBR (Fwindow_end);
5481 DEFSUBR (Fset_window_point);
5482 DEFSUBR (Fset_window_start);
5483 DEFSUBR (Fwindow_dedicated_p);
5484 DEFSUBR (Fset_window_dedicated_p);
5485 DEFSUBR (Fnext_window);
5486 DEFSUBR (Fprevious_window);
5487 DEFSUBR (Fnext_vertical_window);
5488 DEFSUBR (Fother_window);
5489 DEFSUBR (Fget_lru_window);
5490 DEFSUBR (Fget_largest_window);
5491 DEFSUBR (Fget_buffer_window);
5492 DEFSUBR (Fwindow_left_margin_pixel_width);
5493 DEFSUBR (Fwindow_right_margin_pixel_width);
5494 DEFSUBR (Fdelete_other_windows);
5495 DEFSUBR (Fdelete_windows_on);
5496 DEFSUBR (Freplace_buffer_in_windows);
5497 DEFSUBR (Fdelete_window);
5498 DEFSUBR (Fset_window_buffer);
5499 DEFSUBR (Fselect_window);
5500 DEFSUBR (Fsplit_window);
5501 DEFSUBR (Fenlarge_window);
5502 DEFSUBR (Fenlarge_window_pixels);
5503 DEFSUBR (Fshrink_window);
5504 DEFSUBR (Fshrink_window_pixels);
5505 DEFSUBR (Fscroll_up);
5506 DEFSUBR (Fscroll_down);
5507 DEFSUBR (Fscroll_left);
5508 DEFSUBR (Fscroll_right);
5509 DEFSUBR (Fother_window_for_scrolling);
5510 DEFSUBR (Fscroll_other_window);
5511 DEFSUBR (Fcenter_to_window_line);
5512 DEFSUBR (Fmove_to_window_line);
5513 #ifdef MEMORY_USAGE_STATS
5514 DEFSUBR (Fwindow_memory_usage);
5516 DEFSUBR (Fwindow_configuration_p);
5517 DEFSUBR (Fset_window_configuration);
5518 DEFSUBR (Fcurrent_window_configuration);
5519 DEFSUBR (Fsave_window_excursion);
5523 vars_of_window (void)
5525 /* Make sure all windows get marked */
5526 minibuf_window = Qnil;
5527 staticpro (&minibuf_window);
5529 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5530 *Non-nil means to scroll if point lands on a line which is clipped.
5532 scroll_on_clipped_lines = 1;
5534 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5535 See `temp-buffer-show-function'.
5537 Vtemp_buffer_show_hook = Qnil;
5539 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5540 Non-nil means call as function to display a help buffer.
5541 The function is called with one argument, the buffer to be displayed.
5542 Used by `with-output-to-temp-buffer'.
5543 If this function is used, then it must do the entire job of showing
5544 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5546 Vtemp_buffer_show_function = Qnil;
5548 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5549 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5551 Vminibuffer_scroll_window = Qnil;
5553 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5554 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5556 Vother_window_scroll_buffer = Qnil;
5558 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5559 *Number of lines of continuity when scrolling by screenfuls.
5561 next_screen_context_lines = 2;
5563 DEFVAR_INT ("window-min-height", &window_min_height /*
5564 *Delete any window less than this tall (including its modeline).
5566 window_min_height = 4;
5568 DEFVAR_INT ("window-min-width", &window_min_width /*
5569 *Delete any window less than this wide.
5571 window_min_width = 10;
5576 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5578 Vwindow_configuration_free_list[i] =
5579 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5580 lrecord_window_configuration);
5581 staticpro (&Vwindow_configuration_free_list[i]);
5587 specifier_vars_of_window (void)
5589 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5590 *How thick to draw 3D shadows around modelines.
5591 If this is set to 0, modelines will be the traditional 2D. Sizes above
5592 10 will be accepted but the maximum thickness that will be drawn is 10.
5593 This is a specifier; use `set-specifier' to change it.
5595 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5596 /* The initial value for modeline-shadow-thickness is 2, but if the
5597 user removes all specifications we provide a fallback value of 0,
5598 which is probably what was expected. */
5599 set_specifier_fallback (Vmodeline_shadow_thickness,
5600 list1 (Fcons (Qnil, Qzero)));
5601 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5603 set_specifier_caching (Vmodeline_shadow_thickness,
5604 slot_offset (struct window,
5605 modeline_shadow_thickness),
5606 modeline_shadow_thickness_changed,
5609 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5610 *Whether the modeline should be displayed.
5611 This is a specifier; use `set-specifier' to change it.
5613 Vhas_modeline_p = Fmake_specifier (Qboolean);
5614 set_specifier_fallback (Vhas_modeline_p,
5615 list1 (Fcons (Qnil, Qt)));
5616 set_specifier_caching (Vhas_modeline_p,
5617 slot_offset (struct window,
5619 /* #### It's strange that we need a special
5620 flag to indicate that the shadow-thickness
5621 has changed, but not one to indicate that
5622 the modeline has been turned off or on. */
5623 some_window_value_changed,
5626 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5627 &Vvertical_divider_always_visible_p /*
5628 *Should XEmacs always display vertical dividers between windows.
5630 When this is non-nil, vertical dividers are always shown, and are
5631 draggable. When it is nil, vertical dividers are shown only when
5632 there are no scrollbars in between windows, and are not draggable.
5634 This is a specifier; use `set-specifier' to change it.
5636 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5637 set_specifier_fallback (Vvertical_divider_always_visible_p,
5638 list1 (Fcons (Qnil, Qt)));
5639 set_specifier_caching (Vvertical_divider_always_visible_p,
5640 slot_offset (struct window,
5641 vertical_divider_always_visible_p),
5642 vertical_divider_changed_in_window,
5645 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5646 *How thick to draw 3D shadows around vertical dividers.
5647 This is a specifier; use `set-specifier' to change it.
5649 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5650 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5651 list1 (Fcons (Qnil, Qzero)));
5652 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5654 set_specifier_caching (Vvertical_divider_shadow_thickness,
5655 slot_offset (struct window,
5656 vertical_divider_shadow_thickness),
5657 vertical_divider_changed_in_window,
5659 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5660 *The width of the vertical dividers, not including shadows.
5662 For TTY windows, divider line is always one character wide. When
5663 instance of this specifier is zero in a TTY window, no divider is
5664 drawn at all between windows. When non-zero, a one character wide
5665 divider is displayed.
5667 This is a specifier; use `set-specifier' to change it.
5670 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5672 Lisp_Object fb = Qnil;
5674 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
5676 #ifdef HAVE_X_WINDOWS
5677 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5679 #ifdef HAVE_MS_WINDOWS
5680 /* #### This should be made magic and made to obey system settings */
5681 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5683 set_specifier_fallback (Vvertical_divider_line_width, fb);
5685 set_specifier_caching (Vvertical_divider_line_width,
5686 slot_offset (struct window,
5687 vertical_divider_line_width),
5688 vertical_divider_changed_in_window,
5691 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5692 *How much space to leave around the vertical dividers.
5694 In TTY windows, spacing is always zero, and the value of this
5695 specifier is ignored.
5697 This is a specifier; use `set-specifier' to change it.
5699 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5701 Lisp_Object fb = Qnil;
5703 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5705 #ifdef HAVE_X_WINDOWS
5706 /* #### 3D dividers look great on MS Windows with spacing = 0.
5707 Should not the same value be the fallback under X? - kkm */
5708 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
5710 #ifdef HAVE_MS_WINDOWS
5711 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
5713 set_specifier_fallback (Vvertical_divider_spacing, fb);
5715 set_specifier_caching (Vvertical_divider_spacing,
5716 slot_offset (struct window,
5717 vertical_divider_spacing),
5718 vertical_divider_changed_in_window,