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"
40 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
41 Lisp_Object Qscroll_up, Qscroll_down, Qdisplay_buffer;
43 #ifdef MEMORY_USAGE_STATS
44 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
45 #ifdef HAVE_SCROLLBARS
46 Lisp_Object Qscrollbar_instances;
50 EXFUN (Fnext_window, 4);
52 static int window_pixel_width_to_char_width (struct window *w,
54 int include_margins_p);
55 static int window_char_width_to_pixel_width (struct window *w,
57 int include_margins_p);
58 static int window_pixel_height_to_char_height (struct window *w,
60 int include_gutters_p);
61 static int window_char_height_to_pixel_height (struct window *w,
63 int include_gutters_p);
64 static void change_window_height (struct window *w, int delta, int widthflag,
67 /* Thickness of shadow border around 3d modelines. */
68 Lisp_Object Vmodeline_shadow_thickness;
70 /* Whether vertical dividers are draggable and displayed */
71 Lisp_Object Vvertical_divider_always_visible_p;
73 /* Whether a modeline should be displayed. */
74 Lisp_Object Vhas_modeline_p;
76 /* Thickness of shadow border around vertical dividers. */
77 Lisp_Object Vvertical_divider_shadow_thickness;
79 /* Divider surface width (not counting 3-d borders) */
80 Lisp_Object Vvertical_divider_line_width;
82 /* Spacing between outer egde of divider border and window edge */
83 Lisp_Object Vvertical_divider_spacing;
85 /* Scroll if point lands on the bottom line and that line is partially
87 int scroll_on_clipped_lines;
89 /* The minibuffer window of the selected frame.
90 Note that you cannot test for minibufferness of an arbitrary window
91 by comparing against this; but you can test for minibufferness of
92 the selected window. */
93 Lisp_Object minibuf_window;
95 /* Non-nil means it is the window for C-M-v to scroll
96 when the minibuffer is selected. */
97 Lisp_Object Vminibuffer_scroll_window;
99 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
100 Lisp_Object Vother_window_scroll_buffer;
102 /* Non-nil means it's the function to call to display temp buffers. */
103 Lisp_Object Vtemp_buffer_show_function;
105 Lisp_Object Vtemp_buffer_show_hook;
107 /* If a window gets smaller than either of these, it is removed. */
108 int window_min_height;
109 int window_min_width;
111 /* Hook run at end of temp_output_buffer_show. */
112 Lisp_Object Qtemp_buffer_show_hook;
114 /* Number of lines of continuity in scrolling by screenfuls. */
115 int next_screen_context_lines;
117 /* List of freed window configurations with 1 - 10 windows. */
118 Lisp_Object Vwindow_configuration_free_list[10];
120 #define SET_LAST_MODIFIED(w, cache_too) \
122 (w)->last_modified[CURRENT_DISP] = Qzero; \
123 (w)->last_modified[DESIRED_DISP] = Qzero; \
124 (w)->last_modified[CMOTION_DISP] = Qzero; \
126 (w)->line_cache_last_updated = Qzero; \
129 #define SET_LAST_FACECHANGE(w) \
131 (w)->last_facechange[CURRENT_DISP] = Qzero; \
132 (w)->last_facechange[DESIRED_DISP] = Qzero; \
133 (w)->last_facechange[CMOTION_DISP] = Qzero; \
137 #define MARK_DISP_VARIABLE(field) \
138 markobj (window->field[CURRENT_DISP]); \
139 markobj (window->field[DESIRED_DISP]); \
140 markobj (window->field[CMOTION_DISP]);
143 mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object))
145 struct window *window = XWINDOW (obj);
146 markobj (window->frame);
147 markobj (window->mini_p);
148 markobj (window->next);
149 markobj (window->prev);
150 markobj (window->hchild);
151 markobj (window->vchild);
152 markobj (window->parent);
153 markobj (window->buffer);
154 MARK_DISP_VARIABLE (start);
155 MARK_DISP_VARIABLE (pointm);
156 markobj (window->sb_point); /* #### move to scrollbar.c? */
157 markobj (window->use_time);
158 MARK_DISP_VARIABLE (last_modified);
159 MARK_DISP_VARIABLE (last_point);
160 MARK_DISP_VARIABLE (last_start);
161 MARK_DISP_VARIABLE (last_facechange);
162 markobj (window->line_cache_last_updated);
163 markobj (window->redisplay_end_trigger);
164 mark_face_cachels (window->face_cachels, markobj);
165 mark_glyph_cachels (window->glyph_cachels, markobj);
167 #define WINDOW_SLOT(slot, compare) ((void) (markobj (window->slot)))
168 #include "winslots.h"
174 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
179 error ("printing unreadable object #<window 0x%x>",
180 XWINDOW (obj)->header.uid);
182 write_c_string ("#<window", printcharfun);
183 if (!NILP (XWINDOW (obj)->buffer))
185 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
186 write_c_string (" on ", printcharfun);
187 print_internal (name, printcharfun, 1);
189 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
190 write_c_string (buf, printcharfun);
194 finalize_window (void *header, int for_disksave)
196 struct window *w = (struct window *) header;
198 if (w->line_start_cache)
200 Dynarr_free (w->line_start_cache);
201 w->line_start_cache = 0;
208 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
210 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
211 if (cachel->merged_faces)
213 Dynarr_free (cachel->merged_faces);
214 cachel->merged_faces = 0;
217 Dynarr_free (w->face_cachels);
221 if (w->glyph_cachels)
223 Dynarr_free (w->glyph_cachels);
224 w->glyph_cachels = 0;
228 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
229 mark_window, print_window, finalize_window,
230 0, 0, struct window);
233 #define INIT_DISP_VARIABLE(field, initialization) \
234 p->field[CURRENT_DISP] = initialization; \
235 p->field[DESIRED_DISP] = initialization; \
236 p->field[CMOTION_DISP] = initialization;
238 /* We have an implicit assertion that the first two elements (default
239 and modeline faces) are always present in the face_element_cache.
240 Normally redisplay ensures this. However, it is possible for a
241 window to get created and functions which reference these values
242 called before redisplay works with the window for the first time.
243 All callers of allocate_window should therefore call
244 reset_face_cachels on the created window. We can't do it
245 here because the window must have its frame pointer set or
246 reset_face_cachels will fail. */
248 allocate_window (void)
251 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
265 INIT_DISP_VARIABLE (start, Fmake_marker ());
266 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
267 p->sb_point = Fmake_marker ();
269 INIT_DISP_VARIABLE (last_modified, Qzero);
270 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
271 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
272 INIT_DISP_VARIABLE (last_facechange, Qzero);
273 p->face_cachels = Dynarr_new (face_cachel);
274 p->glyph_cachels = Dynarr_new (glyph_cachel);
275 p->line_start_cache = Dynarr_new (line_start_cache);
276 p->line_cache_last_updated = Qzero;
277 INIT_DISP_VARIABLE (last_point_x, 0);
278 INIT_DISP_VARIABLE (last_point_y, 0);
279 INIT_DISP_VARIABLE (window_end_pos, 0);
280 p->redisplay_end_trigger = Qnil;
282 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
283 #include "winslots.h"
285 p->windows_changed = 1;
286 p->shadow_thickness_changed = 1;
290 #undef INIT_DISP_VARIABLE
293 * The redisplay structures used to be stored with each window. While
294 * they are logically something associated with frames they can't be
295 * stored there with a redisplay which handles variable height lines.
296 * Lines in horizontally split windows might not line up. So they get
297 * stored with the windows.
299 * The problem with this is window configurations. When restoring a
300 * window configuration it now becomes problematic to do an
301 * incremental redisplay. The solution is to store the redisplay
302 * structures with the frame as they should be but laid out in the
303 * same manner as the window structure. Thus is born the window
306 * It also becomes a convenient place to stick scrollbar instances
307 * since they extrapolate out to having the same problem described for
308 * the display structures.
311 /* Create a new window mirror structure and associated redisplay
313 static struct window_mirror *
314 new_window_mirror (struct frame *f)
316 struct window_mirror *t = xnew_and_zero (struct window_mirror);
320 t->current_display_lines = Dynarr_new (display_line);
321 t->desired_display_lines = Dynarr_new (display_line);
324 #ifdef HAVE_SCROLLBARS
325 t->scrollbar_vertical_instance = NULL;
326 t->scrollbar_horizontal_instance = NULL;
332 /* Synchronize the mirror structure with a given window structure.
333 This is normally called from update_frame_window_mirror with a
334 starting window of f->root_window. */
335 static struct window_mirror *
336 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
342 free_window_mirror (mir);
349 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
351 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
352 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
353 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
356 * If the redisplay structs are not empty and the mirror has
357 * children, then this mirror structure was formerly being used for
358 * display but is no longer. Reset its current display structs so
359 * that redisplay doesn't accidentally think they are accurate if it
360 * is later used for display purposes once again. Also, mark the
361 * scrollbar instance as not active.
363 if (mir->vchild || mir->hchild)
365 /* The redisplay structures are big. Leaving them around in
366 non-leaf windows can add up to a lot of wasted space. So
368 free_display_structs (mir);
369 mir->current_display_lines = Dynarr_new (display_line);
370 mir->desired_display_lines = Dynarr_new (display_line);
372 #ifdef HAVE_SCROLLBARS
373 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
381 /* Given a window mirror, determine which real window it contains the
382 redisplay structures for. */
384 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
385 struct window_mirror *mir)
387 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
391 if (!NILP (XWINDOW (win)->vchild))
394 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
398 if (!NILP (XWINDOW (win)->hchild))
401 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
410 /* Given a real window, find the mirror structure which contains its
411 redisplay structures. */
412 static struct window_mirror *
413 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
416 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
418 if (w == XWINDOW (win))
421 if (!NILP (XWINDOW (win)->vchild))
423 struct window_mirror *retval =
424 find_window_mirror_internal (XWINDOW (win)->vchild,
426 if (retval) return retval;
429 if (!NILP (XWINDOW (win)->hchild))
431 struct window_mirror *retval =
432 find_window_mirror_internal (XWINDOW (win)->hchild,
434 if (retval) return retval;
441 /* Update the mirror structure for the given frame. */
443 update_frame_window_mirror (struct frame *f)
445 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
449 /* Free a given mirror structure along with all of its children as
450 well as their associated display structures. */
452 free_window_mirror (struct window_mirror *mir)
456 struct window_mirror *prev = mir;
457 if (mir->hchild) free_window_mirror (mir->hchild);
458 if (mir->vchild) free_window_mirror (mir->vchild);
459 #ifdef HAVE_SCROLLBARS
460 release_window_mirror_scrollbars (mir);
462 free_display_structs (mir);
468 /* Given a mirror structure, return the window it mirrors. Calls
469 real_window_internal to do most of the work. */
471 real_window (struct window_mirror *mir, int no_abort)
473 Lisp_Object retval = real_window_internal (mir->frame->root_window,
474 mir->frame->root_mirror, mir);
475 if (NILP (retval) && !no_abort)
481 /* Given a real window, return its mirror structure. Calls
482 find_window_mirror_internal to do all of the work. */
483 struct window_mirror *
484 find_window_mirror (struct window *w)
486 struct frame *f = XFRAME (w->frame);
488 update_frame_window_mirror (f);
489 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
492 /*****************************************************************************
493 find_window_by_pixel_pos
495 Given a pixel position relative to a frame, find the window at that
497 ****************************************************************************/
499 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
504 for (; !NILP (win); win = XWINDOW (win)->next)
508 if (!NILP (XWINDOW (win)->vchild))
510 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
513 if (!NILP (XWINDOW (win)->hchild))
515 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
519 if (pix_x >= WINDOW_LEFT (w)
520 && pix_x <= WINDOW_RIGHT (w)
521 && pix_y >= WINDOW_TOP (w)
522 && pix_y <= WINDOW_BOTTOM (w))
528 /* Return a pointer to the display structures for the given window. */
529 display_line_dynarr *
530 window_display_lines (struct window *w, int which)
532 struct window_mirror *t;
534 if (XFRAME (w->frame)->mirror_dirty)
535 update_frame_window_mirror (XFRAME (w->frame));
536 t = find_window_mirror (w);
540 if (which == CURRENT_DISP)
541 return t->current_display_lines;
542 else if (which == DESIRED_DISP)
543 return t->desired_display_lines;
544 else if (which == CMOTION_DISP)
545 /* The CMOTION_DISP display lines are global. */
546 return cmotion_display_lines;
550 return 0; /* shut up compiler */
554 window_display_buffer (struct window *w)
556 struct window_mirror *t;
558 if (XFRAME (w->frame)->mirror_dirty)
559 update_frame_window_mirror (XFRAME (w->frame));
560 t = find_window_mirror (w);
568 set_window_display_buffer (struct window *w, struct buffer *b)
570 struct window_mirror *t;
572 if (XFRAME (w->frame)->mirror_dirty)
573 update_frame_window_mirror (XFRAME (w->frame));
574 t = find_window_mirror (w);
582 /* Determining a window's position based solely on its pixel
583 positioning doesn't work. Instead, we do it the intelligent way,
584 by checking its positioning in the window hierarchy. */
586 window_is_leftmost (struct window *w)
588 Lisp_Object parent, current_ancestor, window;
590 XSETWINDOW (window, w);
592 parent = XWINDOW (window)->parent;
593 current_ancestor = window;
595 while (!NILP (parent))
597 if (!NILP (XWINDOW (parent)->hchild) &&
598 !EQ (XWINDOW (parent)->hchild, current_ancestor))
601 current_ancestor = parent;
602 parent = XWINDOW (parent)->parent;
609 window_is_rightmost (struct window *w)
611 Lisp_Object parent, current_ancestor, window;
613 XSETWINDOW (window, w);
615 parent = XWINDOW (window)->parent;
616 current_ancestor = window;
618 while (!NILP (parent))
620 if (!NILP (XWINDOW (parent)->hchild)
621 && !NILP (XWINDOW (current_ancestor)->next))
624 current_ancestor = parent;
625 parent = XWINDOW (parent)->parent;
632 window_full_width_p (struct window *w)
634 return window_is_leftmost (w) && window_is_rightmost (w);
638 window_is_highest (struct window *w)
640 Lisp_Object parent, current_ancestor, window;
642 XSETWINDOW (window, w);
644 parent = XWINDOW (window)->parent;
645 current_ancestor = window;
647 while (!NILP (parent))
649 if (!NILP (XWINDOW (parent)->vchild) &&
650 !EQ (XWINDOW (parent)->vchild, current_ancestor))
653 current_ancestor = parent;
654 parent = XWINDOW (parent)->parent;
657 /* This is really to catch the minibuffer but we make it generic in
658 case we ever change things around to let the minibuffer be on top. */
659 if (NILP (XWINDOW (current_ancestor)->prev))
666 window_is_lowest (struct window *w)
668 Lisp_Object parent, current_ancestor, window;
670 XSETWINDOW (window, w);
672 parent = XWINDOW (window)->parent;
673 current_ancestor = window;
675 while (!NILP (parent))
677 if (!NILP (XWINDOW (parent)->vchild)
678 && !NILP (XWINDOW (current_ancestor)->next))
681 current_ancestor = parent;
682 parent = XWINDOW (parent)->parent;
688 #if 0 /* not currently used */
691 window_full_height_p (struct window *w)
693 return window_is_highest (w) && window_is_lowest (w);
699 window_truncation_on (struct window *w)
701 /* Horizontally scrolled windows are truncated. */
705 /* If truncate_partial_width_windows is true and the window is not
706 the full width of the frame it is truncated. */
707 if (truncate_partial_width_windows
708 && !(window_is_leftmost (w) && window_is_rightmost (w)))
711 /* If the window's buffer's value of truncate_lines is non-nil, then
712 the window is truncated. */
713 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
720 have_undivided_common_edge (struct window *w_right, void *closure)
722 struct window *w_left = (struct window *) closure;
723 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
724 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
725 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
726 #ifdef HAVE_SCROLLBARS
727 && (NILP (w_right->scrollbar_on_left_p)
728 || NILP (w_right->vertical_scrollbar_visible_p)
729 || ZEROP (w_right->scrollbar_width))
735 window_needs_vertical_divider_1 (struct window *w)
737 /* Never if we're on the right */
738 if (window_is_rightmost (w))
741 /* Always if draggable */
742 if (!NILP (w->vertical_divider_always_visible_p))
745 #ifdef HAVE_SCROLLBARS
746 /* Our right scrollbar is enough to separate us at the right */
747 if (NILP (w->scrollbar_on_left_p)
748 && !NILP (w->vertical_scrollbar_visible_p)
749 && !ZEROP (w->scrollbar_width))
753 /* Ok. to determine whether we need a divider on the left, we must
754 check that our right neighbor windows have scrollbars on their
755 left sides. We must check all such windows which have common
756 left edge with our window's right edge. */
757 return map_windows (XFRAME (WINDOW_FRAME (w)),
758 have_undivided_common_edge, (void*)w);
762 window_needs_vertical_divider (struct window *w)
764 if (!w->need_vertical_divider_valid_p)
766 w->need_vertical_divider_p =
767 window_needs_vertical_divider_1 (w);
768 w->need_vertical_divider_valid_p = 1;
770 return w->need_vertical_divider_p;
773 /* Called from invalidate_vertical_divider_cache_in_frame */
775 invalidate_vertical_divider_cache_in_window (struct window *w,
778 w->need_vertical_divider_valid_p = 0;
782 /* Calculate width of vertical divider, including its shadows
783 and spacing. The returned value is effectively the distance
784 between adjacent window edges. This function does not check
785 whether a window needs a vertical divider, so the returned
786 value is a "theoretical" one */
788 window_divider_width (struct window *w)
790 /* the shadow thickness can be negative. This means that the divider
791 will have a depressed look */
793 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
795 XINT (w->vertical_divider_line_width)
796 + 2 * XINT (w->vertical_divider_spacing)
797 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
799 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
803 window_scrollbar_width (struct window *w)
805 #ifdef HAVE_SCROLLBARS
806 if (!WINDOW_WIN_P (w)
809 || NILP (w->vertical_scrollbar_visible_p))
810 /* #### when does NILP (w->buffer) happen? */
813 return XINT (w->scrollbar_width);
816 #endif /* HAVE_SCROLLBARS */
819 /* Horizontal scrollbars are only active on windows with truncation
822 window_scrollbar_height (struct window *w)
824 #ifdef HAVE_SCROLLBARS
825 if (!WINDOW_WIN_P (w)
828 || NILP (w->horizontal_scrollbar_visible_p)
829 || !window_truncation_on (w))
832 return XINT (w->scrollbar_height);
835 #endif /* HAVE_SCROLLBARS */
839 window_modeline_height (struct window *w)
841 struct frame *f = XFRAME (w->frame);
844 if (MINI_WINDOW_P (w) || NILP (w->buffer))
848 else if (!WINDOW_HAS_MODELINE_P (w))
850 if (window_scrollbar_height (w))
854 modeline_height = FRAMEMETH (f, divider_height, ());
856 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
857 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
866 display_line_dynarr *dla;
868 /* We don't force a regeneration of the modeline here.
869 Instead it is now a precondition that any function calling
870 this should make sure that one of these structures is
871 up-to-date. In practice this only affects two internal
872 redisplay functions, regenerate_window and
873 regenerate_window_point_center. */
874 /* We check DESIRED_DISP because if it is valid it is more
875 up-to-date than CURRENT_DISP. For calls to this outside
876 of redisplay it doesn't matter which structure we check
877 since there is a redisplay condition that these
878 structures be identical outside of redisplay. */
879 dla = window_display_lines (w, DESIRED_DISP);
880 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
881 modeline_height = (Dynarr_atp (dla, 0)->ascent +
882 Dynarr_atp (dla, 0)->descent);
885 dla = window_display_lines (w, CURRENT_DISP);
886 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
887 modeline_height = (Dynarr_atp (dla, 0)->ascent +
888 Dynarr_atp (dla, 0)->descent);
890 /* This should be an abort except I'm not yet 100%
891 confident that it won't ever get hit (though I
892 haven't been able to trigger it). It is extremely
893 unlikely to cause any noticeable problem and even if
894 it does it will be a minor display glitch. */
895 /* #### Bullshit alert. It does get hit and it causes
896 noticeable glitches. real_current_modeline_height
897 is a kludge to fix this for 19.14. */
898 modeline_height = real_current_modeline_height (w);
901 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
902 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
906 return modeline_height;
909 /*****************************************************************************
910 margin_width_internal
912 For a given window, return the width in pixels of the specified margin.
913 ****************************************************************************/
915 margin_width_internal (struct window *w, int left_margin)
918 int window_cwidth = window_char_width (w, 1);
923 /* We might be getting called on a non-leaf. */
924 if (NILP (w->buffer))
927 /* The minibuffer never has margins. */
928 if (MINI_WINDOW_P (w))
931 XSETWINDOW (window, w);
932 b = XBUFFER (w->buffer);
933 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
934 XINT (w->right_margin_width));
936 default_face_height_and_width (window, 0, &font_width);
938 /* The left margin takes precedence over the right margin so we
939 subtract its width from the space available for the right
942 window_cwidth -= XINT (w->left_margin_width);
944 /* The margin cannot be wider than the window is. We allow the
945 value to be bigger since it is possible for the user to enlarge
946 the window such that the left margin value would no longer be too
947 big, but we won't return a value that is larger. */
948 if (margin_cwidth > window_cwidth)
949 margin_cwidth = window_cwidth;
951 /* At the user level the margin is always specified in characters.
952 Internally however it is manipulated in terms of pixels. */
953 return margin_cwidth * font_width;
957 window_left_margin_width (struct window *w)
959 return margin_width_internal (w, 1);
963 window_right_margin_width (struct window *w)
965 return margin_width_internal (w, 0);
969 window_top_toolbar_height (struct window *w)
971 /* #### implement this shit. */
975 /* #### Currently used in scrollbar.c. Does it actually need to be? */
977 window_bottom_toolbar_height (struct window *w)
983 window_left_toolbar_width (struct window *w)
989 window_right_toolbar_width (struct window *w)
994 /*****************************************************************************
997 The gutters of a window are those areas in the boundary defined by
998 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
999 do not contain text. Items which may be in the gutters include
1000 scrollbars, toolbars and modelines. The margin areas are not
1001 included. This is an exception made because redisplay special cases
1002 the handling of those areas in many places in such a way that
1003 including them in the gutter area would make life difficult.
1005 The size functions refer to height for the bottom and top gutters and
1006 width for the left and right gutters. The starting position
1007 functions refer to the Y coord for bottom and top gutters and the X
1008 coord for left and right gutters. All starting positions are
1009 relative to the frame, not the window.
1010 ****************************************************************************/
1013 window_top_gutter_height (struct window *w)
1015 int toolbar_height = window_top_toolbar_height (w);
1017 if (!NILP (w->hchild) || !NILP (w->vchild))
1020 #ifdef HAVE_SCROLLBARS
1021 if (!NILP (w->scrollbar_on_top_p))
1022 return window_scrollbar_height (w) + toolbar_height;
1025 return toolbar_height;
1029 window_bottom_gutter_height (struct window *w)
1033 if (!NILP (w->hchild) || !NILP (w->vchild))
1037 window_modeline_height (w) + window_bottom_toolbar_height (w);
1039 #ifdef HAVE_SCROLLBARS
1040 if (NILP (w->scrollbar_on_top_p))
1041 return window_scrollbar_height (w) + other_height;
1044 return other_height;
1048 window_left_gutter_width (struct window *w, int modeline)
1050 int gutter = window_left_toolbar_width (w);
1052 if (!NILP (w->hchild) || !NILP (w->vchild))
1056 #ifdef HAVE_SCROLLBARS
1057 if (!modeline && !NILP (w->scrollbar_on_left_p))
1058 gutter += window_scrollbar_width (w);
1065 window_right_gutter_width (struct window *w, int modeline)
1067 int gutter = window_right_toolbar_width (w);
1069 if (!NILP (w->hchild) || !NILP (w->vchild))
1072 #ifdef HAVE_SCROLLBARS
1073 if (!modeline && NILP (w->scrollbar_on_left_p))
1074 gutter += window_scrollbar_width (w);
1077 if (window_needs_vertical_divider (w))
1078 gutter += window_divider_width (w);
1084 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1085 Return t if OBJ is a window.
1089 return WINDOWP (obj) ? Qt : Qnil;
1092 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1093 Return t if OBJ is a window which is currently visible.
1097 return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
1100 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1101 Return the window that the cursor now appears in and commands apply to.
1102 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1103 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1104 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1105 is a console, the selected frame on that console's selected device will
1106 be used. Otherwise, the selected frame is used.
1110 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1111 return Qnil; /* happens at startup */
1114 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1115 return FRAME_SELECTED_WINDOW (f);
1119 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1120 Return the window used now for minibuffers.
1121 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1122 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1123 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1124 is a console, the selected frame on that console's selected device will
1125 be used. Otherwise, the selected frame is used.
1129 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1132 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 1, 1, 0, /*
1133 Return non-nil if WINDOW is a minibuffer window.
1137 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1140 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1141 Return the first horizontal child of WINDOW, or nil.
1145 return decode_window (window)->hchild;
1148 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1149 Return the first vertical child of WINDOW, or nil.
1153 return decode_window (window)->vchild;
1156 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1157 Return the next window on the same level as WINDOW, or nil.
1161 return decode_window (window)->next;
1164 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1165 Return the previous window on the same level as WINDOW, or nil.
1169 return decode_window (window)->prev;
1172 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1173 Return the parent of WINDOW, or nil.
1177 return decode_window (window)->parent;
1180 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1181 Return non-nil if WINDOW is along the bottom of its frame.
1185 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1188 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1189 Return non-nil if WINDOW is along the top of its frame.
1193 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1196 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1197 Return non-nil if WINDOW is along the left edge of its frame.
1201 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1204 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1205 Return non-nil if WINDOW is along the right edge of its frame.
1209 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1212 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1213 Return t if position POS is currently on the frame in WINDOW.
1214 Returns nil if that position is scrolled vertically out of view.
1215 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1219 struct window *w = decode_window (window);
1220 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1222 struct buffer *buf = XBUFFER (w->buffer);
1225 posint = BUF_PT (buf);
1228 CHECK_INT_COERCE_MARKER (pos);
1229 posint = XINT (pos);
1232 if (posint < top || posint > BUF_ZV (buf))
1235 /* w->start can be out of range. If it is, do something reasonable. */
1236 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1239 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1244 decode_window (Lisp_Object window)
1247 return XWINDOW (Fselected_window (Qnil));
1249 CHECK_LIVE_WINDOW (window);
1250 return XWINDOW (window);
1253 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1254 Return the buffer that WINDOW is displaying.
1258 return decode_window (window)->buffer;
1261 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1262 Return the frame that window WINDOW is on.
1266 return decode_window (window)->frame;
1269 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1270 Return the number of default lines in WINDOW.
1271 This actually works by dividing the window's pixel height (including
1272 the modeline and horizontal scrollbar, if any) by the height of the
1273 default font; therefore, the number of displayed lines will probably
1275 Use `window-height' to get consistent results in geometry calculations.
1276 Use `window-displayed-height' to get the actual number of lines
1277 currently displayed in a window.
1281 return make_int (window_char_height (decode_window (window), 1));
1284 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1285 Return the number of lines currently displayed in WINDOW.
1286 This counts the actual number of lines displayed in WINDOW
1287 \(as opposed to `window-height'). The modeline and horizontal
1288 scrollbar do not count as lines. If there is some blank space
1289 between the end of the buffer and the end of the window, this
1290 function pretends that there are lines of text in the default
1295 return make_int (window_displayed_height (decode_window (window)));
1298 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1299 Return the height of WINDOW in pixels. Defaults to current window.
1300 This includes the window's modeline and horizontal scrollbar (if any).
1304 return make_int (decode_window (window)->pixel_height);
1307 DEFUN ("window-text-area-pixel-height",
1308 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1309 Return the height in pixels of the text-displaying portion of WINDOW.
1310 Unlike `window-pixel-height', the space occupied by the modeline and
1311 horizontal scrollbar, if any, is not counted.
1315 struct window *w = decode_window (window);
1317 return make_int (WINDOW_TEXT_HEIGHT (w));
1320 DEFUN ("window-displayed-text-pixel-height",
1321 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1322 Return the height in pixels of the text displayed in WINDOW.
1323 Unlike `window-text-area-pixel-height', any blank space below the
1324 end of the buffer is not included. If optional argument NOCLIPPED
1325 is non-nil, do not include space occupied by clipped lines.
1327 (window, noclipped))
1330 Bufpos start, eobuf;
1332 int hlimit, height, prev_height = -1;
1336 line_start_cache_dynarr *cache;
1339 window = Fselected_window (Qnil);
1341 CHECK_WINDOW (window);
1342 w = XWINDOW (window);
1344 start = marker_position (w->start[CURRENT_DISP]);
1345 hlimit = WINDOW_TEXT_HEIGHT (w);
1346 eobuf = BUF_ZV (XBUFFER (w->buffer));
1348 default_face_height_and_width (window, &defheight, NULL);
1350 /* guess lines needed in line start cache + a few extra */
1351 needed = (hlimit + defheight-1) / defheight + 3;
1354 elt = point_in_line_start_cache (w, start, needed);
1355 assert (elt >= 0); /* in the cache */
1357 cache = w->line_start_cache;
1358 nelt = Dynarr_length (cache);
1361 for (i = elt; i < nelt; i++) {
1362 line = Dynarr_atp (cache, i)->height;
1364 if (height + line > hlimit)
1365 return make_int (!NILP (noclipped) ? height : hlimit);
1369 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1370 return make_int (height);
1373 /* get here => need more cache lines. try again. */
1374 assert(height > prev_height); /* progress? */
1375 prev_height = height;
1377 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1380 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1383 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1384 Return the number of display columns in WINDOW.
1385 This is the width that is usable columns available for text in WINDOW.
1389 return make_int (window_char_width (decode_window (window), 0));
1392 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1393 Return the width of WINDOW in pixels. Defaults to current window.
1397 return make_int (decode_window (window)->pixel_width);
1400 DEFUN ("window-text-area-pixel-width",
1401 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1402 Return the width in pixels of the text-displaying portion of WINDOW.
1403 Unlike `window-pixel-width', the space occupied by the vertical
1404 scrollbar or divider, if any, is not counted.
1408 struct window *w = decode_window (window);
1410 return make_int (WINDOW_TEXT_WIDTH (w));
1413 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1414 Return the number of columns by which WINDOW is scrolled from left margin.
1418 return make_int (decode_window (window)->hscroll);
1421 #ifdef MODELINE_IS_SCROLLABLE
1422 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1423 Return the number of columns by which WINDOW's modeline is scrolled from
1424 left margin. If the window has no modeline, return nil.
1428 struct window *w = decode_window (window);
1430 return (WINDOW_HAS_MODELINE_P (w)) ? make_int (w->modeline_hscroll) : Qnil;
1433 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1434 Set number of columns WINDOW's modeline is scrolled from left margin to NCOL.
1435 NCOL should be zero or positive. If NCOL is negative, it will be forced to 0.
1436 If the window has no modeline, do nothing and return nil.
1440 struct window *w = decode_window (window);
1442 if (WINDOW_HAS_MODELINE_P (w))
1446 ncols = XINT (ncol);
1447 if (ncols < 0) ncols = 0;
1448 if (w->modeline_hscroll != ncols)
1449 MARK_MODELINE_CHANGED;
1450 w->modeline_hscroll = ncols;
1455 #endif /* MODELINE_IS_SCROLLABLE */
1457 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1458 Set number of columns WINDOW is scrolled from left margin to NCOL.
1459 NCOL should be zero or positive.
1467 ncols = XINT (ncol);
1468 if (ncols < 0) ncols = 0;
1469 w = decode_window (window);
1470 if (w->hscroll != ncols)
1471 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1476 #if 0 /* bogus FSF crock */
1478 xxDEFUN ("window-redisplay-end-trigger",
1479 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1480 Return WINDOW's redisplay end trigger value.
1481 See `set-window-redisplay-end-trigger' for more information.
1485 return decode_window (window)->redisplay_end_trigger;
1488 xxDEFUN ("set-window-redisplay-end-trigger",
1489 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1490 Set WINDOW's redisplay end trigger value to VALUE.
1491 VALUE should be a buffer position (typically a marker) or nil.
1492 If it is a buffer position, then if redisplay in WINDOW reaches a position
1493 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1494 with two arguments: WINDOW, and the end trigger value.
1495 Afterwards the end-trigger value is reset to nil.
1499 return (decode_window (window)->redisplay_end_trigger = value);
1504 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1505 Return a list of the pixel edge coordinates of WINDOW.
1506 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1507 The frame toolbars and menubars are considered to be outside of this area.
1511 struct window *w = decode_window (window);
1512 struct frame *f = XFRAME (w->frame);
1514 int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
1515 int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
1517 return list4 (make_int (left),
1519 make_int (left + w->pixel_width),
1520 make_int (top + w->pixel_height));
1523 DEFUN ("window-text-area-pixel-edges",
1524 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1525 Return a list of the pixel edge coordinates of the text area of WINDOW.
1526 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1527 top left corner of the window.
1531 struct window *w = decode_window (window);
1533 int left = window_left_gutter_width (w, /* modeline = */ 0);
1534 int top = window_top_gutter_height (w);
1535 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1536 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1538 return list4 (make_int (left),
1544 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1545 Return current value of point in WINDOW.
1546 For a nonselected window, this is the value point would have
1547 if that window were selected.
1549 Note that, when WINDOW is the selected window and its buffer
1550 is also currently selected, the value returned is the same as (point).
1551 It would be more strictly correct to return the `top-level' value
1552 of point, outside of any save-excursion forms.
1553 But that is hard to define.
1557 struct window *w = decode_window (window);
1559 /* The special check for current buffer is necessary for this
1560 function to work as defined when called within an excursion. */
1561 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1562 && current_buffer == XBUFFER (w->buffer))
1563 return Fpoint (Qnil);
1564 return Fmarker_position (w->pointm[CURRENT_DISP]);
1567 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1568 Return position at which display currently starts in WINDOW.
1569 This is updated by redisplay or by calling `set-window-start'.
1573 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1576 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1577 Return position at which display currently ends in WINDOW.
1578 This is updated by redisplay, when it runs to completion.
1579 Simply changing the buffer text or setting `window-start'
1580 does not update this value.
1581 If GUARANTEE is non-nil, then the return value is guaranteed to be
1582 the value of window-end at the end of the next full redisplay assuming
1583 nothing else changes in the meantime. This function is potentially much
1584 slower with this flag set.
1586 (window, guarantee))
1588 struct window *w = decode_window (window);
1590 if (NILP (guarantee))
1595 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1599 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1600 return make_int (end_of_last_line (w, startp));
1604 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1605 Make point value in WINDOW be at position POS in WINDOW's buffer.
1609 struct window *w = decode_window (window);
1611 CHECK_INT_COERCE_MARKER (pos);
1612 if (w == XWINDOW (Fselected_window (Qnil)))
1613 Fgoto_char (pos, Qnil);
1615 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1621 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1622 Make display in WINDOW start at position POS in WINDOW's buffer.
1623 Optional third arg NOFORCE non-nil inhibits next redisplay
1624 from overriding motion of point in order to display at this exact start.
1626 (window, pos, noforce))
1628 struct window *w = decode_window (window);
1630 CHECK_INT_COERCE_MARKER (pos);
1631 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1632 /* this is not right, but much easier than doing what is right. */
1633 /* w->start_at_line_beg = 0; */
1634 /* WTF is the above supposed to mean? GE */
1635 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1636 marker_position (w->start[CURRENT_DISP]));
1639 w->redo_modeline = 1;
1640 SET_LAST_MODIFIED (w, 0);
1641 SET_LAST_FACECHANGE (w);
1643 MARK_WINDOWS_CHANGED (w);
1648 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1649 Return WINDOW's dedicated object, usually t or nil.
1650 See also `set-window-dedicated-p'.
1654 return decode_window (window)->dedicated;
1657 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1658 Control whether WINDOW is dedicated to the buffer it displays.
1659 If it is dedicated, Emacs will not automatically change
1660 which buffer appears in it.
1661 The second argument is the new value for the dedication flag;
1666 struct window *w = decode_window (window);
1668 w->dedicated = NILP (arg) ? Qnil : Qt;
1670 return w->dedicated;
1673 /* FSFmacs has window-display-table here. We have display table as a
1677 /* Record info on buffer window w is displaying
1678 when it is about to cease to display that buffer. */
1680 unshow_buffer (struct window *w)
1682 Lisp_Object buf = w->buffer;
1684 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1687 /* FSF disables this check, so I'll do it too. I hope it won't
1688 break things. --ben */
1690 if (w == XWINDOW (Fselected_window (Qnil))
1691 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1692 /* Do this except when the selected window's buffer
1693 is being removed from some other window. */
1695 /* last_window_start records the start position that this buffer
1696 had in the last window to be disconnected from it.
1697 Now that this statement is unconditional,
1698 it is possible for the buffer to be displayed in the
1699 selected window, while last_window_start reflects another
1700 window which was recently showing the same buffer.
1701 Some people might say that might be a good thing. Let's see. */
1702 XBUFFER (buf)->last_window_start =
1703 marker_position (w->start[CURRENT_DISP]);
1705 /* Point in the selected window's buffer
1706 is actually stored in that buffer, and the window's pointm isn't used.
1707 So don't clobber point in that buffer. */
1708 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1710 struct buffer *b= XBUFFER (buf);
1711 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1712 marker_position (w->pointm[CURRENT_DISP]),
1717 /* Put REPLACEMENT into the window structure in place of OLD. */
1719 replace_window (Lisp_Object old, Lisp_Object replacement)
1722 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1724 /* If OLD is its frame's root_window, then replacement is the new
1725 root_window for that frame. */
1727 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1728 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1730 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1731 WINDOW_TOP (p) = WINDOW_TOP (o);
1732 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1733 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1735 p->next = tem = o->next;
1737 XWINDOW (tem)->prev = replacement;
1739 p->prev = tem = o->prev;
1741 XWINDOW (tem)->next = replacement;
1743 p->parent = tem = o->parent;
1746 if (EQ (XWINDOW (tem)->vchild, old))
1747 XWINDOW (tem)->vchild = replacement;
1748 if (EQ (XWINDOW (tem)->hchild, old))
1749 XWINDOW (tem)->hchild = replacement;
1752 /* #### Here, if replacement is a vertical combination
1753 and so is its new parent, we should make replacement's
1754 children be children of that parent instead. */
1757 /* we're deleting W; set the structure of W to indicate this. */
1760 mark_window_as_deleted (struct window *w)
1763 (while t (split-window) (delete-window))
1764 we end up with a tree of deleted windows which are all connected
1765 through the `next' slot. This might not seem so bad, as they're
1766 deleted, and will presumably be GCed - but if even *one* of those
1767 windows is still being pointed to, by the user, or by a window
1768 configuration, then *all* of those windows stick around.
1770 Since the window-configuration code doesn't need any of the
1771 pointers to other windows (they are all recreated from the
1772 window-config data), we set them all to nil so that we
1773 are able to collect more actual garbage.
1783 /* Free the extra data structures attached to windows immediately so
1784 they don't sit around consuming excess space. They will be
1785 reinitialized by the window-configuration code as necessary. */
1786 finalize_window ((void *) w, 0);
1789 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1790 Remove WINDOW from the display. Default is selected window.
1791 If window is the only one on the frame, the frame is destroyed.
1792 Normally, you cannot delete the last non-minibuffer-only frame (you must
1793 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1794 second argument FORCE is non-nil, you can delete the last frame. (This
1795 will automatically call `save-buffers-kill-emacs'.)
1799 /* This function can GC if this is the only window in the frame */
1807 /* Note: this function is called by other C code on non-leaf
1810 /* Do the equivalent of decode_window() but don't error out on
1811 deleted window; it's OK to delete an already-deleted window. */
1813 window = Fselected_window (Qnil);
1815 CHECK_WINDOW (window);
1816 w = XWINDOW (window);
1818 /* It's okay to delete an already-deleted window. */
1819 if (! WINDOW_LIVE_P (w))
1822 frame = WINDOW_FRAME (w);
1824 d = XDEVICE (FRAME_DEVICE (f));
1826 if (TOP_LEVEL_WINDOW_P (w))
1828 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1829 /* this frame isn't fully initialized yet; don't blow up. */
1832 if (MINI_WINDOW_P (XWINDOW (window)))
1833 error ("Attempt to delete the minibuffer window");
1835 /* It has been suggested that it's a good thing for C-x 0 to have this
1836 behavior, but not such a good idea for #'delete-window to have it.
1837 Maybe C-x 0 should be bound to something else, or maybe frame
1838 deletion should only happen when this is called interactively.
1840 delete_frame_internal (f, !NILP (force), 0, 0);
1844 /* At this point, we know the window has a parent. */
1846 par = XWINDOW (parent);
1848 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1850 /* Are we trying to delete any frame's selected window?
1851 Note that we could be dealing with a non-leaf window
1852 where the selected window is one of our children.
1853 So, we check by scanning all the ancestors of the
1854 frame's selected window and comparing each one with
1857 Lisp_Object pwindow;
1859 pwindow = FRAME_SELECTED_WINDOW (f);
1861 while (!NILP (pwindow))
1863 if (EQ (window, pwindow))
1865 pwindow = XWINDOW (pwindow)->parent;
1868 if (EQ (window, pwindow))
1870 /* OK, we found it. */
1871 Lisp_Object alternative;
1872 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1874 /* If we're about to delete the selected window on the
1875 selected frame, then we should use Fselect_window to select
1876 the new window. On the other hand, if we're about to
1877 delete the selected window on any other frame, we shouldn't do
1878 anything but set the frame's selected_window slot. */
1879 if (EQ (frame, Fselected_frame (Qnil)))
1880 Fselect_window (alternative, Qnil);
1882 set_frame_selected_window (f, alternative);
1886 /* w->buffer is nil in a non-leaf window; in this case,
1887 get rid of the markers we maintain that point into that buffer. */
1888 if (!NILP (w->buffer))
1891 unchain_marker (w->pointm[CURRENT_DISP]);
1892 unchain_marker (w->pointm[DESIRED_DISP]);
1893 unchain_marker (w->pointm[CMOTION_DISP]);
1894 unchain_marker (w->start[CURRENT_DISP]);
1895 unchain_marker (w->start[DESIRED_DISP]);
1896 unchain_marker (w->start[CMOTION_DISP]);
1897 unchain_marker (w->sb_point);
1898 /* This breaks set-window-configuration if windows in the saved
1899 configuration get deleted and multiple frames are in use. */
1900 /* w->buffer = Qnil; */
1903 /* close up the hole in the sibling list */
1904 if (!NILP (w->next))
1905 XWINDOW (w->next)->prev = w->prev;
1906 if (!NILP (w->prev))
1907 XWINDOW (w->prev)->next = w->next;
1908 if (EQ (window, par->hchild))
1909 par->hchild = w->next;
1910 if (EQ (window, par->vchild))
1911 par->vchild = w->next;
1913 /* Find one of our siblings to give our space to. */
1915 Lisp_Object sib = w->prev;
1918 /* If w gives its space to its next sibling, that sibling needs
1919 to have its top/left side pulled back to where w's is.
1920 set_window_{height,width} will re-position the sibling's
1923 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1924 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1927 /* Stretch that sibling. */
1928 if (!NILP (par->vchild))
1929 set_window_pixheight
1930 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1931 if (!NILP (par->hchild))
1933 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1936 /* If parent now has only one child,
1937 put the child into the parent's place. */
1939 Lisp_Object parchild = par->hchild;
1940 if (NILP (parchild))
1941 parchild = par->vchild;
1942 if (NILP (XWINDOW (parchild)->next))
1944 replace_window (parent, parchild);
1945 mark_window_as_deleted (XWINDOW (parent));
1949 /* Since we may be deleting combination windows, we must make sure that
1950 not only W but all its children have been marked as deleted. */
1951 if (!NILP (w->hchild))
1952 delete_all_subwindows (XWINDOW (w->hchild));
1953 else if (!NILP (w->vchild))
1954 delete_all_subwindows (XWINDOW (w->vchild));
1956 mark_window_as_deleted (w);
1958 f->mirror_dirty = 1;
1963 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1964 Return next window after WINDOW in canonical ordering of windows.
1965 If omitted, WINDOW defaults to the selected window.
1967 Optional second arg MINIBUF t means count the minibuffer window even
1968 if not active. MINIBUF nil or omitted means count the minibuffer iff
1969 it is active. MINIBUF neither t nor nil means not to count the
1970 minibuffer even if it is active.
1972 Several frames may share a single minibuffer; if the minibuffer
1973 counts, all windows on all frames that share that minibuffer count
1974 too. Therefore, `next-window' can be used to iterate through the
1975 set of windows even when the minibuffer is on another frame. If the
1976 minibuffer does not count, only windows from WINDOW's frame count.
1978 Optional third arg ALL-FRAMES t means include windows on all frames.
1979 ALL-FRAMES nil or omitted means cycle within the frames as specified
1980 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1981 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1982 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1983 Anything else means restrict to WINDOW's frame.
1985 Optional fourth argument CONSOLE controls which consoles or devices the
1986 returned window may be on. If CONSOLE is a console, return windows only
1987 on that console. If CONSOLE is a device, return windows only on that
1988 device. If CONSOLE is a console type, return windows only on consoles
1989 of that type. If CONSOLE is 'window-system, return any windows on any
1990 window-system consoles. If CONSOLE is nil or omitted, return windows only
1991 on WINDOW's console. Otherwise, all windows are considered.
1993 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
1994 can use `next-window' to iterate through the entire cycle of acceptable
1995 windows, eventually ending up back at the window you started with.
1996 `previous-window' traverses the same cycle, in the reverse order.
1998 (window, minibuf, all_frames, console))
2001 Lisp_Object start_window;
2004 window = Fselected_window (Qnil);
2006 CHECK_LIVE_WINDOW (window);
2008 start_window = window;
2010 /* minibuf == nil may or may not include minibuffers.
2011 Decide if it does. */
2013 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2014 else if (! EQ (minibuf, Qt))
2016 /* Now minibuf can be t => count all minibuffer windows,
2017 lambda => count none of them,
2018 or a specific minibuffer window (the active one) to count. */
2020 /* all_frames == nil doesn't specify which frames to include. */
2021 if (NILP (all_frames))
2022 all_frames = (! EQ (minibuf, Qlambda)
2023 ? (FRAME_MINIBUF_WINDOW
2026 (XWINDOW (window)))))
2028 else if (EQ (all_frames, Qvisible))
2030 else if (ZEROP (all_frames))
2032 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2033 /* If all_frames is a frame and window arg isn't on that frame, just
2034 return the first window on the frame. */
2035 return frame_first_window (XFRAME (all_frames));
2036 else if (! EQ (all_frames, Qt))
2038 /* Now all_frames is t meaning search all frames,
2039 nil meaning search just current frame,
2040 visible meaning search just visible frames,
2041 0 meaning search visible and iconified frames,
2042 or a window, meaning search the frame that window belongs to. */
2044 /* Do this loop at least once, to get the next window, and perhaps
2045 again, if we hit the minibuffer and that is not acceptable. */
2048 /* Find a window that actually has a next one. This loop
2049 climbs up the tree. */
2050 while (tem = XWINDOW (window)->next, NILP (tem))
2051 if (tem = XWINDOW (window)->parent, !NILP (tem))
2053 else /* window must be minibuffer window now */
2055 /* We've reached the end of this frame.
2056 Which other frames are acceptable? */
2057 tem = WINDOW_FRAME (XWINDOW (window));
2059 if (! NILP (all_frames))
2064 tem = next_frame (tem, all_frames, console);
2065 /* In the case where the minibuffer is active,
2066 and we include its frame as well as the selected one,
2067 next_frame may get stuck in that frame.
2068 If that happens, go back to the selected frame
2069 so we can complete the cycle. */
2071 XSETFRAME (tem, selected_frame ());
2074 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2080 /* If we're in a combination window, find its first child and
2081 recurse on that. Otherwise, we've found the window we want. */
2084 if (!NILP (XWINDOW (window)->hchild))
2085 window = XWINDOW (window)->hchild;
2086 else if (!NILP (XWINDOW (window)->vchild))
2087 window = XWINDOW (window)->vchild;
2091 /* "acceptable" is the correct spelling. */
2092 /* Which windows are acceptable?
2093 Exit the loop and accept this window if
2094 this isn't a minibuffer window,
2095 or we're accepting all minibuffer windows,
2096 or this is the active minibuffer and we are accepting that one, or
2097 we've come all the way around and we're back at the original window. */
2098 while (MINI_WINDOW_P (XWINDOW (window))
2099 && ! EQ (minibuf, Qt)
2100 && ! EQ (minibuf, window)
2101 && ! EQ (window, start_window));
2106 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2107 Return the window preceding WINDOW in canonical ordering of windows.
2108 If omitted, WINDOW defaults to the selected window.
2110 Optional second arg MINIBUF t means count the minibuffer window even
2111 if not active. MINIBUF nil or omitted means count the minibuffer iff
2112 it is active. MINIBUF neither t nor nil means not to count the
2113 minibuffer even if it is active.
2115 Several frames may share a single minibuffer; if the minibuffer
2116 counts, all windows on all frames that share that minibuffer count
2117 too. Therefore, `previous-window' can be used to iterate through
2118 the set of windows even when the minibuffer is on another frame. If
2119 the minibuffer does not count, only windows from WINDOW's frame count
2121 If optional third arg ALL-FRAMES t means include windows on all frames.
2122 ALL-FRAMES nil or omitted means cycle within the frames as specified
2123 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2124 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2125 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2126 Anything else means restrict to WINDOW's frame.
2128 Optional fourth argument CONSOLE controls which consoles or devices the
2129 returned window may be on. If CONSOLE is a console, return windows only
2130 on that console. If CONSOLE is a device, return windows only on that
2131 device. If CONSOLE is a console type, return windows only on consoles
2132 of that type. If CONSOLE is 'window-system, return any windows on any
2133 window-system consoles. If CONSOLE is nil or omitted, return windows only
2134 on WINDOW's console. Otherwise, all windows are considered.
2136 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2137 can use `previous-window' to iterate through the entire cycle of acceptable
2138 windows, eventually ending up back at the window you started with.
2139 `next-window' traverses the same cycle, in the reverse order.
2141 (window, minibuf, all_frames, console))
2144 Lisp_Object start_window;
2147 window = Fselected_window (Qnil);
2149 CHECK_LIVE_WINDOW (window);
2151 start_window = window;
2153 /* minibuf == nil may or may not include minibuffers.
2154 Decide if it does. */
2156 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2157 else if (! EQ (minibuf, Qt))
2159 /* Now minibuf can be t => count all minibuffer windows,
2160 lambda => count none of them,
2161 or a specific minibuffer window (the active one) to count. */
2163 /* all_frames == nil doesn't specify which frames to include.
2164 Decide which frames it includes. */
2165 if (NILP (all_frames))
2166 all_frames = (! EQ (minibuf, Qlambda)
2167 ? (FRAME_MINIBUF_WINDOW
2170 (XWINDOW (window)))))
2172 else if (EQ (all_frames, Qvisible))
2174 else if (ZEROP (all_frames))
2176 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2177 /* If all_frames is a frame and window arg isn't on that frame, just
2178 return the first window on the frame. */
2179 return frame_first_window (XFRAME (all_frames));
2180 else if (! EQ (all_frames, Qt))
2182 /* Now all_frames is t meaning search all frames,
2183 nil meaning search just current frame,
2184 visible meaning search just visible frames,
2185 0 meaning search visible and iconified frames,
2186 or a window, meaning search the frame that window belongs to. */
2188 /* Do this loop at least once, to get the next window, and perhaps
2189 again, if we hit the minibuffer and that is not acceptable. */
2192 /* Find a window that actually has a next one. This loop
2193 climbs up the tree. */
2194 while (tem = XWINDOW (window)->prev, NILP (tem))
2195 if (tem = XWINDOW (window)->parent, !NILP (tem))
2197 else /* window must be minibuffer window now */
2199 /* We have found the top window on the frame.
2200 Which frames are acceptable? */
2201 tem = WINDOW_FRAME (XWINDOW (window));
2203 if (! NILP (all_frames))
2204 /* It's actually important that we use prev_frame here,
2205 rather than next_frame. All the windows acceptable
2206 according to the given parameters should form a ring;
2207 Fnext_window and Fprevious_window should go back and
2208 forth around the ring. If we use next_frame here,
2209 then Fnext_window and Fprevious_window take different
2210 paths through the set of acceptable windows.
2211 window_loop assumes that these `ring' requirement are
2217 tem = prev_frame (tem, all_frames, console);
2218 /* In the case where the minibuffer is active,
2219 and we include its frame as well as the selected one,
2220 next_frame may get stuck in that frame.
2221 If that happens, go back to the selected frame
2222 so we can complete the cycle. */
2224 XSETFRAME (tem, selected_frame ());
2227 /* If this frame has a minibuffer, find that window first,
2228 because it is conceptually the last window in that frame. */
2229 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2230 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2232 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2239 /* If we're in a combination window, find its first child and
2240 recurse on that. Otherwise, we've found the window we want. */
2243 if (!NILP (XWINDOW (window)->hchild))
2244 window = XWINDOW (window)->hchild;
2245 else if (!NILP (XWINDOW (window)->vchild))
2246 window = XWINDOW (window)->vchild;
2248 while (tem = XWINDOW (window)->next, !NILP (tem))
2252 /* Which windows are acceptable?
2253 Exit the loop and accept this window if
2254 this isn't a minibuffer window,
2255 or we're accepting all minibuffer windows,
2256 or this is the active minibuffer and we are accepting that one, or
2257 we've come all the way around and we're back at the original window. */
2258 while (MINI_WINDOW_P (XWINDOW (window))
2259 && ! EQ (minibuf, Qt)
2260 && ! EQ (minibuf, window)
2261 && ! EQ (window, start_window));
2266 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2267 Return the next window which is vertically after WINDOW.
2272 struct window *w = decode_window (window);
2273 XSETWINDOW (window, w);
2275 if (MINI_WINDOW_P (XWINDOW (window)))
2278 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2280 if (EQ (window, root))
2283 if (!NILP (XWINDOW (window)->hchild))
2284 window = XWINDOW (window)->hchild;
2285 else if (!NILP (XWINDOW (window)->vchild))
2286 window = XWINDOW (window)->vchild;
2293 if (!NILP (XWINDOW (window)->parent) &&
2294 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2296 if (!NILP (XWINDOW (window)->next))
2297 return XWINDOW (window)->next;
2299 window = XWINDOW (window)->parent;
2302 window = XWINDOW (window)->parent;
2304 while (!EQ (window, root));
2307 if (!NILP (XWINDOW (window)->hchild))
2308 window = XWINDOW (window)->hchild;
2309 else if (!NILP (XWINDOW (window)->vchild))
2310 window = XWINDOW (window)->vchild;
2315 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2316 Select the N'th different window on this frame.
2317 All windows on current frame are arranged in a cyclic order.
2318 This command selects the window N steps away in that order.
2319 A negative N moves in the opposite order.
2321 If optional argument FRAME is `visible', search all visible frames.
2322 If FRAME is 0, search all visible and iconified frames.
2323 If FRAME is t, search all frames.
2324 If FRAME is nil, search only the selected frame.
2325 If FRAME is a frame, search only that frame.
2327 Optional third argument CONSOLE controls which consoles or devices the
2328 returned window may be on. If CONSOLE is a console, return windows only
2329 on that console. If CONSOLE is a device, return windows only on that
2330 device. If CONSOLE is a console type, return windows only on consoles
2331 of that type. If CONSOLE is 'window-system, return any windows on any
2332 window-system consoles. If CONSOLE is nil or omitted, return windows only
2333 on FRAME'S console, or on the selected console if FRAME is not a frame.
2334 Otherwise, all windows are considered.
2336 (n, frame, console))
2342 w = Fselected_window (Qnil);
2347 w = Fnext_window (w, Qnil, frame, console);
2352 w = Fprevious_window (w, Qnil, frame, console);
2355 Fselect_window (w, Qnil);
2360 /* Look at all windows, performing an operation specified by TYPE
2363 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2364 frame. If FRAMES is a frame, just look at windows on that frame.
2365 If MINI is non-zero, perform the operation on minibuffer windows too.
2371 GET_BUFFER_WINDOW, /* Arg is buffer */
2372 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2373 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2374 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2376 UNSHOW_BUFFER, /* Arg is buffer */
2377 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2378 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2382 window_loop (enum window_loop type,
2387 Lisp_Object console)
2389 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2391 Lisp_Object best_window = Qnil;
2392 Lisp_Object next_window;
2393 Lisp_Object last_window;
2394 struct frame *frame;
2395 Lisp_Object frame_arg = Qt;
2396 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2397 /* #### I think the change of "precomputing" last_window and next_window
2398 * #### catch the lossage this is meant(?) to punt on...
2401 Lisp_Object devcons, concons;
2403 /* FRAME_ARG is Qlambda to stick to one frame,
2404 Qvisible to consider all visible frames,
2407 /* If we're only looping through windows on a particular frame,
2408 FRAME points to that frame. If we're looping through windows
2409 on all frames, FRAME is 0. */
2411 if (FRAMEP (frames))
2412 frame = XFRAME (frames);
2413 else if (NILP (frames))
2414 frame = selected_frame ();
2418 frame_arg = Qlambda;
2419 else if (ZEROP (frames))
2421 else if (EQ (frames, Qvisible))
2424 DEVICE_LOOP_NO_BREAK (devcons, concons)
2426 Lisp_Object device = XCAR (devcons);
2427 Lisp_Object the_frame;
2430 XSETFRAME (the_frame, frame);
2432 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2434 if (NILP (the_frame))
2437 if (!device_matches_console_spec (the_frame, device, console))
2440 /* Pick a window to start with. */
2444 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2446 /* Figure out the last window we're going to mess with. Since
2447 Fnext_window, given the same options, is guaranteed to go in a
2448 ring, we can just use Fprevious_window to find the last one.
2450 We can't just wait until we hit the first window again,
2451 because it might be deleted. */
2453 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2458 struct window *p = XWINDOW (w);
2459 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2461 /* Pick the next window now, since some operations will delete
2462 the current window. */
2463 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2465 /* #### Still needed ?? */
2466 /* Given the outstanding quality of the rest of this code,
2467 I feel no shame about putting this piece of shit in. */
2468 if (++lose_lose >= 500)
2471 /* Note that we do not pay attention here to whether
2472 the frame is visible, since Fnext_window skips non-visible frames
2473 if that is desired, under the control of frame_arg. */
2474 if (! MINI_WINDOW_P (p)
2475 || (mini && minibuf_level > 0))
2478 case GET_BUFFER_WINDOW:
2480 if (XBUFFER (p->buffer) == XBUFFER (obj))
2485 case GET_BUFFER_WINDOW_COUNT:
2487 if (XBUFFER (p->buffer) == XBUFFER (obj))
2492 case GET_LRU_WINDOW:
2494 /* t as arg means consider only full-width windows */
2496 && !window_full_width_p (p))
2498 /* Ignore dedicated windows and minibuffers. */
2499 if (MINI_WINDOW_P (p)
2500 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2502 if (NILP (best_window)
2503 || (XINT (XWINDOW (best_window)->use_time)
2504 > XINT (p->use_time)))
2509 case GET_BUFFER_MRU_WINDOW:
2511 /* #### what about the first check in GET_LRU_WINDOW? */
2512 /* Ignore dedicated windows and minibuffers. */
2513 if (MINI_WINDOW_P (p)
2514 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2517 if (XBUFFER (p->buffer) == XBUFFER (obj))
2519 if (NILP (best_window)
2520 || (XINT (XWINDOW (best_window)->use_time)
2521 < XINT (p->use_time)))
2527 case DELETE_OTHER_WINDOWS:
2529 /* Don't delete the last window on a frame; this can
2530 happen when the minibuffer is selected, and would
2531 cause the frame to be deleted. */
2532 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2533 Fdelete_window (w, Qnil);
2537 case DELETE_BUFFER_WINDOWS:
2539 if (EQ (p->buffer, obj))
2541 struct frame *f = XFRAME (WINDOW_FRAME (p));
2543 /* If this window is dedicated, and in a frame
2544 of its own, kill the frame. */
2545 if (EQ (w, FRAME_ROOT_WINDOW (f))
2546 && !NILP (p->dedicated)
2547 && other_visible_frames (f))
2549 /* Skip the other windows on this frame.
2550 There might be one, the minibuffer! */
2551 if (! EQ (w, last_window))
2552 while (f == XFRAME (WINDOW_FRAME
2553 (XWINDOW (next_window))))
2555 /* As we go, check for the end of the
2556 loop. We mustn't start going
2557 around a second time. */
2558 if (EQ (next_window, last_window))
2563 next_window = Fnext_window (next_window,
2567 /* Now we can safely delete the frame. */
2568 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2571 /* If we're deleting the buffer displayed in
2572 the only window on the frame, find a new
2573 buffer to display there. */
2574 if (NILP (p->parent))
2576 Lisp_Object new_buffer;
2577 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2578 if (NILP (new_buffer))
2579 new_buffer = Fget_buffer_create (QSscratch);
2580 Fset_window_buffer (w, new_buffer);
2581 if (EQ (w, Fselected_window (Qnil)))
2582 Fset_buffer (p->buffer);
2585 Fdelete_window (w, Qnil);
2590 case GET_LARGEST_WINDOW:
2592 /* Ignore dedicated windows and minibuffers. */
2593 if (MINI_WINDOW_P (p)
2594 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2597 /* write the check as follows to avoid tripping
2598 error_check_window() --ben */
2599 struct window *b = NILP (best_window) ? 0 :
2600 XWINDOW (best_window);
2601 if (NILP (best_window)
2602 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2603 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2611 if (EQ (p->buffer, obj))
2613 /* Find another buffer to show in this window. */
2614 Lisp_Object another_buffer =
2615 Fother_buffer (obj, Qnil, Qnil);
2616 if (NILP (another_buffer))
2618 = Fget_buffer_create (QSscratch);
2619 /* If this window is dedicated, and in a frame
2620 of its own, kill the frame. */
2621 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2622 && !NILP (p->dedicated)
2623 && other_visible_frames (w_frame))
2625 /* Skip the other windows on this frame.
2626 There might be one, the minibuffer! */
2627 if (! EQ (w, last_window))
2628 while (w_frame == XFRAME (WINDOW_FRAME
2629 (XWINDOW (next_window))))
2631 /* As we go, check for the end of the
2632 loop. We mustn't start going
2633 around a second time. */
2634 if (EQ (next_window, last_window))
2639 next_window = Fnext_window (next_window,
2643 /* Now we can safely delete the frame. */
2644 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2649 /* Otherwise show a different buffer in the
2651 p->dedicated = Qnil;
2652 Fset_window_buffer (w, another_buffer);
2653 if (EQ (w, Fselected_window (Qnil)))
2654 Fset_buffer (p->buffer);
2664 if (EQ (w, last_window))
2671 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2674 #if 0 /* not currently used */
2677 buffer_window_count (struct buffer *b, struct frame *f)
2679 Lisp_Object buffer, frame;
2681 XSETFRAME (frame, f);
2682 XSETBUFFER (buffer, b);
2684 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2689 buffer_window_mru (struct window *w)
2691 Lisp_Object window =
2692 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2696 else if (XWINDOW (window) == w)
2705 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2706 Return the window least recently selected or used for display.
2707 If optional argument FRAME is `visible', search all visible frames.
2708 If FRAME is 0, search all visible and iconified frames.
2709 If FRAME is t, search all frames.
2710 If FRAME is nil, search only the selected frame.
2711 If FRAME is a frame, search only that frame.
2713 Optional second argument CONSOLE controls which consoles or devices the
2714 returned window may be on. If CONSOLE is a console, return windows only
2715 on that console. If CONSOLE is a device, return windows only on that
2716 device. If CONSOLE is a console type, return windows only on consoles
2717 of that type. If CONSOLE is 'window-system, return any windows on any
2718 window-system consoles. If CONSOLE is nil or omitted, return windows only
2719 on FRAME'S console, or on the selected console if FRAME is not a frame.
2720 Otherwise, all windows are considered.
2725 /* First try for a non-dedicated window that is full-width */
2726 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2727 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2730 /* Then try for any non-dedicated window */
2731 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2732 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2736 /* FSFmacs never returns a dedicated window here. If we do,
2737 it makes `display-buffer' not work right. #### All of this
2738 shit is so disgusting and awful that it needs to be rethought
2740 /* then try for a dedicated window that is full-width */
2741 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2742 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2745 /* If none of them, then all windows, dedicated or not. */
2746 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2748 /* At this point we damn well better have found something. */
2749 if (NILP (w)) abort ();
2755 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2756 Return the window largest in area.
2757 If optional argument FRAME is `visible', search all visible frames.
2758 If FRAME is 0, search all visible and iconified frames.
2759 If FRAME is t, search all frames.
2760 If FRAME is nil, search only the selected frame.
2761 If FRAME is a frame, search only that frame.
2763 Optional second argument CONSOLE controls which consoles or devices the
2764 returned window may be on. If CONSOLE is a console, return windows only
2765 on that console. If CONSOLE is a device, return windows only on that
2766 device. If CONSOLE is a console type, return windows only on consoles
2767 of that type. If CONSOLE is 'window-system, return any windows on any
2768 window-system consoles. If CONSOLE is nil or omitted, return windows only
2769 on FRAME'S console, or on the selected console if FRAME is not a frame.
2770 Otherwise, all windows are considered.
2774 /* Don't search dedicated windows because FSFmacs doesn't.
2775 This stuff is all black magic so don't try to apply common
2777 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2780 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2781 Return a window currently displaying BUFFER, or nil if none.
2782 If optional argument FRAME is `visible', search all visible frames.
2783 If optional argument FRAME is 0, search all visible and iconified frames.
2784 If FRAME is t, search all frames.
2785 If FRAME is nil, search only the selected frame.
2786 If FRAME is a frame, search only that frame.
2788 Optional third argument CONSOLE controls which consoles or devices the
2789 returned window may be on. If CONSOLE is a console, return windows only
2790 on that console. If CONSOLE is a device, return windows only on that
2791 device. If CONSOLE is a console type, return windows only on consoles
2792 of that type. If CONSOLE is 'window-system, return any windows on any
2793 window-system consoles. If CONSOLE is nil or omitted, return windows only
2794 on FRAME'S console, or on the selected console if FRAME is not a frame.
2795 Otherwise, all windows are considered.
2797 (buffer, frame, console))
2799 buffer = Fget_buffer (buffer);
2800 if (BUFFERP (buffer))
2801 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2802 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2807 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2808 but there is no sensible way to implement those functions, since
2809 you can't in general derive a window from a buffer. */
2811 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2813 Return the width in pixels of the left outside margin of window WINDOW.
2814 If WINDOW is nil, the selected window is assumed.
2818 return make_int (window_left_margin_width (decode_window (window)));
2821 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2823 Return the width in pixels of the right outside margin of window WINDOW.
2824 If WINDOW is nil, the selected window is assumed.
2828 return make_int (window_right_margin_width (decode_window (window)));
2831 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2832 Make WINDOW (or the selected window) fill its frame.
2833 Only the frame WINDOW is on is affected.
2834 This function tries to reduce display jumps
2835 by keeping the text previously visible in WINDOW
2836 in the same place on the frame. Doing this depends on
2837 the value of (window-start WINDOW), so if calling this function
2838 in a program gives strange scrolling, make sure the window-start
2839 value is reasonable when this function is called.
2843 struct window *w = decode_window (window);
2844 struct buffer *b = XBUFFER (w->buffer);
2846 int old_top = WINDOW_TOP (w);
2848 XSETWINDOW (window, w);
2850 if (MINI_WINDOW_P (w) && old_top > 0)
2851 error ("Can't expand minibuffer to full frame");
2853 /* Ignore dedicated windows. */
2854 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2856 start_pos = marker_position (w->start[CURRENT_DISP]);
2858 /* Try to minimize scrolling, by setting the window start to the
2859 point which will cause the text at the old window start to be at
2860 the same place on the frame. But don't try to do this if the
2861 window start is outside the visible portion (as might happen when
2862 the display is not current, due to typeahead). */
2863 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2864 && !MINI_WINDOW_P (w))
2866 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2868 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2870 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2872 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2874 /* We need to do this, so that the window-scroll-functions
2882 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2883 "bDelete windows on (buffer): ", /*
2884 Delete all windows showing BUFFER.
2885 Optional second argument FRAME controls which frames are affected.
2886 If nil or omitted, delete all windows showing BUFFER in any frame.
2887 If t, delete only windows showing BUFFER in the selected frame.
2888 If `visible', delete all windows showing BUFFER in any visible frame.
2889 If a frame, delete only windows showing BUFFER in that frame.
2891 Optional third argument CONSOLE controls which consoles or devices the
2892 returned window may be on. If CONSOLE is a console, return windows only
2893 on that console. If CONSOLE is a device, return windows only on that
2894 device. If CONSOLE is a console type, return windows only on consoles
2895 of that type. If CONSOLE is 'window-system, return any windows on any
2896 window-system consoles. If CONSOLE is nil or omitted, return windows only
2897 on FRAME'S console, or on the selected console if FRAME is not a frame.
2898 Otherwise, all windows are considered.
2900 (buffer, frame, console))
2902 /* This function can GC */
2903 /* FRAME uses t and nil to mean the opposite of what window_loop
2905 if (!FRAMEP (frame))
2906 frame = NILP (frame) ? Qt : Qnil;
2910 buffer = Fget_buffer (buffer);
2911 CHECK_BUFFER (buffer);
2912 /* Ignore dedicated windows. */
2913 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2918 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2919 "bReplace buffer in windows: ", /*
2920 Replace BUFFER with some other buffer in all windows showing it.
2924 /* This function can GC */
2927 buffer = Fget_buffer (buffer);
2928 CHECK_BUFFER (buffer);
2929 /* Ignore dedicated windows. */
2930 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2935 /* The smallest acceptable dimensions for a window. Anything smaller
2936 might crash Emacs. */
2937 #define MIN_SAFE_WINDOW_WIDTH (2)
2938 #define MIN_SAFE_WINDOW_HEIGHT (2)
2940 /* Make sure that window_min_height and window_min_width are
2941 not too small; if they are, set them to safe minima. */
2944 check_min_window_sizes (void)
2946 /* Smaller values might permit a crash. */
2947 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2948 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2949 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2950 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2953 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2954 minimum allowable size. */
2956 check_frame_size (struct frame *frame, int *rows, int *cols)
2958 /* For height, we have to see whether the frame has a minibuffer, and
2959 whether it wants a modeline. */
2961 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2962 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2963 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2965 if (*rows < min_height)
2967 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2968 *cols = MIN_SAFE_WINDOW_WIDTH;
2971 /* Normally the window is deleted if it gets too small.
2972 nodelete nonzero means do not do this.
2973 (The caller should check later and do so if appropriate) */
2975 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
2978 struct window *w = XWINDOW (window);
2979 struct frame *f = XFRAME (w->frame);
2981 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
2982 Lisp_Object child, minor_kid, major_kid;
2985 int defheight, defwidth;
2987 /* #### This is very likely incorrect and instead the char_to_pixel_
2988 functions should be called. */
2989 default_face_height_and_width (window, &defheight, &defwidth);
2990 line_size = (set_height ? defheight : defwidth);
2992 check_min_window_sizes ();
2994 minsize = (set_height ? window_min_height : window_min_width);
2995 minsize *= line_size;
2998 && !TOP_LEVEL_WINDOW_P (w)
2999 && new_pixsize < minsize)
3001 Fdelete_window (window, Qnil);
3005 SET_LAST_MODIFIED (w, 0);
3006 SET_LAST_FACECHANGE (w);
3007 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3010 WINDOW_HEIGHT (w) = new_pixsize;
3011 major_kid = w->vchild;
3012 minor_kid = w->hchild;
3016 WINDOW_WIDTH (w) = new_pixsize;
3017 major_kid = w->hchild;
3018 minor_kid = w->vchild;
3021 if (!NILP (minor_kid))
3023 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3026 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3028 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3030 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3033 else if (!NILP (major_kid))
3035 int last_pos, last_old_pos, pos, old_pos, first;
3036 int pixel_adj_left = new_pixsize - old_pixsize;
3037 int div_val = old_pixsize << 1;
3040 * Previously we bailed out here if there was no size change.
3041 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3042 * toolbar appears or disappears, windows may not change size,
3043 * but their top and left coordinates need to be updated.
3045 * So we don't bail until after the loop below.
3048 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3051 for (child = major_kid; !NILP (child); child = c->next)
3053 c = XWINDOW (child);
3057 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3058 WINDOW_TOP (c) = last_pos;
3062 old_pos = last_old_pos + WINDOW_WIDTH (c);
3063 WINDOW_LEFT (c) = last_pos;
3066 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3067 /* All but the last window should have a height which is
3068 a multiple of the default line height. */
3069 if (!NILP (c->next))
3070 pos = (pos / line_size) * line_size;
3072 /* Avoid confusion: don't delete child if it becomes too small */
3073 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3075 last_pos = pos + first;
3076 last_old_pos = old_pos;
3079 /* Sometimes we may get called with our old size. In that case
3080 we don't need to do anything else. */
3081 if (!pixel_adj_left)
3084 /* Now delete any children that became too small. */
3086 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3089 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3091 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3096 /* Set the height of WINDOW and all its inferiors. */
3098 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3100 set_window_pixsize (window, new_pixheight, nodelete, 1);
3103 /* Recursively set width of WINDOW and its inferiors. */
3105 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3107 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3111 static int window_select_count;
3113 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3114 Make WINDOW display BUFFER as its contents.
3115 BUFFER can be a buffer or buffer name.
3120 struct window *w = decode_window (window);
3122 buffer = Fget_buffer (buffer);
3123 CHECK_BUFFER (buffer);
3125 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3126 error ("Attempt to display deleted buffer");
3130 error ("Window is deleted");
3132 /* While this seems like a logical thing to do, it causes problems
3133 because of saved window configurations. It is possible for a
3134 buffer to get restored into a window in which it is already being
3135 displayed, but start and point are actually at completely
3136 different locations. So we let this function complete fully and
3137 it will then make sure redisplay correctly updates things.
3139 #### This is a kludge. The correct approach is not to do this
3140 but to fix set-window-configuration. */
3142 else if (EQ (tem, buffer))
3145 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3146 is first being set up. */
3148 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3149 error ("Window is dedicated to buffer %s",
3150 XSTRING_DATA (XBUFFER (tem)->name));
3156 w->window_end_pos[CURRENT_DISP] = 0;
3158 w->modeline_hscroll = 0;
3159 Fset_marker (w->pointm[CURRENT_DISP],
3160 make_int (BUF_PT (XBUFFER (buffer))),
3162 set_marker_restricted (w->start[CURRENT_DISP],
3163 make_int (XBUFFER (buffer)->last_window_start),
3165 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3166 /* set start_at_line_beg correctly. GE */
3167 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3168 marker_position (w->start[CURRENT_DISP]));
3169 w->force_start = 0; /* Lucid fix */
3170 SET_LAST_MODIFIED (w, 1);
3171 SET_LAST_FACECHANGE (w);
3172 MARK_WINDOWS_CHANGED (w);
3173 recompute_all_cached_specifiers_in_window (w);
3174 if (EQ (window, Fselected_window (Qnil)))
3176 Fset_buffer (buffer);
3181 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3182 Select WINDOW. Most editing will apply to WINDOW's buffer.
3183 The main editor command loop selects the buffer of the selected window
3184 before each command.
3186 With non-nil optional argument `norecord', do not modify the
3187 global or per-frame buffer ordering.
3192 Lisp_Object old_selected_window = Fselected_window (Qnil);
3194 CHECK_LIVE_WINDOW (window);
3195 w = XWINDOW (window);
3197 /* we have already caught dead-window errors */
3198 if (!NILP (w->hchild) || !NILP (w->vchild))
3199 error ("Trying to select non-leaf window");
3201 w->use_time = make_int (++window_select_count);
3202 if (EQ (window, old_selected_window))
3205 /* deselect the old window, if it exists (it might not exist if
3206 the selected device has no frames, which occurs at startup) */
3207 if (!NILP (old_selected_window))
3209 struct window *ow = XWINDOW (old_selected_window);
3211 Fset_marker (ow->pointm[CURRENT_DISP],
3212 make_int (BUF_PT (XBUFFER (ow->buffer))),
3215 MARK_WINDOWS_CHANGED (ow);
3218 /* now select the window's frame */
3219 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3221 select_frame_1 (WINDOW_FRAME (w));
3223 /* also select the window's buffer */
3224 if (NILP (norecord))
3225 Frecord_buffer (w->buffer);
3226 Fset_buffer (w->buffer);
3228 /* Go to the point recorded in the window.
3229 This is important when the buffer is in more
3230 than one window. It also matters when
3231 redisplay_window has altered point after scrolling,
3232 because it makes the change only in the window. */
3234 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3235 if (new_point < BUF_BEGV (current_buffer))
3236 new_point = BUF_BEGV (current_buffer);
3237 else if (new_point > BUF_ZV (current_buffer))
3238 new_point = BUF_ZV (current_buffer);
3240 BUF_SET_PT (current_buffer, new_point);
3243 MARK_WINDOWS_CHANGED (w);
3249 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3250 Lisp_Object override_frame)
3252 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3256 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3258 /* This function can GC */
3261 struct buffer *b = XBUFFER (buf);
3263 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3264 widen_buffer (b, 0);
3265 BUF_SET_PT (b, BUF_BEG (b));
3267 if (!NILP (Vtemp_buffer_show_function))
3268 call1 (Vtemp_buffer_show_function, buf);
3271 window = display_buffer (buf, Qnil, same_frame);
3273 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3274 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3276 Vminibuffer_scroll_window = window;
3277 w = XWINDOW (window);
3279 w->modeline_hscroll = 0;
3280 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3281 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3282 set_marker_restricted (w->sb_point, make_int (1), buf);
3284 /* Run temp-buffer-show-hook, with the chosen window selected. */
3285 if (!preparing_for_armageddon)
3288 tem = Fboundp (Qtemp_buffer_show_hook);
3291 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3294 int count = specpdl_depth ();
3296 /* Select the window that was chosen, for running
3298 record_unwind_protect (save_window_excursion_unwind,
3299 Fcurrent_window_configuration (Qnil));
3301 Fselect_window (window, Qnil);
3302 run_hook (Qtemp_buffer_show_hook);
3303 unbind_to (count, Qnil);
3311 make_dummy_parent (Lisp_Object window)
3314 struct window *o = XWINDOW (window);
3315 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
3317 XSETWINDOW (new, p);
3318 copy_lcrecord (p, o);
3320 /* Don't copy the pointers to the line start cache or the face
3322 p->line_start_cache = Dynarr_new (line_start_cache);
3323 p->face_cachels = Dynarr_new (face_cachel);
3324 p->glyph_cachels = Dynarr_new (glyph_cachel);
3326 /* Put new into window structure in place of window */
3327 replace_window (window, new);
3335 p->start[CURRENT_DISP] = Qnil;
3336 p->start[DESIRED_DISP] = Qnil;
3337 p->start[CMOTION_DISP] = Qnil;
3338 p->pointm[CURRENT_DISP] = Qnil;
3339 p->pointm[DESIRED_DISP] = Qnil;
3340 p->pointm[CMOTION_DISP] = Qnil;
3345 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3346 Split WINDOW, putting SIZE lines in the first of the pair.
3347 WINDOW defaults to selected one and SIZE to half its size.
3348 If optional third arg HOR-FLAG is non-nil, split side by side
3349 and put SIZE columns in the first of the pair.
3351 (window, chsize, horflag))
3354 struct window *o, *p;
3360 window = Fselected_window (Qnil);
3362 CHECK_WINDOW (window);
3364 o = XWINDOW (window);
3365 f = XFRAME (WINDOW_FRAME (o));
3369 if (!NILP (horflag))
3370 /* In the new scheme, we are symmetric with respect to separators
3371 so there is no need to do weird things here. */
3373 psize = WINDOW_WIDTH (o) >> 1;
3374 size = window_pixel_width_to_char_width (o, psize, 0);
3378 psize = WINDOW_HEIGHT (o) >> 1;
3379 size = window_pixel_height_to_char_height (o, psize, 1);
3385 size = XINT (chsize);
3386 if (!NILP (horflag))
3387 psize = window_char_width_to_pixel_width (o, size, 0);
3389 psize = window_char_height_to_pixel_height (o, size, 1);
3392 if (MINI_WINDOW_P (o))
3393 error ("Attempt to split minibuffer window");
3394 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3395 error ("Attempt to split unsplittable frame");
3397 check_min_window_sizes ();
3401 if (size < window_min_height)
3402 error ("Window height %d too small (after splitting)", size);
3403 if (size + window_min_height > window_char_height (o, 1))
3404 error ("Window height %d too small (after splitting)",
3405 window_char_height (o, 1) - size);
3406 if (NILP (o->parent)
3407 || NILP (XWINDOW (o->parent)->vchild))
3409 make_dummy_parent (window);
3410 reset_face_cachels (XWINDOW (window));
3412 XWINDOW (new)->vchild = window;
3413 XFRAME (o->frame)->mirror_dirty = 1;
3418 if (size < window_min_width)
3419 error ("Window width %d too small (after splitting)", size);
3420 if (size + window_min_width > window_char_width (o, 0))
3421 error ("Window width %d too small (after splitting)",
3422 window_char_width (o, 0) - size);
3423 if (NILP (o->parent)
3424 || NILP (XWINDOW (o->parent)->hchild))
3426 make_dummy_parent (window);
3427 reset_face_cachels (XWINDOW (window));
3429 XWINDOW (new)->hchild = window;
3430 XFRAME (o->frame)->mirror_dirty = 1;
3434 /* Now we know that window's parent is a vertical combination
3435 if we are dividing vertically, or a horizontal combination
3436 if we are making side-by-side windows */
3438 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3439 new = allocate_window ();
3442 p->frame = o->frame;
3444 if (!NILP (p->next))
3445 XWINDOW (p->next)->prev = new;
3448 p->parent = o->parent;
3451 reset_face_cachels (p);
3452 reset_glyph_cachels (p);
3455 /* Apportion the available frame space among the two new windows */
3457 if (!NILP (horflag))
3459 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3460 WINDOW_TOP (p) = WINDOW_TOP (o);
3461 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3462 WINDOW_WIDTH (o) = psize;
3463 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3467 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3468 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3469 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3470 WINDOW_HEIGHT (o) = psize;
3471 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3474 XFRAME (p->frame)->mirror_dirty = 1;
3475 /* do this last (after the window is completely initialized and
3476 the mirror-dirty flag is set) so that specifier recomputation
3477 caused as a result of this will work properly and not abort. */
3478 Fset_window_buffer (new, o->buffer);
3483 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3484 Make the selected window N lines bigger.
3485 From program, optional second arg SIDE non-nil means grow sideways N columns,
3486 and optional third arg WINDOW specifies the window to change instead of the
3491 struct window *w = decode_window (window);
3493 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3497 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3498 Make the selected window N pixels bigger.
3499 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3500 and optional third arg WINDOW specifies the window to change instead of the
3505 struct window *w = decode_window (window);
3507 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3511 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3512 Make the selected window N lines smaller.
3513 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3514 and optional third arg WINDOW specifies the window to change instead of the
3520 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3525 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3526 Make the selected window N pixels smaller.
3527 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3528 and optional third arg WINDOW specifies the window to change instead of the
3534 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3540 window_pixel_height (Lisp_Object window)
3542 return WINDOW_HEIGHT (XWINDOW (window));
3546 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3547 int include_gutters_p)
3550 int defheight, defwidth;
3554 XSETWINDOW (window, w);
3556 avail_height = (pixel_height -
3557 (include_gutters_p ? 0 :
3558 window_top_gutter_height (w) +
3559 window_bottom_gutter_height (w)));
3561 default_face_height_and_width (window, &defheight, &defwidth);
3563 char_height = avail_height / defheight;
3565 /* It's the calling function's responsibility to check these values
3566 and make sure they're not out of range.
3568 #### We need to go through the calling functions and actually
3570 return max (0, char_height);
3574 window_char_height_to_pixel_height (struct window *w, int char_height,
3575 int include_gutters_p)
3578 int defheight, defwidth;
3583 XSETWINDOW (window, w);
3585 default_face_height_and_width (window, &defheight, &defwidth);
3587 avail_height = char_height * defheight;
3588 pixel_height = (avail_height +
3589 (include_gutters_p ? 0 :
3590 window_top_gutter_height (w) +
3591 window_bottom_gutter_height (w)));
3593 /* It's the calling function's responsibility to check these values
3594 and make sure they're not out of range.
3596 #### We need to go through the calling functions and actually
3598 return max (0, pixel_height);
3601 /* Return number of default lines of text can fit in the window W.
3602 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3603 horizontal scrollbar) in the space that is used for the calculation.
3606 window_char_height (struct window *w, int include_gutters_p)
3608 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3613 * Return number of lines currently displayed in window w. If
3614 * end-of-buffer is displayed then the area below end-of-buffer is assume
3615 * to be blank lines of default height.
3616 * Does not include the modeline.
3619 window_displayed_height (struct window *w)
3621 struct buffer *b = XBUFFER (w->buffer);
3622 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3624 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3626 : w->window_end_pos[CURRENT_DISP]);
3628 if (!Dynarr_length (dla))
3629 return window_char_height (w, 0);
3631 num_lines = Dynarr_length (dla);
3633 /* #### Document and assert somewhere that w->window_end_pos == -1
3634 indicates that end-of-buffer is being displayed. */
3637 struct display_line *dl = Dynarr_atp (dla, 0);
3638 int ypos1 = dl->ypos + dl->descent;
3639 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3641 int defheight, defwidth;
3643 XSETWINDOW (window, w);
3649 if (Dynarr_length (dla) == 1)
3650 ypos1 = WINDOW_TEXT_TOP (w);
3653 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3654 /* If this line is clipped then we know that there is no
3655 blank room between eob and the modeline. If we are
3656 scrolling on clipped lines just know off the clipped
3658 if (scroll_on_clipped_lines && dl->clip)
3659 return num_lines - 1;
3660 ypos1 = dl->ypos + dl->descent - dl->clip;
3664 default_face_height_and_width (window, &defheight, &defwidth);
3665 /* #### This probably needs to know about the clipping area once a
3666 final definition is decided on. */
3667 num_lines += ((ypos2 - ypos1) / defheight);
3671 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3674 if (scroll_on_clipped_lines
3675 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3683 window_pixel_width (Lisp_Object window)
3685 return WINDOW_WIDTH (XWINDOW (window));
3689 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3690 int include_margins_p)
3694 int defheight, defwidth;
3697 XSETWINDOW (window, w);
3699 avail_width = (pixel_width -
3700 window_left_gutter_width (w, 0) -
3701 window_right_gutter_width (w, 0) -
3702 (include_margins_p ? 0 : window_left_margin_width (w)) -
3703 (include_margins_p ? 0 : window_right_margin_width (w)));
3705 default_face_height_and_width (window, &defheight, &defwidth);
3707 char_width = (avail_width / defwidth);
3709 /* It's the calling function's responsibility to check these values
3710 and make sure they're not out of range.
3712 #### We need to go through the calling functions and actually
3714 return max (0, char_width);
3718 window_char_width_to_pixel_width (struct window *w, int char_width,
3719 int include_margins_p)
3723 int defheight, defwidth;
3726 XSETWINDOW (window, w);
3728 default_face_height_and_width (window, &defheight, &defwidth);
3730 avail_width = char_width * defwidth;
3731 pixel_width = (avail_width +
3732 window_left_gutter_width (w, 0) +
3733 window_right_gutter_width (w, 0) +
3734 (include_margins_p ? 0 : window_left_margin_width (w)) +
3735 (include_margins_p ? 0 : window_right_margin_width (w)));
3737 /* It's the calling function's responsibility to check these values
3738 and make sure they're not out of range.
3740 #### We need to go through the calling functions and actually
3742 return max (0, pixel_width);
3745 /* This returns the usable space which doesn't include space needed by
3746 scrollbars or divider lines. */
3748 window_char_width (struct window *w, int include_margins_p)
3750 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3754 #define MINSIZE(w) \
3756 ? window_min_width * defwidth \
3757 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3760 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3762 #define CURSIZE(w) \
3763 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3765 #define CURCHARSIZE(w) \
3766 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3768 #define MINCHARSIZE(window) \
3769 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3770 ? 1 : window_min_height)
3772 /* Unlike set_window_pixheight, this function
3773 also changes the heights of the siblings so as to
3774 keep everything consistent. */
3777 change_window_height (struct window *win, int delta, int widthflag,
3785 int (*sizefun) (Lisp_Object) = (widthflag
3786 ? window_pixel_width
3787 : window_pixel_height);
3788 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3789 ? set_window_pixwidth
3790 : set_window_pixheight);
3792 int defheight, defwidth;
3797 check_min_window_sizes ();
3799 XSETWINDOW (window, win);
3800 f = XFRAME (win->frame);
3801 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3802 error ("Won't change only window");
3804 /* #### This is very likely incorrect and instead the char_to_pixel_
3805 functions should be called. */
3806 default_face_height_and_width (window, &defheight, &defwidth);
3810 w = XWINDOW (window);
3815 error ("No other window to side of this one");
3819 ? !NILP (XWINDOW (parent)->hchild)
3820 : !NILP (XWINDOW (parent)->vchild))
3825 sizep = &CURSIZE (w);
3826 dim = CURCHARSIZE (w);
3828 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3829 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3831 if (MINI_WINDOW_P (XWINDOW (window)))
3833 else if (!NILP (parent))
3835 Fdelete_window (window, Qnil);
3841 delta *= (widthflag ? defwidth : defheight);
3846 maxdelta = ((!NILP (parent))
3847 ? (*sizefun) (parent) - *sizep
3848 : ((!NILP (w->next))
3849 ? (*sizefun) (w->next) - MINSIZE (w->next)
3850 : ((!NILP (w->prev))
3851 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3852 /* This is a frame with only one window,
3853 a minibuffer-only or a minibufferless frame. */
3856 if (delta > maxdelta)
3857 /* This case traps trying to make the minibuffer
3858 the full frame, or make the only window aside from the
3859 minibuffer the full frame. */
3866 /* #### Chuck: is this correct? */
3867 if (*sizep + delta < MINSIZE (window))
3869 Fdelete_window (window);
3875 if (!NILP (w->next) &&
3876 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3878 CURBEG (XWINDOW (w->next)) += delta;
3879 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3880 (*setsizefun) (window, *sizep + delta, 0);
3882 else if (!NILP (w->prev) &&
3883 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3885 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3886 CURBEG (w) -= delta;
3887 (*setsizefun) (window, *sizep + delta, 0);
3892 int opht = (*sizefun) (parent);
3894 /* If trying to grow this window to or beyond size of the parent,
3895 make delta1 so big that, on shrinking back down,
3896 all the siblings end up with less than one line and are deleted. */
3897 if (opht <= *sizep + delta)
3898 delta1 = opht * opht * 2;
3899 /* Otherwise, make delta1 just right so that if we add delta1
3900 lines to this window and to the parent, and then shrink
3901 the parent back to its original size, the new proportional
3902 size of this window will increase by delta. */
3904 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3906 /* Add delta1 lines or columns to this window, and to the parent,
3907 keeping things consistent while not affecting siblings. */
3908 CURSIZE (XWINDOW (parent)) = opht + delta1;
3909 (*setsizefun) (window, *sizep + delta1, 0);
3911 /* Squeeze out delta1 lines or columns from our parent,
3912 shrinking this window and siblings proportionately.
3913 This brings parent back to correct size.
3914 Delta1 was calculated so this makes this window the desired size,
3915 taking it all out of the siblings. */
3916 (*setsizefun) (parent, opht, 0);
3919 SET_LAST_MODIFIED (w, 0);
3920 SET_LAST_FACECHANGE (w);
3921 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3931 /* Scroll contents of window WINDOW up N lines. */
3933 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3934 Error_behavior errb)
3936 struct window *w = XWINDOW (window);
3937 struct buffer *b = XBUFFER (w->buffer);
3938 int selected = EQ (window, Fselected_window (Qnil));
3940 Lisp_Object point, tem;
3943 point = make_int (BUF_PT (b));
3946 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3948 if (pos < BUF_BEGV (b))
3950 else if (pos > BUF_ZV (b))
3953 point = make_int (pos);
3956 /* Always set force_start so that redisplay_window will run
3957 the window-scroll-functions. */
3960 /* #### When the fuck does this happen? I'm so glad that history has
3961 completely documented the behavior of the scrolling functions under
3962 all circumstances. */
3963 tem = Fpos_visible_in_window_p (point, window);
3966 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
3968 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
3969 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
3970 MARK_WINDOWS_CHANGED (w);
3979 n = Fprefix_numeric_value (n);
3980 value = XINT (n) * direction;
3983 return; /* someone just made a pointless call */
3987 /* If the user didn't specify how far to scroll then we have to figure it
3988 out by ourselves. */
3989 if (NILP (n) || EQ (n, Qminus))
3991 /* Going forwards is easy. If that is what we are doing then just
3992 set value and the section which handles the user specifying a
3993 positive value will work. */
3996 value = window_displayed_height (w) - next_screen_context_lines;
3997 value = (value < 1 ? 1 : value);
4000 /* Going backwards is hard. We can't use the same loop used if the
4001 user specified a negative value because we care about
4002 next_screen_context_lines. In a variable height world you don't
4003 know how many lines above you can actually be displayed and still
4004 have the context lines appear. So we leave value set to 0 and add
4005 a separate section to deal with this. */
4009 if (direction == 1 && !value)
4016 Bufpos startp, old_start;
4018 old_start = marker_position (w->start[CURRENT_DISP]);
4019 startp = vmotion (w, old_start, value, &vtarget);
4021 if (vtarget < value &&
4022 (w->window_end_pos[CURRENT_DISP] == -1
4023 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4025 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4030 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4033 w->start_at_line_beg = beginning_of_line_p (b, startp);
4034 MARK_WINDOWS_CHANGED (w);
4036 if (!point_would_be_visible (w, startp, XINT (point)))
4039 BUF_SET_PT (b, startp);
4041 set_marker_restricted (w->pointm[CURRENT_DISP],
4050 Bufpos startp, old_start;
4052 old_start = marker_position (w->start[CURRENT_DISP]);
4053 startp = vmotion (w, old_start, value, &vtarget);
4056 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4058 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4063 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4066 w->start_at_line_beg = beginning_of_line_p (b, startp);
4067 MARK_WINDOWS_CHANGED (w);
4069 if (!point_would_be_visible (w, startp, XINT (point)))
4073 if (MINI_WINDOW_P (w))
4076 new_point = start_of_last_line (w, startp);
4079 BUF_SET_PT (b, new_point);
4081 set_marker_restricted (w->pointm[CURRENT_DISP],
4082 make_int (new_point),
4087 else /* value == 0 && direction == -1 */
4089 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4091 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4097 int movement = next_screen_context_lines - 1;
4098 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4099 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4101 start_with_point_on_display_line (w, bottom,
4102 -1 - (movement - vtarget));
4104 if (startp >= old_startp)
4105 startp = vmotion (w, old_startp, -1, NULL);
4107 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4110 w->start_at_line_beg = beginning_of_line_p (b, startp);
4111 MARK_WINDOWS_CHANGED (w);
4113 if (!point_would_be_visible (w, startp, XINT (point)))
4115 Bufpos new_point = start_of_last_line (w, startp);
4118 BUF_SET_PT (b, new_point);
4120 set_marker_restricted (w->pointm[CURRENT_DISP],
4121 make_int (new_point),
4129 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4130 Scroll text of current window upward N lines; or near full screen if no arg.
4131 A near full screen is `next-screen-context-lines' less than a full screen.
4132 Negative N means scroll downward.
4133 When calling from a program, supply an integer as argument or nil.
4134 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4135 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4140 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4144 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4145 Scroll text of current window downward N lines; or near full screen if no arg.
4146 A near full screen is `next-screen-context-lines' less than a full screen.
4147 Negative N means scroll upward.
4148 When calling from a program, supply a number as argument or nil.
4149 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4150 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4155 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4159 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4160 Return the other window for "other window scroll" commands.
4161 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4162 specifies the window.
4163 If `other-window-scroll-buffer' is non-nil, a window
4164 showing that buffer is used.
4169 Lisp_Object selected_window = Fselected_window (Qnil);
4171 if (MINI_WINDOW_P (XWINDOW (selected_window))
4172 && !NILP (Vminibuffer_scroll_window))
4173 window = Vminibuffer_scroll_window;
4174 /* If buffer is specified, scroll that buffer. */
4175 else if (!NILP (Vother_window_scroll_buffer))
4177 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4179 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4183 /* Nothing specified; look for a neighboring window on the same
4185 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4187 if (EQ (window, selected_window))
4188 /* That didn't get us anywhere; look for a window on another
4191 window = Fnext_window (window, Qnil, Qt, Qnil);
4192 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4193 && ! EQ (window, selected_window));
4196 CHECK_LIVE_WINDOW (window);
4198 if (EQ (window, selected_window))
4199 error ("There is no other window");
4204 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4205 Scroll next window upward N lines; or near full frame if no arg.
4206 The next window is the one below the current one; or the one at the top
4207 if the current one is at the bottom. Negative N means scroll downward.
4208 When calling from a program, supply a number as argument or nil.
4210 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4211 specifies the window to scroll.
4212 If `other-window-scroll-buffer' is non-nil, scroll the window
4213 showing that buffer, popping the buffer up if necessary.
4217 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4221 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4222 Scroll selected window display N columns left.
4223 Default for N is window width minus 2.
4227 Lisp_Object window = Fselected_window (Qnil);
4228 struct window *w = XWINDOW (window);
4229 int count = (NILP (n) ?
4230 window_char_width (w, 0) - 2 :
4231 XINT (Fprefix_numeric_value (n)));
4233 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4236 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4237 Scroll selected window display N columns right.
4238 Default for N is window width minus 2.
4242 Lisp_Object window = Fselected_window (Qnil);
4243 struct window *w = XWINDOW (window);
4244 int count = (NILP (n) ?
4245 window_char_width (w, 0) - 2 :
4246 XINT (Fprefix_numeric_value (n)));
4248 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4251 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4252 Center point in WINDOW. With N, put point on line N.
4253 The desired position of point is always relative to the window.
4254 If WINDOW is nil, the selected window is used.
4258 struct window *w = decode_window (window);
4259 struct buffer *b = XBUFFER (w->buffer);
4260 Bufpos opoint = BUF_PT (b);
4264 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4267 n = Fprefix_numeric_value (n);
4269 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4272 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4274 w->start_at_line_beg = beginning_of_line_p (b, startp);
4276 MARK_WINDOWS_CHANGED (w);
4280 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4281 Position point relative to WINDOW.
4282 With no argument, position text at center of window.
4283 An argument specifies window line; zero means top of window,
4284 negative means relative to bottom of window.
4285 If WINDOW is nil, the selected window is used.
4292 Bufpos start, new_point;
4295 /* Don't use decode_window() because we need the new value of
4298 window = Fselected_window (Qnil);
4300 CHECK_WINDOW (window);
4301 w = XWINDOW (window);
4302 b = XBUFFER (w->buffer);
4304 height = window_displayed_height (w);
4305 selected = EQ (window, Fselected_window (w->frame));
4311 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4312 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4314 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4317 BUF_SET_PT (b, new_point);
4319 Fset_window_point (window, make_int (new_point));
4321 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4325 start = marker_position (w->start[CURRENT_DISP]);
4326 if (start < BUF_BEGV (b))
4327 start = BUF_BEGV (b);
4328 else if (start > BUF_ZV (b))
4332 new_point = BUF_PT (b);
4334 new_point = marker_position (w->pointm[CURRENT_DISP]);
4336 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4339 BUF_SET_PT (b, new_point);
4341 Fset_window_point (window, make_int (new_point));
4343 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4346 return make_int (retval);
4350 /* #### Is this going to work right when at eob? */
4351 arg = Fprefix_numeric_value (arg);
4353 XSETINT (arg, XINT (arg) + height);
4356 start = marker_position (w->start[CURRENT_DISP]);
4357 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4360 new_point = BUF_PT (b);
4362 new_point = marker_position (w->pointm[CURRENT_DISP]);
4364 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4367 BUF_SET_PT (b, new_point);
4369 Fset_window_point (window, make_int (new_point));
4371 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4373 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4379 BUF_SET_PT (b, start);
4381 Fset_window_point (window, make_int (start));
4385 return Fvertical_motion (arg, window, Qnil);
4389 new_point = vmotion (XWINDOW (window),
4390 marker_position (w->pointm[CURRENT_DISP]),
4392 Fset_window_point (window, make_int (new_point));
4393 return make_int (vpos);
4399 map_windows_1 (Lisp_Object window,
4400 int (*mapfun) (struct window *w, void *closure),
4403 for (; !NILP (window); window = XWINDOW (window)->next)
4406 struct window *w = XWINDOW (window);
4408 if (!NILP (w->vchild))
4409 retval = map_windows_1 (w->vchild, mapfun, closure);
4410 else if (!NILP (w->hchild))
4411 retval = map_windows_1 (w->hchild, mapfun, closure);
4413 retval = (mapfun) (w, closure);
4422 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4423 invocation of MAPFUN. If any invocation of MAPFUN returns
4424 non-zero, the mapping is halted. Otherwise, map_windows() maps
4425 over all windows in F.
4427 If MAPFUN creates or deletes windows, the behavior is undefined. */
4430 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4434 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4437 Lisp_Object frmcons, devcons, concons;
4439 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4441 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4453 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4456 w->shadow_thickness_changed = 1;
4457 MARK_WINDOWS_CHANGED (w);
4461 vertical_divider_changed_in_window (Lisp_Object specifier,
4465 MARK_WINDOWS_CHANGED (w);
4466 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4469 /* also used in scrollbar.c */
4471 some_window_value_changed (Lisp_Object specifier, struct window *w,
4474 MARK_WINDOWS_CHANGED (w);
4477 #ifdef MEMORY_USAGE_STATS
4483 #ifdef HAVE_SCROLLBARS
4487 int other_redisplay;
4492 compute_window_mirror_usage (struct window_mirror *mir,
4493 struct window_stats *stats,
4494 struct overhead_stats *ovstats)
4498 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4500 #ifdef HAVE_SCROLLBARS
4502 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4505 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4508 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4511 #endif /* HAVE_SCROLLBARS */
4512 stats->other_redisplay +=
4513 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4514 stats->other_redisplay +=
4515 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4519 compute_window_usage (struct window *w, struct window_stats *stats,
4520 struct overhead_stats *ovstats)
4523 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4524 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4525 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4526 stats->line_start +=
4527 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4528 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4531 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4532 Return stats about the memory usage of window WINDOW.
4533 The values returned are in the form of an alist of usage types and byte
4534 counts. The byte counts attempt to encompass all the memory used
4535 by the window (separate from the memory logically associated with a
4536 buffer or frame), including internal structures and any malloc()
4537 overhead associated with them. In practice, the byte counts are
4538 underestimated because certain memory usage is very hard to determine
4539 \(e.g. the amount of memory used inside the Xt library or inside the
4540 X server) and because there is other stuff that might logically
4541 be associated with a window, buffer, or frame (e.g. window configurations,
4542 glyphs) but should not obviously be included in the usage counts.
4544 Multiple slices of the total memory usage may be returned, separated
4545 by a nil. Each slice represents a particular view of the memory, a
4546 particular way of partitioning it into groups. Within a slice, there
4547 is no overlap between the groups of memory, and each slice collectively
4548 represents all the memory concerned.
4552 struct window_stats stats;
4553 struct overhead_stats ovstats;
4554 Lisp_Object val = Qnil;
4556 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4558 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4560 val = acons (Qface_cache, make_int (stats.face), val);
4561 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4562 #ifdef HAVE_SCROLLBARS
4563 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4565 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4566 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4567 val = acons (Qother, make_int (stats.other), val);
4568 val = Fcons (Qnil, val);
4569 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4570 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4571 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4573 return Fnreverse (val);
4576 #endif /* MEMORY_USAGE_STATS */
4579 /************************************************************************/
4580 /* Window configurations */
4581 /************************************************************************/
4583 /* #### This window configuration stuff has had serious bugs lurking in it
4584 for years; it would be a -huge- win if this was reimplemented in lisp.
4587 /* If you add anything to this structure make sure saved_window_equal
4591 Lisp_Object window; /* window */
4592 Lisp_Object buffer; /* buffer */
4593 Lisp_Object start; /* copied marker */
4594 Lisp_Object pointm; /* copied marker */
4595 Lisp_Object sb_point; /* copied marker */
4596 Lisp_Object mark; /* copied marker */
4602 int modeline_hscroll;
4603 int parent_index; /* index into saved_windows */
4604 int prev_index; /* index into saved_windows */
4605 char start_at_line_beg; /* boolean */
4607 #define WINDOW_SLOT_DECLARATION
4608 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4609 #include "winslots.h"
4612 /* If you add anything to this structure make sure window_config_equal
4614 struct window_config
4616 struct lcrecord_header header;
4620 Lisp_Object selected_frame;
4622 Lisp_Object current_window;
4623 Lisp_Object current_buffer;
4624 Lisp_Object minibuffer_scroll_window;
4625 Lisp_Object root_window;
4626 /* Record the values of window-min-width and window-min-height
4627 so that window sizes remain consistent with them. */
4628 int min_width, min_height;
4629 int saved_windows_count;
4630 /* Zero-sized arrays aren't ANSI C */
4631 struct saved_window saved_windows[1];
4634 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4635 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4636 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4637 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4638 #define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
4639 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4642 mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
4644 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4646 markobj (config->current_window);
4647 markobj (config->current_buffer);
4648 markobj (config->minibuffer_scroll_window);
4649 markobj (config->root_window);
4651 for (i = 0; i < config->saved_windows_count; i++)
4653 struct saved_window *s = SAVED_WINDOW_N (config, i);
4654 markobj (s->window);
4655 markobj (s->buffer);
4657 markobj (s->pointm);
4658 markobj (s->sb_point);
4661 /* #### This looked like this. I do not see why specifier cached
4662 values should not be marked, as such specifiers as toolbars
4663 might have GC-able instances. Freed configs are not marked,
4664 aren't they? -- kkm */
4665 markobj (s->dedicated);
4667 #define WINDOW_SLOT(slot, compare) ((void) (markobj (s->slot)))
4668 #include "winslots.h"
4675 sizeof_window_config_for_n_windows (int n)
4677 return (sizeof (struct window_config) +
4678 /* n - 1 because zero-sized arrays aren't ANSI C */
4679 (n - 1) *sizeof (struct saved_window));
4683 sizeof_window_config (CONST void *h)
4685 CONST struct window_config *c = (CONST struct window_config *) h;
4686 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4690 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4692 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4695 error ("printing unreadable object #<window-configuration 0x%x>",
4696 config->header.uid);
4697 write_c_string ("#<window-configuration ", printcharfun);
4698 sprintf (buf, "0x%x>", config->header.uid);
4699 write_c_string (buf, printcharfun);
4702 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4703 window_configuration,
4705 print_window_config,
4706 0, 0, 0, sizeof_window_config,
4707 struct window_config);
4710 /* Returns a boolean indicating whether the two saved windows are
4713 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4715 #define WINDOW_SLOT(slot, compare) \
4716 if (!compare (win1->slot, win2->slot)) \
4718 #include "winslots.h"
4721 EQ (win1->window, win2->window) &&
4722 EQ (win1->buffer, win2->buffer) &&
4723 internal_equal (win1->start, win2->start, 0) &&
4724 internal_equal (win1->pointm, win2->pointm, 0) &&
4725 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4726 internal_equal (win1->mark, win2->mark, 0) &&
4727 win1->pixel_left == win2->pixel_left &&
4728 win1->pixel_top == win2->pixel_top &&
4729 win1->pixel_width == win2->pixel_width &&
4730 win1->pixel_height == win2->pixel_height &&
4731 win1->hscroll == win2->hscroll &&
4732 win1->modeline_hscroll == win2->modeline_hscroll &&
4733 win1->parent_index == win2->parent_index &&
4734 win1->prev_index == win2->prev_index &&
4735 win1->start_at_line_beg == win2->start_at_line_beg;
4738 /* Returns a boolean indicating whether the two given configurations
4741 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4743 struct window_config *fig1, *fig2;
4746 /* First check if they are truly the same. */
4747 if (EQ (conf1, conf2))
4750 fig1 = XWINDOW_CONFIGURATION (conf1);
4751 fig2 = XWINDOW_CONFIGURATION (conf2);
4753 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4754 EQ (fig1->current_window, fig2->current_window) &&
4755 EQ (fig1->current_buffer, fig2->current_buffer) &&
4756 EQ (fig1->root_window, fig2->root_window) &&
4757 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window) &&
4758 fig1->frame_width == fig2->frame_width &&
4759 fig1->frame_height == fig2->frame_height))
4762 for (i = 0; i < fig1->saved_windows_count; i++)
4764 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4765 SAVED_WINDOW_N (fig2, i)))
4772 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4773 Return t if OBJECT is a window-configuration object.
4777 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4781 mark_windows_in_use_closure (struct window *w, void *closure)
4783 int mark = *(int *)closure;
4784 w->config_mark = mark;
4789 mark_windows_in_use (struct frame *f, int mark)
4791 map_windows (f, mark_windows_in_use_closure, &mark);
4794 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4796 free_window_configuration (Lisp_Object window_config)
4799 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4801 /* Free all the markers. It's not completely necessary that
4802 we do this (window configs sitting in a free list aren't
4803 marked normally so the markers wouldn't be marked anyway)
4804 but it's more efficient. */
4805 for (i = 0; i < config->saved_windows_count; i++)
4807 struct saved_window *p = SAVED_WINDOW_N (config, i);
4809 if (!NILP (p->pointm))
4811 free_marker (XMARKER (p->pointm));
4814 if (!NILP (p->start))
4816 free_marker (XMARKER (p->start));
4819 if (!NILP (p->sb_point))
4821 free_marker (XMARKER (p->sb_point));
4824 if (!NILP (p->mark))
4826 free_marker (XMARKER (p->mark));
4831 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4832 free_managed_lcrecord (Vwindow_configuration_free_list
4833 [config->saved_windows_count - 1],
4839 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4840 Set the configuration of windows and buffers as specified by CONFIGURATION.
4841 CONFIGURATION must be a value previously returned
4842 by `current-window-configuration' (which see).
4847 struct window_config *config;
4848 struct saved_window *p;
4849 Lisp_Object new_current_buffer;
4853 struct gcpro gcpro1;
4854 Lisp_Object old_window_config;
4855 int previous_frame_height;
4856 int previous_frame_width;
4857 int specpdl_count = specpdl_depth ();
4859 GCPRO1 (configuration);
4861 CHECK_WINDOW_CONFIGURATION (configuration);
4862 config = XWINDOW_CONFIGURATION (configuration);
4864 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4867 /* Do not signal an error here if the frame was deleted. There are
4868 reasonable cases where we could get here with a deleted frame and
4869 just want to do close to nothing instead. */
4871 if (FRAME_LIVE_P (f))
4873 /* restore the frame characteristics */
4875 new_current_buffer = config->current_buffer;
4876 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4877 new_current_buffer = Qnil;
4880 * Assumed precondition: w->config_mark = 0 for all w
4881 * This procedure should ensure this is true by the time it exits
4882 * to ensure the precondition for future calls.
4884 * We use w->config_mark to know whether we're modifying a
4885 * window that is currently visible on the frame (#### we
4886 * should just be able to check whether the window is dead
4887 * or not, but this way is safer?). As we process each
4888 * window, we set its config_mark to 0. At the end, we
4889 * go through all the windows that used to be on the frame,
4890 * set each one's config_mark to 0 (to maintain the
4891 * assumed precondition) and delete each one that's no
4894 * #### Using a window-configuration to keep track of
4895 * the current windows is wasteful. All we need is the
4896 * list of windows, so we could just use a dynarr.
4898 old_window_config = Fcurrent_window_configuration (frame);
4900 /* If the new configuration is already equal to the old, then stop
4901 right here. This saves the work below and it also saves
4902 triggering a full redisplay of this window. This is a huge win
4903 when using the mouse since the mode motion code uses
4904 save-window-excursion extensively but will rarely cause the
4905 configuration to actually change. */
4906 if (window_config_equal (configuration, old_window_config))
4908 free_window_configuration (old_window_config);
4913 /* We can't quit or even check for quit because that may cause
4914 investigation of the frame state, which may crash if the frame is
4915 in an inconsistent state. */
4916 begin_dont_check_for_quit ();
4917 record_unwind_protect (free_window_configuration, old_window_config);
4919 mark_windows_in_use (f, 1);
4921 previous_frame_width = FRAME_WIDTH (f);
4922 previous_frame_height = FRAME_HEIGHT (f);
4923 /* If the frame has been resized since this window configuration was
4924 made, we change the frame to the size specified in the
4925 configuration, restore the configuration, and then resize it
4926 back. We keep track of the prevailing height in these variables. */
4927 if (config->frame_height != FRAME_HEIGHT (f)
4928 || config->frame_width != FRAME_WIDTH (f))
4929 change_frame_size (f, config->frame_height, config->frame_width, 0);
4931 /* Temporarily avoid any problems with windows that are smaller
4932 than they are supposed to be. */
4933 window_min_height = 1;
4934 window_min_width = 1;
4936 /* OK, now restore all the windows in the window config.
4937 This may involve "undeleting" windows, since the
4938 windows in the window config may be deleted.
4940 for (k = 0; k < config->saved_windows_count; k++)
4942 p = SAVED_WINDOW_N (config, k);
4943 w = XWINDOW (p->window);
4946 /* The window might be dead. In this case, its redisplay
4947 structures were freed, so we need to reallocate them. */
4948 if (!w->face_cachels)
4950 w->face_cachels = Dynarr_new (face_cachel);
4951 reset_face_cachels (w);
4953 if (!w->glyph_cachels)
4954 w->glyph_cachels = Dynarr_new (glyph_cachel);
4955 if (!w->line_start_cache)
4956 w->line_start_cache = Dynarr_new (line_start_cache);
4959 if (p->parent_index >= 0)
4960 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
4964 if (p->prev_index >= 0)
4966 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
4968 /* This is true for a minibuffer-only frame. */
4969 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
4972 XWINDOW (w->prev)->next = p->window;
4977 if (!NILP (w->parent))
4979 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
4981 XWINDOW (w->parent)->vchild = p->window;
4982 XWINDOW (w->parent)->hchild = Qnil;
4986 XWINDOW (w->parent)->hchild = p->window;
4987 XWINDOW (w->parent)->vchild = Qnil;
4991 if (!w->config_mark)
4993 /* #### This should be equivalent to the window previously
4994 having been dead. If we're brave, we'll put in an
4995 assertion to this effect. */
4996 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4998 else /* if (!EQ (w->buffer, p->buffer)) */
5000 /* With the new redisplay we let it know that a change has
5001 been made and it will take care of the rest. If we don't
5002 tell it something has possibly changed it could lead to
5003 incorrect display. */
5004 MARK_WINDOWS_CHANGED (w);
5007 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5008 WINDOW_TOP (w) = WINDOW_TOP (p);
5009 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5010 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5011 w->hscroll = p->hscroll;
5012 w->modeline_hscroll = p->modeline_hscroll;
5013 w->line_cache_last_updated = Qzero;
5014 SET_LAST_MODIFIED (w, 1);
5015 SET_LAST_FACECHANGE (w);
5018 #define WINDOW_SLOT(slot, compare) w->slot = p->slot;
5019 #include "winslots.h"
5021 /* Reinstall the saved buffer and pointers into it. */
5022 if (NILP (p->buffer))
5023 w->buffer = p->buffer;
5026 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5027 /* If saved buffer is alive, install it. */
5029 w->buffer = p->buffer;
5030 w->start_at_line_beg = p->start_at_line_beg;
5031 set_marker_restricted (w->start[CURRENT_DISP],
5032 Fmarker_position (p->start),
5034 set_marker_restricted (w->pointm[CURRENT_DISP],
5035 Fmarker_position (p->pointm),
5037 set_marker_restricted (w->sb_point,
5038 Fmarker_position (p->sb_point),
5040 Fset_marker (XBUFFER (w->buffer)->mark,
5041 Fmarker_position (p->mark), w->buffer);
5043 /* As documented in Fcurrent_window_configuration, don't
5044 save the location of point in the buffer which was current
5045 when the window configuration was recorded. */
5046 if (!EQ (p->buffer, new_current_buffer) &&
5047 XBUFFER (p->buffer) == current_buffer)
5048 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5050 else if (NILP (w->buffer) ||
5051 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5052 /* Else if window's old buffer is dead too, get a live one. */
5054 /* #### The following line makes me nervous... */
5055 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5056 w->buffer = Fget_buffer_create (QSscratch);
5057 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5058 /* This will set the markers to beginning of visible
5060 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5061 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5063 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5064 w->start_at_line_beg = 1;
5067 /* Keeping window's old buffer; make sure the markers
5070 /* Set window markers at start of visible range. */
5071 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5072 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5074 if (XMARKER (w->sb_point)->buffer == 0)
5075 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5076 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5077 set_marker_restricted (w->pointm[CURRENT_DISP],
5079 (BUF_PT (XBUFFER (w->buffer))),
5081 w->start_at_line_beg = 1;
5086 FRAME_ROOT_WINDOW (f) = config->root_window;
5087 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5088 then calls do_switch_frame() below to select the frame that was
5089 recorded in the window config as being selected.
5091 Instead, we don't ever change the selected frame, and either
5092 call Fselect_window() below if the window config's frame is
5093 currently selected, or just set the selected window of the
5094 window config's frame. */
5096 /* Set the frame height to the value it had before this function. */
5097 if (previous_frame_height != FRAME_HEIGHT (f)
5098 || previous_frame_width != FRAME_WIDTH (f))
5099 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5101 /* If restoring in the current frame make the window current,
5102 otherwise just update the frame selected_window slot to be
5103 the restored current_window. */
5104 if (f == selected_frame ())
5106 /* When using `pop-window-configuration', often the minibuffer
5107 ends up as the selected window even though it's not active ...
5108 I really don't know the cause of this, but it should never
5109 happen. This kludge should fix it.
5111 #### Find out why this is really going wrong. */
5112 if (!minibuf_level &&
5113 MINI_WINDOW_P (XWINDOW (config->current_window)))
5114 Fselect_window (Fnext_window (config->current_window,
5118 Fselect_window (config->current_window, Qnil);
5119 if (!NILP (new_current_buffer))
5120 Fset_buffer (new_current_buffer);
5122 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5125 set_frame_selected_window (f, config->current_window);
5128 old_window_config = Qnil; /* Warning suppression */
5130 /* Restore the minimum heights recorded in the configuration. */
5131 window_min_height = config->min_height;
5132 window_min_width = config->min_width;
5135 /* see above comment */
5136 /* Fselect_window will have made f the selected frame, so we
5137 reselect the proper frame here. Fhandle_switch_frame will change the
5138 selected window too, but that doesn't make the call to
5139 Fselect_window above totally superfluous; it still sets f's
5141 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5142 do_switch_frame (config->selected_frame, Qnil, 0);
5145 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5147 if (FRAME_LIVE_P (f))
5149 /* Do this before calling recompute_all_cached_specifiers_in_window()
5150 so that things like redisplay_redraw_cursor() won't abort due
5151 to no window mirror present. */
5152 f->mirror_dirty = 1;
5154 config = XWINDOW_CONFIGURATION (old_window_config);
5155 for (k = 0; k < config->saved_windows_count; k++)
5157 p = SAVED_WINDOW_N (config, k);
5158 w = XWINDOW (p->window);
5159 /* Remember, we set w->config_mark on all currently visible
5160 windows, and reset it on all newly visible windows.
5161 Any windows still marked need to be deleted. */
5164 mark_window_as_deleted (w);
5169 /* We just potentially changed the window's buffer and
5170 potentially turned a dead window into a live one,
5171 so we need to recompute the cached specifier values. */
5172 recompute_all_cached_specifiers_in_window (w);
5177 /* Now restore things, when everything else if OK. */
5179 unbind_to (specpdl_count, Qnil);
5186 /* Mark all subwindows of a window as deleted. The argument
5187 W is actually the subwindow tree of the window in question. */
5190 delete_all_subwindows (struct window *w)
5192 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5193 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5194 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5196 mark_window_as_deleted (w);
5201 count_windows (struct window *window)
5204 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5205 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5206 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5210 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5213 for (j = 0; j < lim; j++)
5215 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5219 return 0; /* suppress compiler warning */
5223 save_window_save (Lisp_Object window, struct window_config *config, int i)
5227 for (; !NILP (window); window = w->next)
5229 struct saved_window *p = SAVED_WINDOW_N (config, i);
5231 w = XWINDOW (window);
5234 p->buffer = w->buffer;
5235 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5236 WINDOW_TOP (p) = WINDOW_TOP (w);
5237 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5238 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5239 p->hscroll = w->hscroll;
5240 p->modeline_hscroll = w->modeline_hscroll;
5242 #define WINDOW_SLOT(slot, compare) p->slot = w->slot;
5243 #include "winslots.h"
5245 if (!NILP (w->buffer))
5247 /* Save w's value of point in the window configuration.
5248 If w is the selected window, then get the value of point
5249 from the buffer; pointm is garbage in the selected window. */
5250 if (EQ (window, Fselected_window (Qnil)))
5252 p->pointm = noseeum_make_marker ();
5253 Fset_marker (p->pointm,
5254 make_int (BUF_PT (XBUFFER (w->buffer))),
5258 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5260 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5261 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5262 p->start_at_line_beg = w->start_at_line_beg;
5264 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5272 p->start_at_line_beg = 0;
5275 if (NILP (w->parent))
5276 p->parent_index = -1;
5278 p->parent_index = saved_window_index (w->parent, config, i);
5282 p->prev_index = saved_window_index (w->prev, config, i);
5283 if (!NILP (w->vchild))
5284 i = save_window_save (w->vchild, config, i);
5285 if (!NILP (w->hchild))
5286 i = save_window_save (w->hchild, config, i);
5293 /* Added to doc string:
5295 This also records the currently selected frame, and FRAME's focus
5296 redirection (see `redirect-frame-focus').
5301 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5302 Return an object representing the current window configuration of FRAME.
5303 If FRAME is nil or omitted, use the selected frame.
5304 This describes the number of windows, their sizes and current buffers,
5305 and for each displayed buffer, where display starts, and the positions of
5306 point and mark. An exception is made for point in the current buffer:
5307 its value is -not- saved.
5312 struct frame *f = decode_frame (frame);
5313 struct window_config *config;
5314 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5316 if (n_windows <= countof (Vwindow_configuration_free_list))
5317 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5318 (Vwindow_configuration_free_list
5321 /* More than ten windows; just allocate directly */
5322 config = (struct window_config *)
5323 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5324 lrecord_window_configuration);
5325 XSETWINDOW_CONFIGURATION (result, config);
5327 config->frame_width = FRAME_WIDTH (f);
5328 config->frame_height = FRAME_HEIGHT (f);
5329 config->current_window = FRAME_SELECTED_WINDOW (f);
5330 XSETBUFFER (config->current_buffer, current_buffer);
5331 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5332 config->root_window = FRAME_ROOT_WINDOW (f);
5333 config->min_height = window_min_height;
5334 config->min_width = window_min_width;
5335 config->saved_windows_count = n_windows;
5336 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5341 save_window_excursion_unwind (Lisp_Object window_config)
5343 Lisp_Object val = Fset_window_configuration (window_config);
5344 free_window_configuration (window_config);
5348 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5349 Execute body, preserving window sizes and contents.
5350 Restores which buffer appears in which window, where display starts,
5351 as well as the current buffer.
5352 Does not restore the value of point in current buffer.
5356 /* This function can GC */
5358 int speccount = specpdl_depth ();
5360 record_unwind_protect (save_window_excursion_unwind,
5361 Fcurrent_window_configuration (Qnil));
5362 val = Fprogn (args);
5363 return unbind_to (speccount, val);
5368 /* This is short and simple in elisp, but... it was written to debug
5369 problems purely on the C side. That is where we need to call it so
5372 debug_print_window (Lisp_Object window, int level)
5375 Lisp_Object child = Fwindow_first_vchild (window);
5378 child = Fwindow_first_hchild (window);
5380 for (i = level; i > 0; i--)
5381 putc ('\t', stderr);
5383 fputs ("#<window", stderr);
5385 Lisp_Object buffer = XWINDOW (window)->buffer;
5386 if (!NILP (buffer) && BUFFERP (buffer))
5387 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5389 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5391 while (!NILP (child))
5393 debug_print_window (child, level + 1);
5394 child = Fwindow_next_child (child);
5398 void debug_print_windows (struct frame *f);
5400 debug_print_windows (struct frame *f)
5402 debug_print_window (f->root_window, 0);
5403 putc ('\n', stderr);
5405 #endif /* DEBUG_XEMACS */
5408 /************************************************************************/
5409 /* initialization */
5410 /************************************************************************/
5413 syms_of_window (void)
5415 defsymbol (&Qwindowp, "windowp");
5416 defsymbol (&Qwindow_live_p, "window-live-p");
5417 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5418 defsymbol (&Qscroll_up, "scroll-up");
5419 defsymbol (&Qscroll_down, "scroll-down");
5420 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5421 defsymbol (&Qdisplay_buffer, "display-buffer");
5423 #ifdef MEMORY_USAGE_STATS
5424 defsymbol (&Qface_cache, "face-cache");
5425 defsymbol (&Qglyph_cache, "glyph-cache");
5426 defsymbol (&Qline_start_cache, "line-start-cache");
5427 #ifdef HAVE_SCROLLBARS
5428 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5430 defsymbol (&Qother_redisplay, "other-redisplay");
5431 /* Qother in general.c */
5434 DEFSUBR (Fselected_window);
5435 DEFSUBR (Fminibuffer_window);
5436 DEFSUBR (Fwindow_minibuffer_p);
5438 DEFSUBR (Fwindow_live_p);
5439 DEFSUBR (Fwindow_first_hchild);
5440 DEFSUBR (Fwindow_first_vchild);
5441 DEFSUBR (Fwindow_next_child);
5442 DEFSUBR (Fwindow_previous_child);
5443 DEFSUBR (Fwindow_parent);
5444 DEFSUBR (Fwindow_lowest_p);
5445 DEFSUBR (Fwindow_highest_p);
5446 DEFSUBR (Fwindow_leftmost_p);
5447 DEFSUBR (Fwindow_rightmost_p);
5448 DEFSUBR (Fpos_visible_in_window_p);
5449 DEFSUBR (Fwindow_buffer);
5450 DEFSUBR (Fwindow_frame);
5451 DEFSUBR (Fwindow_height);
5452 DEFSUBR (Fwindow_displayed_height);
5453 DEFSUBR (Fwindow_width);
5454 DEFSUBR (Fwindow_pixel_height);
5455 DEFSUBR (Fwindow_pixel_width);
5456 DEFSUBR (Fwindow_text_area_pixel_height);
5457 DEFSUBR (Fwindow_displayed_text_pixel_height);
5458 DEFSUBR (Fwindow_text_area_pixel_width);
5459 DEFSUBR (Fwindow_hscroll);
5460 #ifdef MODELINE_IS_SCROLLABLE
5461 DEFSUBR (Fmodeline_hscroll);
5462 DEFSUBR (Fset_modeline_hscroll);
5463 #endif /* MODELINE_IS_SCROLLABLE */
5464 #if 0 /* bogus FSF crock */
5465 DEFSUBR (Fwindow_redisplay_end_trigger);
5466 DEFSUBR (Fset_window_redisplay_end_trigger);
5468 DEFSUBR (Fset_window_hscroll);
5469 DEFSUBR (Fwindow_pixel_edges);
5470 DEFSUBR (Fwindow_text_area_pixel_edges);
5471 DEFSUBR (Fwindow_point);
5472 DEFSUBR (Fwindow_start);
5473 DEFSUBR (Fwindow_end);
5474 DEFSUBR (Fset_window_point);
5475 DEFSUBR (Fset_window_start);
5476 DEFSUBR (Fwindow_dedicated_p);
5477 DEFSUBR (Fset_window_dedicated_p);
5478 DEFSUBR (Fnext_window);
5479 DEFSUBR (Fprevious_window);
5480 DEFSUBR (Fnext_vertical_window);
5481 DEFSUBR (Fother_window);
5482 DEFSUBR (Fget_lru_window);
5483 DEFSUBR (Fget_largest_window);
5484 DEFSUBR (Fget_buffer_window);
5485 DEFSUBR (Fwindow_left_margin_pixel_width);
5486 DEFSUBR (Fwindow_right_margin_pixel_width);
5487 DEFSUBR (Fdelete_other_windows);
5488 DEFSUBR (Fdelete_windows_on);
5489 DEFSUBR (Freplace_buffer_in_windows);
5490 DEFSUBR (Fdelete_window);
5491 DEFSUBR (Fset_window_buffer);
5492 DEFSUBR (Fselect_window);
5493 DEFSUBR (Fsplit_window);
5494 DEFSUBR (Fenlarge_window);
5495 DEFSUBR (Fenlarge_window_pixels);
5496 DEFSUBR (Fshrink_window);
5497 DEFSUBR (Fshrink_window_pixels);
5498 DEFSUBR (Fscroll_up);
5499 DEFSUBR (Fscroll_down);
5500 DEFSUBR (Fscroll_left);
5501 DEFSUBR (Fscroll_right);
5502 DEFSUBR (Fother_window_for_scrolling);
5503 DEFSUBR (Fscroll_other_window);
5504 DEFSUBR (Fcenter_to_window_line);
5505 DEFSUBR (Fmove_to_window_line);
5506 #ifdef MEMORY_USAGE_STATS
5507 DEFSUBR (Fwindow_memory_usage);
5509 DEFSUBR (Fwindow_configuration_p);
5510 DEFSUBR (Fset_window_configuration);
5511 DEFSUBR (Fcurrent_window_configuration);
5512 DEFSUBR (Fsave_window_excursion);
5516 vars_of_window (void)
5518 /* Make sure all windows get marked */
5519 minibuf_window = Qnil;
5520 staticpro (&minibuf_window);
5522 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5523 *Non-nil means to scroll if point lands on a line which is clipped.
5525 scroll_on_clipped_lines = 1;
5527 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5528 See `temp-buffer-show-function'.
5530 Vtemp_buffer_show_hook = Qnil;
5532 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5533 Non-nil means call as function to display a help buffer.
5534 The function is called with one argument, the buffer to be displayed.
5535 Used by `with-output-to-temp-buffer'.
5536 If this function is used, then it must do the entire job of showing
5537 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5539 Vtemp_buffer_show_function = Qnil;
5541 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5542 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5544 Vminibuffer_scroll_window = Qnil;
5546 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5547 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5549 Vother_window_scroll_buffer = Qnil;
5551 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5552 *Number of lines of continuity when scrolling by screenfuls.
5554 next_screen_context_lines = 2;
5556 DEFVAR_INT ("window-min-height", &window_min_height /*
5557 *Delete any window less than this tall (including its modeline).
5559 window_min_height = 4;
5561 DEFVAR_INT ("window-min-width", &window_min_width /*
5562 *Delete any window less than this wide.
5564 window_min_width = 10;
5569 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5571 Vwindow_configuration_free_list[i] =
5572 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5573 lrecord_window_configuration);
5574 staticpro (&Vwindow_configuration_free_list[i]);
5580 specifier_vars_of_window (void)
5582 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5583 *How thick to draw 3D shadows around modelines.
5584 If this is set to 0, modelines will be the traditional 2D. Sizes above
5585 10 will be accepted but the maximum thickness that will be drawn is 10.
5586 This is a specifier; use `set-specifier' to change it.
5588 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5589 /* The initial value for modeline-shadow-thickness is 2, but if the
5590 user removes all specifications we provide a fallback value of 0,
5591 which is probably what was expected. */
5592 set_specifier_fallback (Vmodeline_shadow_thickness,
5593 list1 (Fcons (Qnil, Qzero)));
5594 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5596 set_specifier_caching (Vmodeline_shadow_thickness,
5597 slot_offset (struct window,
5598 modeline_shadow_thickness),
5599 modeline_shadow_thickness_changed,
5602 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5603 *Whether the modeline should be displayed.
5604 This is a specifier; use `set-specifier' to change it.
5606 Vhas_modeline_p = Fmake_specifier (Qboolean);
5607 set_specifier_fallback (Vhas_modeline_p,
5608 list1 (Fcons (Qnil, Qt)));
5609 set_specifier_caching (Vhas_modeline_p,
5610 slot_offset (struct window,
5612 /* #### It's strange that we need a special
5613 flag to indicate that the shadow-thickness
5614 has changed, but not one to indicate that
5615 the modeline has been turned off or on. */
5616 some_window_value_changed,
5619 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5620 &Vvertical_divider_always_visible_p /*
5621 *Should XEmacs always display vertical dividers between windows.
5623 When this is non-nil, vertical dividers are always shown, and are
5624 draggable. When it is nil, vertical dividers are shown only when
5625 there are no scrollbars in between windows, and are not draggable.
5627 This is a specifier; use `set-specifier' to change it.
5629 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5630 set_specifier_fallback (Vvertical_divider_always_visible_p,
5631 list1 (Fcons (Qnil, Qt)));
5632 set_specifier_caching (Vvertical_divider_always_visible_p,
5633 slot_offset (struct window,
5634 vertical_divider_always_visible_p),
5635 vertical_divider_changed_in_window,
5638 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5639 *How thick to draw 3D shadows around vertical dividers.
5640 This is a specifier; use `set-specifier' to change it.
5642 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5643 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5644 list1 (Fcons (Qnil, Qzero)));
5645 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5647 set_specifier_caching (Vvertical_divider_shadow_thickness,
5648 slot_offset (struct window,
5649 vertical_divider_shadow_thickness),
5650 vertical_divider_changed_in_window,
5652 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5653 *The width of the vertical dividers, not including shadows.
5655 For TTY windows, divider line is always one character wide. When
5656 instance of this specifier is zero in a TTY window, no divider is
5657 drawn at all between windows. When non-zero, a one character wide
5658 divider is displayed.
5660 This is a specifier; use `set-specifier' to change it.
5663 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5665 Lisp_Object fb = Qnil;
5667 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
5669 #ifdef HAVE_X_WINDOWS
5670 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5672 #ifdef HAVE_MS_WINDOWS
5673 /* #### This should be made magic and made to obey system settings */
5674 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5676 set_specifier_fallback (Vvertical_divider_line_width, fb);
5678 set_specifier_caching (Vvertical_divider_line_width,
5679 slot_offset (struct window,
5680 vertical_divider_line_width),
5681 vertical_divider_changed_in_window,
5684 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5685 *How much space to leave around the vertical dividers.
5687 In TTY windows, spacing is always zero, and the value of this
5688 specifier is ignored.
5690 This is a specifier; use `set-specifier' to change it.
5692 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5694 Lisp_Object fb = Qnil;
5696 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5698 #ifdef HAVE_X_WINDOWS
5699 /* #### 3D dividers look great on MS Windows with spacing = 0.
5700 Should not the same value be the fallback under X? - kkm */
5701 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
5703 #ifdef HAVE_MS_WINDOWS
5704 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
5706 set_specifier_fallback (Vvertical_divider_spacing, fb);
5708 set_specifier_caching (Vvertical_divider_spacing,
5709 slot_offset (struct window,
5710 vertical_divider_spacing),
5711 vertical_divider_changed_in_window,