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"
41 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
42 Lisp_Object Qscroll_up, Qscroll_down, Qdisplay_buffer;
44 #ifdef MEMORY_USAGE_STATS
45 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
46 #ifdef HAVE_SCROLLBARS
47 Lisp_Object Qscrollbar_instances;
51 EXFUN (Fnext_window, 4);
53 static int window_pixel_width_to_char_width (struct window *w,
55 int include_margins_p);
56 static int window_char_width_to_pixel_width (struct window *w,
58 int include_margins_p);
59 static int window_pixel_height_to_char_height (struct window *w,
61 int include_gutters_p);
62 static int window_char_height_to_pixel_height (struct window *w,
64 int include_gutters_p);
65 static void change_window_height (struct window *w, int delta, int widthflag,
68 /* Thickness of shadow border around 3d modelines. */
69 Lisp_Object Vmodeline_shadow_thickness;
71 /* Whether vertical dividers are draggable and displayed */
72 Lisp_Object Vvertical_divider_always_visible_p;
74 /* Whether a modeline should be displayed. */
75 Lisp_Object Vhas_modeline_p;
77 /* Thickness of shadow border around vertical dividers. */
78 Lisp_Object Vvertical_divider_shadow_thickness;
80 /* Divider surface width (not counting 3-d borders) */
81 Lisp_Object Vvertical_divider_line_width;
83 /* Spacing between outer egde of divider border and window edge */
84 Lisp_Object Vvertical_divider_spacing;
86 /* Scroll if point lands on the bottom line and that line is partially
88 int scroll_on_clipped_lines;
90 /* The minibuffer window of the selected frame.
91 Note that you cannot test for minibufferness of an arbitrary window
92 by comparing against this; but you can test for minibufferness of
93 the selected window. */
94 Lisp_Object minibuf_window;
96 /* Non-nil means it is the window for C-M-v to scroll
97 when the minibuffer is selected. */
98 Lisp_Object Vminibuffer_scroll_window;
100 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
101 Lisp_Object Vother_window_scroll_buffer;
103 /* Non-nil means it's the function to call to display temp buffers. */
104 Lisp_Object Vtemp_buffer_show_function;
106 Lisp_Object Vtemp_buffer_show_hook;
108 /* If a window gets smaller than either of these, it is removed. */
109 int window_min_height;
110 int window_min_width;
112 /* Hook run at end of temp_output_buffer_show. */
113 Lisp_Object Qtemp_buffer_show_hook;
115 /* Number of lines of continuity in scrolling by screenfuls. */
116 int next_screen_context_lines;
118 /* List of freed window configurations with 1 - 10 windows. */
119 Lisp_Object Vwindow_configuration_free_list[10];
121 #define SET_LAST_MODIFIED(w, cache_too) \
123 (w)->last_modified[CURRENT_DISP] = Qzero; \
124 (w)->last_modified[DESIRED_DISP] = Qzero; \
125 (w)->last_modified[CMOTION_DISP] = Qzero; \
127 (w)->line_cache_last_updated = Qzero; \
130 #define SET_LAST_FACECHANGE(w) \
132 (w)->last_facechange[CURRENT_DISP] = Qzero; \
133 (w)->last_facechange[DESIRED_DISP] = Qzero; \
134 (w)->last_facechange[CMOTION_DISP] = Qzero; \
138 #define MARK_DISP_VARIABLE(field) \
139 ((markobj) (window->field[CURRENT_DISP])); \
140 ((markobj) (window->field[DESIRED_DISP])); \
141 ((markobj) (window->field[CMOTION_DISP]));
144 mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object))
146 struct window *window = XWINDOW (obj);
147 ((markobj) (window->frame));
148 ((markobj) (window->mini_p));
149 ((markobj) (window->next));
150 ((markobj) (window->prev));
151 ((markobj) (window->hchild));
152 ((markobj) (window->vchild));
153 ((markobj) (window->parent));
154 ((markobj) (window->buffer));
155 MARK_DISP_VARIABLE (start);
156 MARK_DISP_VARIABLE (pointm);
157 ((markobj) (window->sb_point)); /* #### move to scrollbar.c? */
158 ((markobj) (window->use_time));
159 MARK_DISP_VARIABLE (last_modified);
160 MARK_DISP_VARIABLE (last_point);
161 MARK_DISP_VARIABLE (last_start);
162 MARK_DISP_VARIABLE (last_facechange);
163 ((markobj) (window->line_cache_last_updated));
164 ((markobj) (window->redisplay_end_trigger));
165 mark_face_cachels (window->face_cachels, markobj);
166 mark_glyph_cachels (window->glyph_cachels, markobj);
168 #define WINDOW_SLOT(slot, compare) ((markobj) (window->slot))
169 #include "winslots.h"
175 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
180 error ("printing unreadable object #<window 0x%x>",
181 XWINDOW (obj)->header.uid);
183 write_c_string ("#<window", printcharfun);
184 if (!NILP (XWINDOW (obj)->buffer))
186 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
187 write_c_string (" on ", printcharfun);
188 print_internal (name, printcharfun, 1);
190 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
191 write_c_string (buf, printcharfun);
195 finalize_window (void *header, int for_disksave)
197 struct window *w = (struct window *) header;
199 if (w->line_start_cache)
201 Dynarr_free (w->line_start_cache);
202 w->line_start_cache = 0;
209 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
211 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
212 if (cachel->merged_faces)
214 Dynarr_free (cachel->merged_faces);
215 cachel->merged_faces = 0;
218 Dynarr_free (w->face_cachels);
222 if (w->glyph_cachels)
224 Dynarr_free (w->glyph_cachels);
225 w->glyph_cachels = 0;
229 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
230 mark_window, print_window, finalize_window,
231 0, 0, struct window);
234 #define INIT_DISP_VARIABLE(field, initialization) \
235 p->field[CURRENT_DISP] = initialization; \
236 p->field[DESIRED_DISP] = initialization; \
237 p->field[CMOTION_DISP] = initialization;
239 /* We have an implicit assertion that the first two elements (default
240 and modeline faces) are always present in the face_element_cache.
241 Normally redisplay ensures this. However, it is possible for a
242 window to get created and functions which reference these values
243 called before redisplay works with the window for the first time.
244 All callers of allocate_window should therefore call
245 reset_face_cachels on the created window. We can't do it
246 here because the window must have its frame pointer set or
247 reset_face_cachels will fail. */
249 allocate_window (void)
252 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
266 INIT_DISP_VARIABLE (start, Fmake_marker ());
267 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
268 p->sb_point = Fmake_marker ();
270 INIT_DISP_VARIABLE (last_modified, Qzero);
271 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
272 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
273 INIT_DISP_VARIABLE (last_facechange, Qzero);
274 p->face_cachels = Dynarr_new (face_cachel);
275 p->glyph_cachels = Dynarr_new (glyph_cachel);
276 p->line_start_cache = Dynarr_new (line_start_cache);
277 p->line_cache_last_updated = Qzero;
278 INIT_DISP_VARIABLE (last_point_x, 0);
279 INIT_DISP_VARIABLE (last_point_y, 0);
280 INIT_DISP_VARIABLE (window_end_pos, 0);
281 p->redisplay_end_trigger = Qnil;
283 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
284 #include "winslots.h"
286 p->windows_changed = 1;
287 p->shadow_thickness_changed = 1;
291 #undef INIT_DISP_VARIABLE
294 * The redisplay structures used to be stored with each window. While
295 * they are logically something associated with frames they can't be
296 * stored there with a redisplay which handles variable height lines.
297 * Lines in horizontally split windows might not line up. So they get
298 * stored with the windows.
300 * The problem with this is window configurations. When restoring a
301 * window configuration it now becomes problematic to do an
302 * incremental redisplay. The solution is to store the redisplay
303 * structures with the frame as they should be but laid out in the
304 * same manner as the window structure. Thus is born the window
307 * It also becomes a convenient place to stick scrollbar instances
308 * since they extrapolate out to having the same problem described for
309 * the display structures.
312 /* Create a new window mirror structure and associated redisplay
314 static struct window_mirror *
315 new_window_mirror (struct frame *f)
317 struct window_mirror *t = xnew_and_zero (struct window_mirror);
321 t->current_display_lines = Dynarr_new (display_line);
322 t->desired_display_lines = Dynarr_new (display_line);
325 #ifdef HAVE_SCROLLBARS
326 t->scrollbar_vertical_instance = NULL;
327 t->scrollbar_horizontal_instance = NULL;
333 /* Synchronize the mirror structure with a given window structure.
334 This is normally called from update_frame_window_mirror with a
335 starting window of f->root_window. */
336 static struct window_mirror *
337 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
343 free_window_mirror (mir);
350 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
352 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
353 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
354 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
357 * If the redisplay structs are not empty and the mirror has
358 * children, then this mirror structure was formerly being used for
359 * display but is no longer. Reset its current display structs so
360 * that redisplay doesn't accidentally think they are accurate if it
361 * is later used for display purposes once again. Also, mark the
362 * scrollbar instance as not active.
364 if (mir->vchild || mir->hchild)
366 /* The redisplay structures are big. Leaving them around in
367 non-leaf windows can add up to a lot of wasted space. So
369 free_display_structs (mir);
370 mir->current_display_lines = Dynarr_new (display_line);
371 mir->desired_display_lines = Dynarr_new (display_line);
373 #ifdef HAVE_SCROLLBARS
374 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
382 /* Given a window mirror, determine which real window it contains the
383 redisplay structures for. */
385 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
386 struct window_mirror *mir)
390 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
394 if (!NILP (XWINDOW (win)->vchild))
396 retval = real_window_internal (XWINDOW (win)->vchild, rmir->vchild,
401 if (!NILP (XWINDOW (win)->hchild))
403 retval = real_window_internal (XWINDOW (win)->hchild, rmir->hchild,
413 /* Given a real window, find the mirror structure which contains its
414 redisplay structures. */
415 static struct window_mirror *
416 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
419 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
421 if (w == XWINDOW (win))
424 if (!NILP (XWINDOW (win)->vchild))
426 struct window_mirror *retval =
427 find_window_mirror_internal (XWINDOW (win)->vchild,
429 if (retval) return retval;
432 if (!NILP (XWINDOW (win)->hchild))
434 struct window_mirror *retval =
435 find_window_mirror_internal (XWINDOW (win)->hchild,
437 if (retval) return retval;
444 /* Update the mirror structure for the given frame. */
446 update_frame_window_mirror (struct frame *f)
448 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
452 /* Free a given mirror structure along with all of its children as
453 well as their associated display structures. */
455 free_window_mirror (struct window_mirror *mir)
459 struct window_mirror *prev = mir;
460 if (mir->hchild) free_window_mirror (mir->hchild);
461 if (mir->vchild) free_window_mirror (mir->vchild);
462 #ifdef HAVE_SCROLLBARS
463 release_window_mirror_scrollbars (mir);
465 free_display_structs (mir);
471 /* Given a mirror structure, return the window it mirrors. Calls
472 real_window_internal to do most of the work. */
474 real_window (struct window_mirror *mir, int no_abort)
476 Lisp_Object retval = real_window_internal (mir->frame->root_window,
477 mir->frame->root_mirror, mir);
478 if (NILP (retval) && !no_abort)
484 /* Given a real window, return its mirror structure. Calls
485 find_window_mirror_internal to do all of the work. */
486 struct window_mirror *
487 find_window_mirror (struct window *w)
489 struct frame *f = XFRAME (w->frame);
491 update_frame_window_mirror (f);
492 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
495 /*****************************************************************************
496 find_window_by_pixel_pos
498 Given a pixel position relative to a frame, find the window at that
500 ****************************************************************************/
502 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
507 for (; !NILP (win); win = XWINDOW (win)->next)
511 if (!NILP (XWINDOW (win)->vchild))
513 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
516 if (!NILP (XWINDOW (win)->hchild))
518 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
522 if (pix_x >= WINDOW_LEFT (w)
523 && pix_x <= WINDOW_RIGHT (w)
524 && pix_y >= WINDOW_TOP (w)
525 && pix_y <= WINDOW_BOTTOM (w))
531 /* Return a pointer to the display structures for the given window. */
532 display_line_dynarr *
533 window_display_lines (struct window *w, int which)
535 struct window_mirror *t;
537 if (XFRAME (w->frame)->mirror_dirty)
538 update_frame_window_mirror (XFRAME (w->frame));
539 t = find_window_mirror (w);
543 if (which == CURRENT_DISP)
544 return t->current_display_lines;
545 else if (which == DESIRED_DISP)
546 return t->desired_display_lines;
547 else if (which == CMOTION_DISP)
548 /* The CMOTION_DISP display lines are global. */
549 return cmotion_display_lines;
553 return 0; /* shut up compiler */
557 window_display_buffer (struct window *w)
559 struct window_mirror *t;
561 if (XFRAME (w->frame)->mirror_dirty)
562 update_frame_window_mirror (XFRAME (w->frame));
563 t = find_window_mirror (w);
571 set_window_display_buffer (struct window *w, struct buffer *b)
573 struct window_mirror *t;
575 if (XFRAME (w->frame)->mirror_dirty)
576 update_frame_window_mirror (XFRAME (w->frame));
577 t = find_window_mirror (w);
585 /* Determining a window's position based solely on its pixel
586 positioning doesn't work. Instead, we do it the intelligent way,
587 by checking its positioning in the window hierarchy. */
589 window_is_leftmost (struct window *w)
591 Lisp_Object parent, current_ancestor, window;
593 XSETWINDOW (window, w);
595 parent = XWINDOW (window)->parent;
596 current_ancestor = window;
598 while (!NILP (parent))
600 if (!NILP (XWINDOW (parent)->hchild) &&
601 !EQ (XWINDOW (parent)->hchild, current_ancestor))
604 current_ancestor = parent;
605 parent = XWINDOW (parent)->parent;
612 window_is_rightmost (struct window *w)
614 Lisp_Object parent, current_ancestor, window;
616 XSETWINDOW (window, w);
618 parent = XWINDOW (window)->parent;
619 current_ancestor = window;
621 while (!NILP (parent))
623 if (!NILP (XWINDOW (parent)->hchild)
624 && !NILP (XWINDOW (current_ancestor)->next))
627 current_ancestor = parent;
628 parent = XWINDOW (parent)->parent;
635 window_full_width_p (struct window *w)
637 return window_is_leftmost (w) && window_is_rightmost (w);
641 window_is_highest (struct window *w)
643 Lisp_Object parent, current_ancestor, window;
645 XSETWINDOW (window, w);
647 parent = XWINDOW (window)->parent;
648 current_ancestor = window;
650 while (!NILP (parent))
652 if (!NILP (XWINDOW (parent)->vchild) &&
653 !EQ (XWINDOW (parent)->vchild, current_ancestor))
656 current_ancestor = parent;
657 parent = XWINDOW (parent)->parent;
660 /* This is really to catch the minibuffer but we make it generic in
661 case we ever change things around to let the minibuffer be on top. */
662 if (NILP (XWINDOW (current_ancestor)->prev))
669 window_is_lowest (struct window *w)
671 Lisp_Object parent, current_ancestor, window;
673 XSETWINDOW (window, w);
675 parent = XWINDOW (window)->parent;
676 current_ancestor = window;
678 while (!NILP (parent))
680 if (!NILP (XWINDOW (parent)->vchild)
681 && !NILP (XWINDOW (current_ancestor)->next))
684 current_ancestor = parent;
685 parent = XWINDOW (parent)->parent;
691 #if 0 /* not currently used */
694 window_full_height_p (struct window *w)
696 return window_is_highest (w) && window_is_lowest (w);
702 window_truncation_on (struct window *w)
704 /* Horizontally scrolled windows are truncated. */
708 /* If truncate_partial_width_windows is true and the window is not
709 the full width of the frame it is truncated. */
710 if (truncate_partial_width_windows
711 && !(window_is_leftmost (w) && window_is_rightmost (w)))
714 /* If the window's buffer's value of truncate_lines is non-nil, then
715 the window is truncated. */
716 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
723 have_undivided_common_edge (struct window *w_right, void *closure)
725 struct window *w_left = (struct window *) closure;
726 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
727 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
728 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
729 #ifdef HAVE_SCROLLBARS
730 && (NILP (w_right->scrollbar_on_left_p)
731 || NILP (w_right->vertical_scrollbar_visible_p)
732 || ZEROP (w_right->scrollbar_width))
738 window_needs_vertical_divider_1 (struct window *w)
740 /* Never if we're on the right */
741 if (window_is_rightmost (w))
744 /* Always if draggable */
745 if (!NILP (w->vertical_divider_always_visible_p))
748 #ifdef HAVE_SCROLLBARS
749 /* Our right scrollabr is enough to separate us at the right */
750 if (NILP (w->scrollbar_on_left_p)
751 && !NILP (w->vertical_scrollbar_visible_p)
752 && !ZEROP (w->scrollbar_width))
756 /* Ok. to determine whether we need a divider on the left, we must
757 check that our right neighbor windows have scrollbars on their
758 left sides. We must check all such windows which have common
759 left edge with our window's right edge. */
760 return map_windows (XFRAME (WINDOW_FRAME (w)),
761 have_undivided_common_edge, (void*)w);
765 window_needs_vertical_divider (struct window *w)
767 if (!w->need_vertical_divider_valid_p)
769 w->need_vertical_divider_p =
770 window_needs_vertical_divider_1 (w);
771 w->need_vertical_divider_valid_p = 1;
773 return w->need_vertical_divider_p;
776 /* Called from invalidate_vertical_divider_cache_in_frame */
778 invalidate_vertical_divider_cache_in_window (struct window *w,
781 w->need_vertical_divider_valid_p = 0;
785 /* Calculate width of vertical divider, including its shadows
786 and spacing. The returned value is effectively the distance
787 between adjacent window edges. This function does not check
788 whether a windows needs vertival divider, so the returned
789 value is a "theoretical" one */
791 window_divider_width (struct window *w)
793 /* the shadow thickness can be negative. This means that the divider
794 will have a depressed look */
796 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
798 XINT (w->vertical_divider_line_width)
799 + 2 * XINT (w->vertical_divider_spacing)
800 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
802 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
806 window_scrollbar_width (struct window *w)
808 #ifdef HAVE_SCROLLBARS
809 if (!WINDOW_WIN_P (w)
812 || NILP (w->vertical_scrollbar_visible_p))
813 /* #### when does NILP (w->buffer) happen? */
816 return XINT (w->scrollbar_width);
819 #endif /* HAVE_SCROLLBARS */
822 /* Horizontal scrollbars are only active on windows with truncation
825 window_scrollbar_height (struct window *w)
827 #ifdef HAVE_SCROLLBARS
828 if (!WINDOW_WIN_P (w)
831 || NILP (w->horizontal_scrollbar_visible_p)
832 || !window_truncation_on (w))
835 return XINT (w->scrollbar_height);
838 #endif /* HAVE_SCROLLBARS */
842 window_modeline_height (struct window *w)
844 struct frame *f = XFRAME (w->frame);
847 if (MINI_WINDOW_P (w) || NILP (w->buffer))
851 else if (!WINDOW_HAS_MODELINE_P (w))
853 if (window_scrollbar_height (w))
857 modeline_height = FRAMEMETH (f, divider_height, ());
859 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
860 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
869 display_line_dynarr *dla;
871 /* We don't force a regeneration of the modeline here.
872 Instead it is now a precondition that any function calling
873 this should make sure that one of these structures is
874 up-to-date. In practice this only affects two internal
875 redisplay functions, regenerate_window and
876 regenerate_window_point_center. */
877 /* We check DESIRED_DISP because if it is valid it is more
878 up-to-date than CURRENT_DISP. For calls to this outside
879 of redisplay it doesn't matter which structure we check
880 since there is a redisplay condition that these
881 structures be identical outside of redisplay. */
882 dla = window_display_lines (w, DESIRED_DISP);
883 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
884 modeline_height = (Dynarr_atp (dla, 0)->ascent +
885 Dynarr_atp (dla, 0)->descent);
888 dla = window_display_lines (w, CURRENT_DISP);
889 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
890 modeline_height = (Dynarr_atp (dla, 0)->ascent +
891 Dynarr_atp (dla, 0)->descent);
893 /* This should be an abort except I'm not yet 100%
894 confident that it won't ever get hit (though I
895 haven't been able to trigger it). It is extremely
896 unlikely to cause any noticable problem and even if
897 it does it will be a minor display glitch. */
898 /* #### Bullshit alert. It does get hit and it causes
899 noticeable glitches. real_current_modeline_height
900 is a kludge to fix this for 19.14. */
901 modeline_height = real_current_modeline_height (w);
904 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
905 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
909 return modeline_height;
912 /*****************************************************************************
913 margin_width_internal
915 For a given window, return the width in pixels of the specified margin.
916 ****************************************************************************/
918 margin_width_internal (struct window *w, int left_margin)
921 int window_cwidth = window_char_width (w, 1);
926 /* We might be getting called on a non-leaf. */
927 if (NILP (w->buffer))
930 /* The minibuffer never has margins. */
931 if (MINI_WINDOW_P (w))
934 XSETWINDOW (window, w);
935 b = XBUFFER (w->buffer);
936 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
937 XINT (w->right_margin_width));
939 default_face_height_and_width (window, 0, &font_width);
941 /* The left margin takes precedence over the right margin so we
942 subtract its width from the space available for the right
945 window_cwidth -= XINT (w->left_margin_width);
947 /* The margin cannot be wider than the window is. We allow the
948 value to be bigger since it is possible for the user to enlarge
949 the window such that the left margin value would no longer be too
950 big, but we won't return a value that is larger. */
951 if (margin_cwidth > window_cwidth)
952 margin_cwidth = window_cwidth;
954 /* At the user level the margin is always specified in characters.
955 Internally however it is manipulated in terms of pixels. */
956 return margin_cwidth * font_width;
960 window_left_margin_width (struct window *w)
962 return margin_width_internal (w, 1);
966 window_right_margin_width (struct window *w)
968 return margin_width_internal (w, 0);
972 window_top_toolbar_height (struct window *w)
974 /* #### implement this shit. */
978 /* #### Currently used in scrollbar.c. Does it actually need to be? */
980 window_bottom_toolbar_height (struct window *w)
986 window_left_toolbar_width (struct window *w)
992 window_right_toolbar_width (struct window *w)
997 /*****************************************************************************
1000 The gutters of a window are those areas in the boundary defined by
1001 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1002 do not contain text. Items which may be in the gutters include
1003 scrollbars, toolbars and modelines. The margin areas are not
1004 included. This is an exception made because redisplay special cases
1005 the handling of those areas in many places in such a way that
1006 including them in the gutter area would make life difficult.
1008 The size functions refer to height for the bottom and top gutters and
1009 width for the left and right gutters. The starting position
1010 functions refer to the Y coord for bottom and top gutters and the X
1011 coord for left and right gutters. All starting positions are
1012 relative to the frame, not the window.
1013 ****************************************************************************/
1016 window_top_gutter_height (struct window *w)
1018 int toolbar_height = window_top_toolbar_height (w);
1020 if (!NILP (w->hchild) || !NILP (w->vchild))
1023 #ifdef HAVE_SCROLLBARS
1024 if (!NILP (w->scrollbar_on_top_p))
1025 return window_scrollbar_height (w) + toolbar_height;
1028 return toolbar_height;
1032 window_bottom_gutter_height (struct window *w)
1036 if (!NILP (w->hchild) || !NILP (w->vchild))
1040 window_modeline_height (w) + window_bottom_toolbar_height (w);
1042 #ifdef HAVE_SCROLLBARS
1043 if (NILP (w->scrollbar_on_top_p))
1044 return window_scrollbar_height (w) + other_height;
1047 return other_height;
1051 window_left_gutter_width (struct window *w, int modeline)
1053 int gutter = window_left_toolbar_width (w);
1055 if (!NILP (w->hchild) || !NILP (w->vchild))
1059 #ifdef HAVE_SCROLLBARS
1060 if (!modeline && !NILP (w->scrollbar_on_left_p))
1061 gutter += window_scrollbar_width (w);
1068 window_right_gutter_width (struct window *w, int modeline)
1070 int gutter = window_left_toolbar_width (w);
1072 if (!NILP (w->hchild) || !NILP (w->vchild))
1075 #ifdef HAVE_SCROLLBARS
1076 if (!modeline && NILP (w->scrollbar_on_left_p))
1077 gutter += window_scrollbar_width (w);
1080 if (window_needs_vertical_divider (w))
1081 gutter += window_divider_width (w);
1087 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1088 Return t if OBJ is a window.
1092 return WINDOWP (obj) ? Qt : Qnil;
1095 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1096 Return t if OBJ is a window which is currently visible.
1100 return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
1103 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1104 Return the window that the cursor now appears in and commands apply to.
1105 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1106 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1107 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1108 is a console, the selected frame on that console's selected device will
1109 be used. Otherwise, the selected frame is used.
1113 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1114 return Qnil; /* happens at startup */
1117 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1118 return FRAME_SELECTED_WINDOW (f);
1122 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1123 Return the window used now for minibuffers.
1124 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1125 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1126 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1127 is a console, the selected frame on that console's selected device will
1128 be used. Otherwise, the selected frame is used.
1132 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1135 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 1, 1, 0, /*
1136 Return non-nil if WINDOW is a minibuffer window.
1140 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1143 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1144 Return the first horizontal child of WINDOW, or nil.
1148 return decode_window (window)->hchild;
1151 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1152 Return the first vertical child of WINDOW, or nil.
1156 return decode_window (window)->vchild;
1159 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1160 Return the next window on the same level as WINDOW, or nil.
1164 return decode_window (window)->next;
1167 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1168 Return the previous window on the same level as WINDOW, or nil.
1172 return decode_window (window)->prev;
1175 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1176 Return the parent of WINDOW, or nil.
1180 return decode_window (window)->parent;
1183 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1184 Return non-nil if WINDOW is along the bottom of its frame.
1188 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1191 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1192 Return non-nil if WINDOW is along the top of its frame.
1196 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1199 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1200 Return non-nil if WINDOW is along the left edge of its frame.
1204 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1207 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1208 Return non-nil if WINDOW is along the right edge of its frame.
1212 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1215 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1216 Return t if position POS is currently on the frame in WINDOW.
1217 Returns nil if that position is scrolled vertically out of view.
1218 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1222 struct window *w = decode_window (window);
1223 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1225 struct buffer *buf = XBUFFER (w->buffer);
1228 posint = BUF_PT (buf);
1231 CHECK_INT_COERCE_MARKER (pos);
1232 posint = XINT (pos);
1235 if (posint < top || posint > BUF_ZV (buf))
1238 /* w->start can be out of range. If it is, do something reasonable. */
1239 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1242 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1247 decode_window (Lisp_Object window)
1250 return XWINDOW (Fselected_window (Qnil));
1252 CHECK_LIVE_WINDOW (window);
1253 return XWINDOW (window);
1256 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1257 Return the buffer that WINDOW is displaying.
1261 return decode_window (window)->buffer;
1264 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1265 Return the frame that window WINDOW is on.
1269 return decode_window (window)->frame;
1272 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1273 Return the number of default lines in WINDOW.
1274 This actually works by dividing the window's pixel height (including
1275 the modeline and horizontal scrollbar, if any) by the height of the
1276 default font; therefore, the number of displayed lines will probably
1278 Use `window-height' to get consistent results in geometry calculations.
1279 Use `window-displayed-height' to get the actual number of lines
1280 currently displayed in a window.
1284 return make_int (window_char_height (decode_window (window), 1));
1287 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1288 Return the number of lines currently displayed in WINDOW.
1289 This counts the actual number of lines displayed in WINDOW
1290 \(as opposed to `window-height'). The modeline and horizontal
1291 scrollbar do not count as lines. If there is some blank space
1292 between the end of the buffer and the end of the window, this
1293 function pretends that there are lines of text in the default
1298 return make_int (window_displayed_height (decode_window (window)));
1301 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1302 Return the height of WINDOW in pixels. Defaults to current window.
1303 This includes the window's modeline and horizontal scrollbar (if any).
1307 return make_int (decode_window (window)->pixel_height);
1310 DEFUN ("window-text-area-pixel-height",
1311 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1312 Return the height in pixels of the text-displaying portion of WINDOW.
1313 Unlike `window-pixel-height', the space occupied by the modeline and
1314 horizontal scrollbar, if any, is not counted.
1318 struct window *w = decode_window (window);
1320 return make_int (WINDOW_TEXT_HEIGHT (w));
1323 DEFUN ("window-displayed-text-pixel-height",
1324 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1325 Return the height in pixels of the text displayed in WINDOW.
1326 Unlike `window-text-area-pixel-height', any blank space below the
1327 end of the buffer is not included. If optional argument NOCLIPPED
1328 is non-nil, do not include space occupied by clipped lines.
1330 (window, noclipped))
1333 Bufpos start, eobuf;
1335 int hlimit, height, prev_height = -1;
1339 line_start_cache_dynarr *cache;
1342 window = Fselected_window (Qnil);
1344 CHECK_WINDOW (window);
1345 w = XWINDOW (window);
1347 start = marker_position (w->start[CURRENT_DISP]);
1348 hlimit = WINDOW_TEXT_HEIGHT (w);
1349 eobuf = BUF_ZV (XBUFFER (w->buffer));
1351 default_face_height_and_width (window, &defheight, NULL);
1353 /* guess lines needed in line start cache + a few extra */
1354 needed = (hlimit + defheight-1) / defheight + 3;
1357 elt = point_in_line_start_cache (w, start, needed);
1358 assert (elt >= 0); /* in the cache */
1360 cache = w->line_start_cache;
1361 nelt = Dynarr_length (cache);
1364 for (i = elt; i < nelt; i++) {
1365 line = Dynarr_atp (cache, i)->height;
1367 if (height + line > hlimit)
1368 return make_int (!NILP (noclipped) ? height : hlimit);
1372 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1373 return make_int (height);
1376 /* get here => need more cache lines. try again. */
1377 assert(height > prev_height); /* progress? */
1378 prev_height = height;
1380 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1383 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1386 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1387 Return the number of display columns in WINDOW.
1388 This is the width that is usable columns available for text in WINDOW.
1392 return make_int (window_char_width (decode_window (window), 0));
1395 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1396 Return the width of WINDOW in pixels. Defaults to current window.
1400 return make_int (decode_window (window)->pixel_width);
1403 DEFUN ("window-text-area-pixel-width",
1404 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1405 Return the width in pixels of the text-displaying portion of WINDOW.
1406 Unlike `window-pixel-width', the space occupied by the vertical
1407 scrollbar or divider, if any, is not counted.
1411 struct window *w = decode_window (window);
1413 return make_int (WINDOW_TEXT_WIDTH (w));
1416 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1417 Return the number of columns by which WINDOW is scrolled from left margin.
1421 return make_int (decode_window (window)->hscroll);
1424 #ifdef MODELINE_IS_SCROLLABLE
1425 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1426 Return the number of columns by which WINDOW's modeline is scrolled from
1427 left margin. If the window has no modeline, return nil.
1431 struct window *w = decode_window (window);
1433 return (WINDOW_HAS_MODELINE_P (w)) ? make_int (w->modeline_hscroll) : Qnil;
1436 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1437 Set number of columns WINDOW's modeline is scrolled from left margin to NCOL.
1438 NCOL should be zero or positive. If NCOL is negative, it will be forced to 0.
1439 If the window has no modeline, do nothing and return nil.
1443 struct window *w = decode_window (window);
1445 if (WINDOW_HAS_MODELINE_P (w))
1449 ncols = XINT (ncol);
1450 if (ncols < 0) ncols = 0;
1451 if (w->modeline_hscroll != ncols)
1452 MARK_MODELINE_CHANGED;
1453 w->modeline_hscroll = ncols;
1458 #endif /* MODELINE_IS_SCROLLABLE */
1460 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1461 Set number of columns WINDOW is scrolled from left margin to NCOL.
1462 NCOL should be zero or positive.
1470 ncols = XINT (ncol);
1471 if (ncols < 0) ncols = 0;
1472 w = decode_window (window);
1473 if (w->hscroll != ncols)
1474 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1479 #if 0 /* bogus FSF crock */
1481 xxDEFUN ("window-redisplay-end-trigger",
1482 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1483 Return WINDOW's redisplay end trigger value.
1484 See `set-window-redisplay-end-trigger' for more information.
1488 return decode_window (window)->redisplay_end_trigger;
1491 xxDEFUN ("set-window-redisplay-end-trigger",
1492 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1493 Set WINDOW's redisplay end trigger value to VALUE.
1494 VALUE should be a buffer position (typically a marker) or nil.
1495 If it is a buffer position, then if redisplay in WINDOW reaches a position
1496 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1497 with two arguments: WINDOW, and the end trigger value.
1498 Afterwards the end-trigger value is reset to nil.
1502 return (decode_window (window)->redisplay_end_trigger = value);
1507 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1508 Return a list of the pixel edge coordinates of WINDOW.
1509 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1510 The frame toolbars and menubars are considered to be outside of this area.
1514 struct window *w = decode_window (window);
1515 struct frame *f = XFRAME (w->frame);
1517 int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
1518 int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
1520 return list4 (make_int (left),
1522 make_int (left + w->pixel_width),
1523 make_int (top + w->pixel_height));
1526 DEFUN ("window-text-area-pixel-edges",
1527 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1528 Return a list of the pixel edge coordinates of the text area of WINDOW.
1529 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1530 top left corner of the window.
1534 struct window *w = decode_window (window);
1536 int left = window_left_gutter_width (w, /* modeline = */ 0);
1537 int top = window_top_gutter_height (w);
1538 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1539 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1541 return list4 (make_int (left),
1547 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1548 Return current value of point in WINDOW.
1549 For a nonselected window, this is the value point would have
1550 if that window were selected.
1552 Note that, when WINDOW is the selected window and its buffer
1553 is also currently selected, the value returned is the same as (point).
1554 It would be more strictly correct to return the `top-level' value
1555 of point, outside of any save-excursion forms.
1556 But that is hard to define.
1560 struct window *w = decode_window (window);
1562 /* The special check for current buffer is necessary for this
1563 function to work as defined when called within an excursion. */
1564 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1565 && current_buffer == XBUFFER (w->buffer))
1566 return Fpoint (Qnil);
1567 return Fmarker_position (w->pointm[CURRENT_DISP]);
1570 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1571 Return position at which display currently starts in WINDOW.
1572 This is updated by redisplay or by calling `set-window-start'.
1576 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1579 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1580 Return position at which display currently ends in WINDOW.
1581 This is updated by redisplay, when it runs to completion.
1582 Simply changing the buffer text or setting `window-start'
1583 does not update this value.
1584 If GUARANTEE is non-nil, then the return value is guaranteed to be
1585 the value of window-end at the end of the next full redisplay assuming
1586 nothing else changes in the meantime. This function is potentially much
1587 slower with this flag set.
1589 (window, guarantee))
1591 struct window *w = decode_window (window);
1593 if (NILP (guarantee))
1598 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1602 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1603 return make_int (end_of_last_line (w, startp));
1607 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1608 Make point value in WINDOW be at position POS in WINDOW's buffer.
1612 struct window *w = decode_window (window);
1614 CHECK_INT_COERCE_MARKER (pos);
1615 if (w == XWINDOW (Fselected_window (Qnil)))
1616 Fgoto_char (pos, Qnil);
1618 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1624 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1625 Make display in WINDOW start at position POS in WINDOW's buffer.
1626 Optional third arg NOFORCE non-nil inhibits next redisplay
1627 from overriding motion of point in order to display at this exact start.
1629 (window, pos, noforce))
1631 struct window *w = decode_window (window);
1633 CHECK_INT_COERCE_MARKER (pos);
1634 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1635 /* this is not right, but much easier than doing what is right. */
1636 /* w->start_at_line_beg = 0; */
1637 /* WTF is the above supposed to mean? GE */
1638 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1639 marker_position (w->start[CURRENT_DISP]));
1642 w->redo_modeline = 1;
1643 SET_LAST_MODIFIED (w, 0);
1644 SET_LAST_FACECHANGE (w);
1646 MARK_WINDOWS_CHANGED (w);
1651 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1652 Return WINDOW's dedicated object, usually t or nil.
1653 See also `set-window-dedicated-p'.
1657 return decode_window (window)->dedicated;
1660 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1661 Control whether WINDOW is dedicated to the buffer it displays.
1662 If it is dedicated, Emacs will not automatically change
1663 which buffer appears in it.
1664 The second argument is the new value for the dedication flag;
1669 struct window *w = decode_window (window);
1671 w->dedicated = NILP (arg) ? Qnil : Qt;
1673 return w->dedicated;
1676 /* FSFmacs has window-display-table here. We have display table as a
1680 /* Record info on buffer window w is displaying
1681 when it is about to cease to display that buffer. */
1683 unshow_buffer (struct window *w)
1685 Lisp_Object buf = w->buffer;
1687 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1690 /* FSF disables this check, so I'll do it too. I hope it won't
1691 break things. --ben */
1693 if (w == XWINDOW (Fselected_window (Qnil))
1694 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1695 /* Do this except when the selected window's buffer
1696 is being removed from some other window. */
1698 /* last_window_start records the start position that this buffer
1699 had in the last window to be disconnected from it.
1700 Now that this statement is unconditional,
1701 it is possible for the buffer to be displayed in the
1702 selected window, while last_window_start reflects another
1703 window which was recently showing the same buffer.
1704 Some people might say that might be a good thing. Let's see. */
1705 XBUFFER (buf)->last_window_start =
1706 marker_position (w->start[CURRENT_DISP]);
1708 /* Point in the selected window's buffer
1709 is actually stored in that buffer, and the window's pointm isn't used.
1710 So don't clobber point in that buffer. */
1711 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1713 struct buffer *b= XBUFFER (buf);
1714 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1715 marker_position (w->pointm[CURRENT_DISP]),
1720 /* Put REPLACEMENT into the window structure in place of OLD. */
1722 replace_window (Lisp_Object old, Lisp_Object replacement)
1725 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1727 /* If OLD is its frame's root_window, then replacement is the new
1728 root_window for that frame. */
1730 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1731 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1733 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1734 WINDOW_TOP (p) = WINDOW_TOP (o);
1735 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1736 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1738 p->next = tem = o->next;
1740 XWINDOW (tem)->prev = replacement;
1742 p->prev = tem = o->prev;
1744 XWINDOW (tem)->next = replacement;
1746 p->parent = tem = o->parent;
1749 if (EQ (XWINDOW (tem)->vchild, old))
1750 XWINDOW (tem)->vchild = replacement;
1751 if (EQ (XWINDOW (tem)->hchild, old))
1752 XWINDOW (tem)->hchild = replacement;
1755 /* #### Here, if replacement is a vertical combination
1756 and so is its new parent, we should make replacement's
1757 children be children of that parent instead. */
1760 /* we're deleting W; set the structure of W to indicate this. */
1763 mark_window_as_deleted (struct window *w)
1766 (while t (split-window) (delete-window))
1767 we end up with a tree of deleted windows which are all connected
1768 through the `next' slot. This might not seem so bad, as they're
1769 deleted, and will presumably be GCed - but if even *one* of those
1770 windows is still being pointed to, by the user, or by a window
1771 configuration, then *all* of those windows stick around.
1773 Since the window-configuration code doesn't need any of the
1774 pointers to other windows (they are all recreated from the
1775 window-config data), we set them all to nil so that we
1776 are able to collect more actual garbage.
1786 /* Free the extra data structures attached to windows immediately so
1787 they don't sit around consuming excess space. They will be
1788 reinitialized by the window-configuration code as necessary. */
1789 finalize_window ((void *) w, 0);
1792 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1793 Remove WINDOW from the display. Default is selected window.
1794 If window is the only one on the frame, the frame is destroyed.
1795 Normally, you cannot delete the last non-minibuffer-only frame (you must
1796 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1797 second argument FORCE is non-nil, you can delete the last frame. (This
1798 will automatically call `save-buffers-kill-emacs'.)
1802 /* This function can GC if this is the only window in the frame */
1810 /* Note: this function is called by other C code on non-leaf
1813 /* Do the equivalent of decode_window() but don't error out on
1814 deleted window; it's OK to delete an already-deleted window. */
1816 window = Fselected_window (Qnil);
1818 CHECK_WINDOW (window);
1819 w = XWINDOW (window);
1821 /* It's okay to delete an already-deleted window. */
1822 if (! WINDOW_LIVE_P (w))
1825 frame = WINDOW_FRAME (w);
1827 d = XDEVICE (FRAME_DEVICE (f));
1829 if (TOP_LEVEL_WINDOW_P (w))
1831 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1832 /* this frame isn't fully initialized yet; don't blow up. */
1835 if (MINI_WINDOW_P (XWINDOW (window)))
1836 error ("Attempt to delete the minibuffer window");
1838 /* It has been suggested that it's a good thing for C-x 0 to have this
1839 behavior, but not such a good idea for #'delete-window to have it.
1840 Maybe C-x 0 should be bound to something else, or maybe frame
1841 deletion should only happen when this is called interactively.
1843 delete_frame_internal (f, !NILP (force), 0, 0);
1847 /* At this point, we know the window has a parent. */
1849 par = XWINDOW (parent);
1851 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1853 /* Are we trying to delete any frame's selected window?
1854 Note that we could be dealing with a non-leaf window
1855 where the selected window is one of our children.
1856 So, we check by scanning all the ancestors of the
1857 frame's selected window and comparing each one with
1860 Lisp_Object pwindow;
1862 pwindow = FRAME_SELECTED_WINDOW (f);
1864 while (!NILP (pwindow))
1866 if (EQ (window, pwindow))
1868 pwindow = XWINDOW (pwindow)->parent;
1871 if (EQ (window, pwindow))
1873 /* OK, we found it. */
1874 Lisp_Object alternative;
1875 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1877 /* If we're about to delete the selected window on the
1878 selected frame, then we should use Fselect_window to select
1879 the new window. On the other hand, if we're about to
1880 delete the selected window on any other frame, we shouldn't do
1881 anything but set the frame's selected_window slot. */
1882 if (EQ (frame, Fselected_frame (Qnil)))
1883 Fselect_window (alternative, Qnil);
1885 set_frame_selected_window (f, alternative);
1889 /* w->buffer is nil in a non-leaf window; in this case,
1890 get rid of the markers we maintain that point into that buffer. */
1891 if (!NILP (w->buffer))
1894 unchain_marker (w->pointm[CURRENT_DISP]);
1895 unchain_marker (w->pointm[DESIRED_DISP]);
1896 unchain_marker (w->pointm[CMOTION_DISP]);
1897 unchain_marker (w->start[CURRENT_DISP]);
1898 unchain_marker (w->start[DESIRED_DISP]);
1899 unchain_marker (w->start[CMOTION_DISP]);
1900 unchain_marker (w->sb_point);
1901 /* This breaks set-window-configuration if windows in the saved
1902 configuration get deleted and multiple frames are in use. */
1903 /* w->buffer = Qnil; */
1906 /* close up the hole in the sibling list */
1907 if (!NILP (w->next))
1908 XWINDOW (w->next)->prev = w->prev;
1909 if (!NILP (w->prev))
1910 XWINDOW (w->prev)->next = w->next;
1911 if (EQ (window, par->hchild))
1912 par->hchild = w->next;
1913 if (EQ (window, par->vchild))
1914 par->vchild = w->next;
1916 /* Find one of our siblings to give our space to. */
1918 Lisp_Object sib = w->prev;
1921 /* If w gives its space to its next sibling, that sibling needs
1922 to have its top/left side pulled back to where w's is.
1923 set_window_{height,width} will re-position the sibling's
1926 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1927 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1930 /* Stretch that sibling. */
1931 if (!NILP (par->vchild))
1932 set_window_pixheight
1933 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1934 if (!NILP (par->hchild))
1936 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1939 /* If parent now has only one child,
1940 put the child into the parent's place. */
1942 Lisp_Object parchild = par->hchild;
1943 if (NILP (parchild))
1944 parchild = par->vchild;
1945 if (NILP (XWINDOW (parchild)->next))
1947 replace_window (parent, parchild);
1948 mark_window_as_deleted (XWINDOW (parent));
1952 /* Since we may be deleting combination windows, we must make sure that
1953 not only W but all its children have been marked as deleted. */
1954 if (!NILP (w->hchild))
1955 delete_all_subwindows (XWINDOW (w->hchild));
1956 else if (!NILP (w->vchild))
1957 delete_all_subwindows (XWINDOW (w->vchild));
1959 mark_window_as_deleted (w);
1961 f->mirror_dirty = 1;
1966 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1967 Return next window after WINDOW in canonical ordering of windows.
1968 If omitted, WINDOW defaults to the selected window.
1970 Optional second arg MINIBUF t means count the minibuffer window even
1971 if not active. MINIBUF nil or omitted means count the minibuffer iff
1972 it is active. MINIBUF neither t nor nil means not to count the
1973 minibuffer even if it is active.
1975 Several frames may share a single minibuffer; if the minibuffer
1976 counts, all windows on all frames that share that minibuffer count
1977 too. Therefore, `next-window' can be used to iterate through the
1978 set of windows even when the minibuffer is on another frame. If the
1979 minibuffer does not count, only windows from WINDOW's frame count.
1981 Optional third arg ALL-FRAMES t means include windows on all frames.
1982 ALL-FRAMES nil or omitted means cycle within the frames as specified
1983 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1984 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1985 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1986 Anything else means restrict to WINDOW's frame.
1988 Optional fourth argument CONSOLE controls which consoles or devices the
1989 returned window may be on. If CONSOLE is a console, return windows only
1990 on that console. If CONSOLE is a device, return windows only on that
1991 device. If CONSOLE is a console type, return windows only on consoles
1992 of that type. If CONSOLE is 'window-system, return any windows on any
1993 window-system consoles. If CONSOLE is nil or omitted, return windows only
1994 on WINDOW's console. Otherwise, all windows are considered.
1996 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
1997 can use `next-window' to iterate through the entire cycle of acceptable
1998 windows, eventually ending up back at the window you started with.
1999 `previous-window' traverses the same cycle, in the reverse order.
2001 (window, minibuf, all_frames, console))
2004 Lisp_Object start_window;
2007 window = Fselected_window (Qnil);
2009 CHECK_LIVE_WINDOW (window);
2011 start_window = window;
2013 /* minibuf == nil may or may not include minibuffers.
2014 Decide if it does. */
2016 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2017 else if (! EQ (minibuf, Qt))
2019 /* Now minibuf can be t => count all minibuffer windows,
2020 lambda => count none of them,
2021 or a specific minibuffer window (the active one) to count. */
2023 /* all_frames == nil doesn't specify which frames to include. */
2024 if (NILP (all_frames))
2025 all_frames = (! EQ (minibuf, Qlambda)
2026 ? (FRAME_MINIBUF_WINDOW
2029 (XWINDOW (window)))))
2031 else if (EQ (all_frames, Qvisible))
2033 else if (ZEROP (all_frames))
2035 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2036 /* If all_frames is a frame and window arg isn't on that frame, just
2037 return the first window on the frame. */
2038 return frame_first_window (XFRAME (all_frames));
2039 else if (! EQ (all_frames, Qt))
2041 /* Now all_frames is t meaning search all frames,
2042 nil meaning search just current frame,
2043 visible meaning search just visible frames,
2044 0 meaning search visible and iconified frames,
2045 or a window, meaning search the frame that window belongs to. */
2047 /* Do this loop at least once, to get the next window, and perhaps
2048 again, if we hit the minibuffer and that is not acceptable. */
2051 /* Find a window that actually has a next one. This loop
2052 climbs up the tree. */
2053 while (tem = XWINDOW (window)->next, NILP (tem))
2054 if (tem = XWINDOW (window)->parent, !NILP (tem))
2056 else /* window must be minibuffer window now */
2058 /* We've reached the end of this frame.
2059 Which other frames are acceptable? */
2060 tem = WINDOW_FRAME (XWINDOW (window));
2062 if (! NILP (all_frames))
2067 tem = next_frame (tem, all_frames, console);
2068 /* In the case where the minibuffer is active,
2069 and we include its frame as well as the selected one,
2070 next_frame may get stuck in that frame.
2071 If that happens, go back to the selected frame
2072 so we can complete the cycle. */
2074 XSETFRAME (tem, selected_frame ());
2077 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2083 /* If we're in a combination window, find its first child and
2084 recurse on that. Otherwise, we've found the window we want. */
2087 if (!NILP (XWINDOW (window)->hchild))
2088 window = XWINDOW (window)->hchild;
2089 else if (!NILP (XWINDOW (window)->vchild))
2090 window = XWINDOW (window)->vchild;
2094 /* "acceptable" is the correct spelling. */
2095 /* Which windows are acceptable?
2096 Exit the loop and accept this window if
2097 this isn't a minibuffer window,
2098 or we're accepting all minibuffer windows,
2099 or this is the active minibuffer and we are accepting that one, or
2100 we've come all the way around and we're back at the original window. */
2101 while (MINI_WINDOW_P (XWINDOW (window))
2102 && ! EQ (minibuf, Qt)
2103 && ! EQ (minibuf, window)
2104 && ! EQ (window, start_window));
2109 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2110 Return the window preceding WINDOW in canonical ordering of windows.
2111 If omitted, WINDOW defaults to the selected window.
2113 Optional second arg MINIBUF t means count the minibuffer window even
2114 if not active. MINIBUF nil or omitted means count the minibuffer iff
2115 it is active. MINIBUF neither t nor nil means not to count the
2116 minibuffer even if it is active.
2118 Several frames may share a single minibuffer; if the minibuffer
2119 counts, all windows on all frames that share that minibuffer count
2120 too. Therefore, `previous-window' can be used to iterate through
2121 the set of windows even when the minibuffer is on another frame. If
2122 the minibuffer does not count, only windows from WINDOW's frame count
2124 If optional third arg ALL-FRAMES t means include windows on all frames.
2125 ALL-FRAMES nil or omitted means cycle within the frames as specified
2126 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2127 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2128 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2129 Anything else means restrict to WINDOW's frame.
2131 Optional fourth argument CONSOLE controls which consoles or devices the
2132 returned window may be on. If CONSOLE is a console, return windows only
2133 on that console. If CONSOLE is a device, return windows only on that
2134 device. If CONSOLE is a console type, return windows only on consoles
2135 of that type. If CONSOLE is 'window-system, return any windows on any
2136 window-system consoles. If CONSOLE is nil or omitted, return windows only
2137 on WINDOW's console. Otherwise, all windows are considered.
2139 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2140 can use `previous-window' to iterate through the entire cycle of acceptable
2141 windows, eventually ending up back at the window you started with.
2142 `next-window' traverses the same cycle, in the reverse order.
2144 (window, minibuf, all_frames, console))
2147 Lisp_Object start_window;
2150 window = Fselected_window (Qnil);
2152 CHECK_LIVE_WINDOW (window);
2154 start_window = window;
2156 /* minibuf == nil may or may not include minibuffers.
2157 Decide if it does. */
2159 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2160 else if (! EQ (minibuf, Qt))
2162 /* Now minibuf can be t => count all minibuffer windows,
2163 lambda => count none of them,
2164 or a specific minibuffer window (the active one) to count. */
2166 /* all_frames == nil doesn't specify which frames to include.
2167 Decide which frames it includes. */
2168 if (NILP (all_frames))
2169 all_frames = (! EQ (minibuf, Qlambda)
2170 ? (FRAME_MINIBUF_WINDOW
2173 (XWINDOW (window)))))
2175 else if (EQ (all_frames, Qvisible))
2177 else if (ZEROP (all_frames))
2179 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2180 /* If all_frames is a frame and window arg isn't on that frame, just
2181 return the first window on the frame. */
2182 return frame_first_window (XFRAME (all_frames));
2183 else if (! EQ (all_frames, Qt))
2185 /* Now all_frames is t meaning search all frames,
2186 nil meaning search just current frame,
2187 visible meaning search just visible frames,
2188 0 meaning search visible and iconified frames,
2189 or a window, meaning search the frame that window belongs to. */
2191 /* Do this loop at least once, to get the next window, and perhaps
2192 again, if we hit the minibuffer and that is not acceptable. */
2195 /* Find a window that actually has a next one. This loop
2196 climbs up the tree. */
2197 while (tem = XWINDOW (window)->prev, NILP (tem))
2198 if (tem = XWINDOW (window)->parent, !NILP (tem))
2200 else /* window must be minibuffer window now */
2202 /* We have found the top window on the frame.
2203 Which frames are acceptable? */
2204 tem = WINDOW_FRAME (XWINDOW (window));
2206 if (! NILP (all_frames))
2207 /* It's actually important that we use prev_frame here,
2208 rather than next_frame. All the windows acceptable
2209 according to the given parameters should form a ring;
2210 Fnext_window and Fprevious_window should go back and
2211 forth around the ring. If we use next_frame here,
2212 then Fnext_window and Fprevious_window take different
2213 paths through the set of acceptable windows.
2214 window_loop assumes that these `ring' requirement are
2220 tem = prev_frame (tem, all_frames, console);
2221 /* In the case where the minibuffer is active,
2222 and we include its frame as well as the selected one,
2223 next_frame may get stuck in that frame.
2224 If that happens, go back to the selected frame
2225 so we can complete the cycle. */
2227 XSETFRAME (tem, selected_frame ());
2230 /* If this frame has a minibuffer, find that window first,
2231 because it is conceptually the last window in that frame. */
2232 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2233 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2235 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2242 /* If we're in a combination window, find its first child and
2243 recurse on that. Otherwise, we've found the window we want. */
2246 if (!NILP (XWINDOW (window)->hchild))
2247 window = XWINDOW (window)->hchild;
2248 else if (!NILP (XWINDOW (window)->vchild))
2249 window = XWINDOW (window)->vchild;
2251 while (tem = XWINDOW (window)->next, !NILP (tem))
2255 /* Which windows are acceptable?
2256 Exit the loop and accept this window if
2257 this isn't a minibuffer window,
2258 or we're accepting all minibuffer windows,
2259 or this is the active minibuffer and we are accepting that one, or
2260 we've come all the way around and we're back at the original window. */
2261 while (MINI_WINDOW_P (XWINDOW (window))
2262 && ! EQ (minibuf, Qt)
2263 && ! EQ (minibuf, window)
2264 && ! EQ (window, start_window));
2269 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2270 Return the next window which is vertically after WINDOW.
2275 struct window *w = decode_window (window);
2276 XSETWINDOW (window, w);
2278 if (MINI_WINDOW_P (XWINDOW (window)))
2281 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2283 if (EQ (window, root))
2286 if (!NILP (XWINDOW (window)->hchild))
2287 window = XWINDOW (window)->hchild;
2288 else if (!NILP (XWINDOW (window)->vchild))
2289 window = XWINDOW (window)->vchild;
2296 if (!NILP (XWINDOW (window)->parent) &&
2297 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2299 if (!NILP (XWINDOW (window)->next))
2300 return XWINDOW (window)->next;
2302 window = XWINDOW (window)->parent;
2305 window = XWINDOW (window)->parent;
2307 while (!EQ (window, root));
2310 if (!NILP (XWINDOW (window)->hchild))
2311 window = XWINDOW (window)->hchild;
2312 else if (!NILP (XWINDOW (window)->vchild))
2313 window = XWINDOW (window)->vchild;
2318 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2319 Select the N'th different window on this frame.
2320 All windows on current frame are arranged in a cyclic order.
2321 This command selects the window N steps away in that order.
2322 A negative N moves in the opposite order.
2324 If optional argument FRAME is `visible', search all visible frames.
2325 If FRAME is 0, search all visible and iconified frames.
2326 If FRAME is t, search all frames.
2327 If FRAME is nil, search only the selected frame.
2328 If FRAME is a frame, search only that frame.
2330 Optional third argument CONSOLE controls which consoles or devices the
2331 returned window may be on. If CONSOLE is a console, return windows only
2332 on that console. If CONSOLE is a device, return windows only on that
2333 device. If CONSOLE is a console type, return windows only on consoles
2334 of that type. If CONSOLE is 'window-system, return any windows on any
2335 window-system consoles. If CONSOLE is nil or omitted, return windows only
2336 on FRAME'S console, or on the selected console if FRAME is not a frame.
2337 Otherwise, all windows are considered.
2339 (n, frame, console))
2345 w = Fselected_window (Qnil);
2350 w = Fnext_window (w, Qnil, frame, console);
2355 w = Fprevious_window (w, Qnil, frame, console);
2358 Fselect_window (w, Qnil);
2363 /* Look at all windows, performing an operation specified by TYPE
2366 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2367 frame. If FRAMES is a frame, just look at windows on that frame.
2368 If MINI is non-zero, perform the operation on minibuffer windows too.
2374 GET_BUFFER_WINDOW, /* Arg is buffer */
2375 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2376 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2377 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2379 UNSHOW_BUFFER, /* Arg is buffer */
2380 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2381 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2385 window_loop (enum window_loop type,
2390 Lisp_Object console)
2392 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2394 Lisp_Object best_window = Qnil;
2395 Lisp_Object next_window;
2396 Lisp_Object last_window;
2397 struct frame *frame;
2398 Lisp_Object frame_arg = Qt;
2399 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2400 /* #### I think the change of "precomputing" last_window and next_window
2401 * #### catch the lossage this is meant(?) to punt on...
2404 Lisp_Object devcons, concons;
2406 /* FRAME_ARG is Qlambda to stick to one frame,
2407 Qvisible to consider all visible frames,
2410 /* If we're only looping through windows on a particular frame,
2411 FRAME points to that frame. If we're looping through windows
2412 on all frames, FRAME is 0. */
2414 if (FRAMEP (frames))
2415 frame = XFRAME (frames);
2416 else if (NILP (frames))
2417 frame = selected_frame ();
2421 frame_arg = Qlambda;
2422 else if (ZEROP (frames))
2424 else if (EQ (frames, Qvisible))
2427 DEVICE_LOOP_NO_BREAK (devcons, concons)
2429 Lisp_Object device = XCAR (devcons);
2430 Lisp_Object the_frame;
2433 XSETFRAME (the_frame, frame);
2435 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2437 if (NILP (the_frame))
2440 if (!device_matches_console_spec (the_frame, device, console))
2443 /* Pick a window to start with. */
2447 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2449 /* Figure out the last window we're going to mess with. Since
2450 Fnext_window, given the same options, is guaranteed to go in a
2451 ring, we can just use Fprevious_window to find the last one.
2453 We can't just wait until we hit the first window again,
2454 because it might be deleted. */
2456 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2461 struct window *p = XWINDOW (w);
2462 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2464 /* Pick the next window now, since some operations will delete
2465 the current window. */
2466 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2468 /* #### Still needed ?? */
2469 /* Given the outstanding quality of the rest of this code,
2470 I feel no shame about putting this piece of shit in. */
2471 if (++lose_lose >= 500)
2474 /* Note that we do not pay attention here to whether
2475 the frame is visible, since Fnext_window skips non-visible frames
2476 if that is desired, under the control of frame_arg. */
2477 if (! MINI_WINDOW_P (p)
2478 || (mini && minibuf_level > 0))
2481 case GET_BUFFER_WINDOW:
2483 if (XBUFFER (p->buffer) == XBUFFER (obj))
2488 case GET_BUFFER_WINDOW_COUNT:
2490 if (XBUFFER (p->buffer) == XBUFFER (obj))
2495 case GET_LRU_WINDOW:
2497 /* t as arg means consider only full-width windows */
2499 && !window_full_width_p (p))
2501 /* Ignore dedicated windows and minibuffers. */
2502 if (MINI_WINDOW_P (p)
2503 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2505 if (NILP (best_window)
2506 || (XINT (XWINDOW (best_window)->use_time)
2507 > XINT (p->use_time)))
2512 case GET_BUFFER_MRU_WINDOW:
2514 /* #### what about the first check in GET_LRU_WINDOW? */
2515 /* Ignore dedicated windows and minibuffers. */
2516 if (MINI_WINDOW_P (p)
2517 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2520 if (XBUFFER (p->buffer) == XBUFFER (obj))
2522 if (NILP (best_window)
2523 || (XINT (XWINDOW (best_window)->use_time)
2524 < XINT (p->use_time)))
2530 case DELETE_OTHER_WINDOWS:
2532 /* Don't delete the last window on a frame; this can
2533 happen when the minibuffer is selected, and would
2534 cause the frame to be deleted. */
2535 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2536 Fdelete_window (w, Qnil);
2540 case DELETE_BUFFER_WINDOWS:
2542 if (EQ (p->buffer, obj))
2544 struct frame *f = XFRAME (WINDOW_FRAME (p));
2546 /* If this window is dedicated, and in a frame
2547 of its own, kill the frame. */
2548 if (EQ (w, FRAME_ROOT_WINDOW (f))
2549 && !NILP (p->dedicated)
2550 && other_visible_frames (f))
2552 /* Skip the other windows on this frame.
2553 There might be one, the minibuffer! */
2554 if (! EQ (w, last_window))
2555 while (f == XFRAME (WINDOW_FRAME
2556 (XWINDOW (next_window))))
2558 /* As we go, check for the end of the
2559 loop. We mustn't start going
2560 around a second time. */
2561 if (EQ (next_window, last_window))
2566 next_window = Fnext_window (next_window,
2570 /* Now we can safely delete the frame. */
2571 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2574 /* If we're deleting the buffer displayed in
2575 the only window on the frame, find a new
2576 buffer to display there. */
2577 if (NILP (p->parent))
2579 Lisp_Object new_buffer;
2580 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2581 if (NILP (new_buffer))
2582 new_buffer = Fget_buffer_create (QSscratch);
2583 Fset_window_buffer (w, new_buffer);
2584 if (EQ (w, Fselected_window (Qnil)))
2585 Fset_buffer (p->buffer);
2588 Fdelete_window (w, Qnil);
2593 case GET_LARGEST_WINDOW:
2595 /* Ignore dedicated windows and minibuffers. */
2596 if (MINI_WINDOW_P (p)
2597 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2600 /* write the check as follows to avoid tripping
2601 error_check_window() --ben */
2602 struct window *b = NILP (best_window) ? 0 :
2603 XWINDOW (best_window);
2604 if (NILP (best_window)
2605 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2606 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2614 if (EQ (p->buffer, obj))
2616 /* Find another buffer to show in this window. */
2617 Lisp_Object another_buffer =
2618 Fother_buffer (obj, Qnil, Qnil);
2619 if (NILP (another_buffer))
2621 = Fget_buffer_create (QSscratch);
2622 /* If this window is dedicated, and in a frame
2623 of its own, kill the frame. */
2624 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2625 && !NILP (p->dedicated)
2626 && other_visible_frames (w_frame))
2628 /* Skip the other windows on this frame.
2629 There might be one, the minibuffer! */
2630 if (! EQ (w, last_window))
2631 while (w_frame == XFRAME (WINDOW_FRAME
2632 (XWINDOW (next_window))))
2634 /* As we go, check for the end of the
2635 loop. We mustn't start going
2636 around a second time. */
2637 if (EQ (next_window, last_window))
2642 next_window = Fnext_window (next_window,
2646 /* Now we can safely delete the frame. */
2647 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2652 /* Otherwise show a different buffer in the
2654 p->dedicated = Qnil;
2655 Fset_window_buffer (w, another_buffer);
2656 if (EQ (w, Fselected_window (Qnil)))
2657 Fset_buffer (p->buffer);
2667 if (EQ (w, last_window))
2674 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2677 #if 0 /* not currently used */
2680 buffer_window_count (struct buffer *b, struct frame *f)
2682 Lisp_Object buffer, frame;
2684 XSETFRAME (frame, f);
2685 XSETBUFFER (buffer, b);
2687 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2692 buffer_window_mru (struct window *w)
2694 Lisp_Object window =
2695 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2699 else if (XWINDOW (window) == w)
2708 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2709 Return the window least recently selected or used for display.
2710 If optional argument FRAME is `visible', search all visible frames.
2711 If FRAME is 0, search all visible and iconified frames.
2712 If FRAME is t, search all frames.
2713 If FRAME is nil, search only the selected frame.
2714 If FRAME is a frame, search only that frame.
2716 Optional second argument CONSOLE controls which consoles or devices the
2717 returned window may be on. If CONSOLE is a console, return windows only
2718 on that console. If CONSOLE is a device, return windows only on that
2719 device. If CONSOLE is a console type, return windows only on consoles
2720 of that type. If CONSOLE is 'window-system, return any windows on any
2721 window-system consoles. If CONSOLE is nil or omitted, return windows only
2722 on FRAME'S console, or on the selected console if FRAME is not a frame.
2723 Otherwise, all windows are considered.
2728 /* First try for a non-dedicated window that is full-width */
2729 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2730 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2733 /* Then try for any non-dedicated window */
2734 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2735 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2739 /* FSFmacs never returns a dedicated window here. If we do,
2740 it makes `display-buffer' not work right. #### All of this
2741 shit is so disgusting and awful that it needs to be rethought
2743 /* then try for a dedicated window that is full-width */
2744 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2745 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2748 /* If none of them, then all windows, dedicated or not. */
2749 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2751 /* At this point we damn well better have found something. */
2752 if (NILP (w)) abort ();
2758 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2759 Return the window largest in area.
2760 If optional argument FRAME is `visible', search all visible frames.
2761 If FRAME is 0, search all visible and iconified frames.
2762 If FRAME is t, search all frames.
2763 If FRAME is nil, search only the selected frame.
2764 If FRAME is a frame, search only that frame.
2766 Optional second argument CONSOLE controls which consoles or devices the
2767 returned window may be on. If CONSOLE is a console, return windows only
2768 on that console. If CONSOLE is a device, return windows only on that
2769 device. If CONSOLE is a console type, return windows only on consoles
2770 of that type. If CONSOLE is 'window-system, return any windows on any
2771 window-system consoles. If CONSOLE is nil or omitted, return windows only
2772 on FRAME'S console, or on the selected console if FRAME is not a frame.
2773 Otherwise, all windows are considered.
2777 /* Don't search dedicated windows because FSFmacs doesn't.
2778 This stuff is all black magic so don't try to apply common
2780 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2783 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2784 Return a window currently displaying BUFFER, or nil if none.
2785 If optional argument FRAME is `visible', search all visible frames.
2786 If optional argument FRAME is 0, search all visible and iconified frames.
2787 If FRAME is t, search all frames.
2788 If FRAME is nil, search only the selected frame.
2789 If FRAME is a frame, search only that frame.
2791 Optional third argument CONSOLE controls which consoles or devices the
2792 returned window may be on. If CONSOLE is a console, return windows only
2793 on that console. If CONSOLE is a device, return windows only on that
2794 device. If CONSOLE is a console type, return windows only on consoles
2795 of that type. If CONSOLE is 'window-system, return any windows on any
2796 window-system consoles. If CONSOLE is nil or omitted, return windows only
2797 on FRAME'S console, or on the selected console if FRAME is not a frame.
2798 Otherwise, all windows are considered.
2800 (buffer, frame, console))
2802 buffer = Fget_buffer (buffer);
2803 if (BUFFERP (buffer))
2804 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2805 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2810 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2811 but there is no sensible way to implement those functions, since
2812 you can't in general derive a window from a buffer. */
2814 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2816 Return the width in pixels of the left outside margin of window WINDOW.
2817 If WINDOW is nil, the selected window is assumed.
2821 return make_int (window_left_margin_width (decode_window (window)));
2824 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2826 Return the width in pixels of the right outside margin of window WINDOW.
2827 If WINDOW is nil, the selected window is assumed.
2831 return make_int (window_right_margin_width (decode_window (window)));
2834 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2835 Make WINDOW (or the selected window) fill its frame.
2836 Only the frame WINDOW is on is affected.
2837 This function tries to reduce display jumps
2838 by keeping the text previously visible in WINDOW
2839 in the same place on the frame. Doing this depends on
2840 the value of (window-start WINDOW), so if calling this function
2841 in a program gives strange scrolling, make sure the window-start
2842 value is reasonable when this function is called.
2846 struct window *w = decode_window (window);
2847 struct buffer *b = XBUFFER (w->buffer);
2849 int old_top = WINDOW_TOP (w);
2851 XSETWINDOW (window, w);
2853 if (MINI_WINDOW_P (w) && old_top > 0)
2854 error ("Can't expand minibuffer to full frame");
2856 /* Ignore dedicated windows. */
2857 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2859 start_pos = marker_position (w->start[CURRENT_DISP]);
2861 /* Try to minimize scrolling, by setting the window start to the
2862 point which will cause the text at the old window start to be at
2863 the same place on the frame. But don't try to do this if the
2864 window start is outside the visible portion (as might happen when
2865 the display is not current, due to typeahead). */
2866 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2867 && !MINI_WINDOW_P (w))
2869 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2871 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2873 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2875 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2877 /* We need to do this, so that the window-scroll-functions
2885 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2886 "bDelete windows on (buffer): ", /*
2887 Delete all windows showing BUFFER.
2888 Optional second argument FRAME controls which frames are affected.
2889 If nil or omitted, delete all windows showing BUFFER in any frame.
2890 If t, delete only windows showing BUFFER in the selected frame.
2891 If `visible', delete all windows showing BUFFER in any visible frame.
2892 If a frame, delete only windows showing BUFFER in that frame.
2894 Optional third argument CONSOLE controls which consoles or devices the
2895 returned window may be on. If CONSOLE is a console, return windows only
2896 on that console. If CONSOLE is a device, return windows only on that
2897 device. If CONSOLE is a console type, return windows only on consoles
2898 of that type. If CONSOLE is 'window-system, return any windows on any
2899 window-system consoles. If CONSOLE is nil or omitted, return windows only
2900 on FRAME'S console, or on the selected console if FRAME is not a frame.
2901 Otherwise, all windows are considered.
2903 (buffer, frame, console))
2905 /* This function can GC */
2906 /* FRAME uses t and nil to mean the opposite of what window_loop
2908 if (!FRAMEP (frame))
2909 frame = NILP (frame) ? Qt : Qnil;
2913 buffer = Fget_buffer (buffer);
2914 CHECK_BUFFER (buffer);
2915 /* Ignore dedicated windows. */
2916 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2921 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2922 "bReplace buffer in windows: ", /*
2923 Replace BUFFER with some other buffer in all windows showing it.
2927 /* This function can GC */
2930 buffer = Fget_buffer (buffer);
2931 CHECK_BUFFER (buffer);
2932 /* Ignore dedicated windows. */
2933 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2938 /* The smallest acceptable dimensions for a window. Anything smaller
2939 might crash Emacs. */
2940 #define MIN_SAFE_WINDOW_WIDTH (2)
2941 #define MIN_SAFE_WINDOW_HEIGHT (2)
2943 /* Make sure that window_min_height and window_min_width are
2944 not too small; if they are, set them to safe minima. */
2947 check_min_window_sizes (void)
2949 /* Smaller values might permit a crash. */
2950 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2951 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2952 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2953 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2956 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2957 minimum allowable size. */
2959 check_frame_size (struct frame *frame, int *rows, int *cols)
2961 /* For height, we have to see whether the frame has a minibuffer, and
2962 whether it wants a modeline. */
2964 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2965 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2966 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2968 if (*rows < min_height)
2970 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2971 *cols = MIN_SAFE_WINDOW_WIDTH;
2974 /* Normally the window is deleted if it gets too small.
2975 nodelete nonzero means do not do this.
2976 (The caller should check later and do so if appropriate) */
2978 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
2981 struct window *w = XWINDOW (window);
2982 struct frame *f = XFRAME (w->frame);
2984 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
2985 Lisp_Object child, minor_kid, major_kid;
2988 int defheight, defwidth;
2990 /* #### This is very likely incorrect and instead the char_to_pixel_
2991 functions should be called. */
2992 default_face_height_and_width (window, &defheight, &defwidth);
2993 line_size = (set_height ? defheight : defwidth);
2995 check_min_window_sizes ();
2997 minsize = (set_height ? window_min_height : window_min_width);
2998 minsize *= line_size;
3001 && !TOP_LEVEL_WINDOW_P (w)
3002 && new_pixsize < minsize)
3004 Fdelete_window (window, Qnil);
3008 SET_LAST_MODIFIED (w, 0);
3009 SET_LAST_FACECHANGE (w);
3010 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3013 WINDOW_HEIGHT (w) = new_pixsize;
3014 major_kid = w->vchild;
3015 minor_kid = w->hchild;
3019 WINDOW_WIDTH (w) = new_pixsize;
3020 major_kid = w->hchild;
3021 minor_kid = w->vchild;
3024 if (!NILP (minor_kid))
3026 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3029 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3031 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3033 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3036 else if (!NILP (major_kid))
3038 int last_pos, last_old_pos, pos, old_pos, first;
3039 int pixel_adj_left = new_pixsize - old_pixsize;
3040 int div_val = old_pixsize << 1;
3043 * Previously we bailed out here if there was no size change.
3044 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3045 * toolbar appears or disappears, windows may not change size,
3046 * but their top and left coordinates need to be updated.
3048 * So we don't bail until after the loop below.
3051 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3054 for (child = major_kid; !NILP (child); child = c->next)
3056 c = XWINDOW (child);
3060 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3061 WINDOW_TOP (c) = last_pos;
3065 old_pos = last_old_pos + WINDOW_WIDTH (c);
3066 WINDOW_LEFT (c) = last_pos;
3069 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3070 /* All but the last window should have a height which is
3071 a multiple of the default line height. */
3072 if (!NILP (c->next))
3073 pos = (pos / line_size) * line_size;
3075 /* Avoid confusion: don't delete child if it becomes too small */
3076 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3078 last_pos = pos + first;
3079 last_old_pos = old_pos;
3082 /* Sometimes we may get called with our old size. In that case
3083 we don't need to do anything else. */
3084 if (!pixel_adj_left)
3087 /* Now delete any children that became too small. */
3089 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3092 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3094 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3099 /* Set the height of WINDOW and all its inferiors. */
3101 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3103 set_window_pixsize (window, new_pixheight, nodelete, 1);
3106 /* Recursively set width of WINDOW and its inferiors. */
3108 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3110 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3114 static int window_select_count;
3116 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3117 Make WINDOW display BUFFER as its contents.
3118 BUFFER can be a buffer or buffer name.
3123 struct window *w = decode_window (window);
3125 buffer = Fget_buffer (buffer);
3126 CHECK_BUFFER (buffer);
3128 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3129 error ("Attempt to display deleted buffer");
3133 error ("Window is deleted");
3135 /* While this seems like a logical thing to do, it causes problems
3136 because of saved window configurations. It is possible for a
3137 buffer to get restored into a window in which it is already being
3138 displayed, but start and point are actually at completely
3139 different locations. So we let this function complete fully and
3140 it will then make sure redisplay correctly updates things.
3142 #### This is a kludge. The correct approach is not to do this
3143 but to fix set-window-configuration. */
3145 else if (EQ (tem, buffer))
3148 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3149 is first being set up. */
3151 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3152 error ("Window is dedicated to buffer %s",
3153 XSTRING_DATA (XBUFFER (tem)->name));
3159 w->window_end_pos[CURRENT_DISP] = 0;
3161 w->modeline_hscroll = 0;
3162 Fset_marker (w->pointm[CURRENT_DISP],
3163 make_int (BUF_PT (XBUFFER (buffer))),
3165 set_marker_restricted (w->start[CURRENT_DISP],
3166 make_int (XBUFFER (buffer)->last_window_start),
3168 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3169 /* set start_at_line_beg correctly. GE */
3170 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3171 marker_position (w->start[CURRENT_DISP]));
3172 w->force_start = 0; /* Lucid fix */
3173 SET_LAST_MODIFIED (w, 1);
3174 SET_LAST_FACECHANGE (w);
3175 MARK_WINDOWS_CHANGED (w);
3176 recompute_all_cached_specifiers_in_window (w);
3177 if (EQ (window, Fselected_window (Qnil)))
3179 Fset_buffer (buffer);
3184 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3185 Select WINDOW. Most editing will apply to WINDOW's buffer.
3186 The main editor command loop selects the buffer of the selected window
3187 before each command.
3189 With non-nil optional argument `norecord', do not modify the
3190 global or per-frame buffer ordering.
3195 Lisp_Object old_selected_window = Fselected_window (Qnil);
3197 CHECK_LIVE_WINDOW (window);
3198 w = XWINDOW (window);
3200 /* we have already caught dead-window errors */
3201 if (!NILP (w->hchild) || !NILP (w->vchild))
3202 error ("Trying to select non-leaf window");
3204 w->use_time = make_int (++window_select_count);
3205 if (EQ (window, old_selected_window))
3208 /* deselect the old window, if it exists (it might not exist if
3209 the selected device has no frames, which occurs at startup) */
3210 if (!NILP (old_selected_window))
3212 struct window *ow = XWINDOW (old_selected_window);
3214 Fset_marker (ow->pointm[CURRENT_DISP],
3215 make_int (BUF_PT (XBUFFER (ow->buffer))),
3218 MARK_WINDOWS_CHANGED (ow);
3221 /* now select the window's frame */
3222 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3224 select_frame_1 (WINDOW_FRAME (w));
3226 /* also select the window's buffer */
3227 if (NILP (norecord))
3228 Frecord_buffer (w->buffer);
3229 Fset_buffer (w->buffer);
3231 /* Go to the point recorded in the window.
3232 This is important when the buffer is in more
3233 than one window. It also matters when
3234 redisplay_window has altered point after scrolling,
3235 because it makes the change only in the window. */
3237 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3238 if (new_point < BUF_BEGV (current_buffer))
3239 new_point = BUF_BEGV (current_buffer);
3240 else if (new_point > BUF_ZV (current_buffer))
3241 new_point = BUF_ZV (current_buffer);
3243 BUF_SET_PT (current_buffer, new_point);
3246 MARK_WINDOWS_CHANGED (w);
3252 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3253 Lisp_Object override_frame)
3255 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3259 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3261 /* This function can GC */
3264 struct buffer *b = XBUFFER (buf);
3266 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3267 widen_buffer (b, 0);
3268 BUF_SET_PT (b, BUF_BEG (b));
3270 if (!NILP (Vtemp_buffer_show_function))
3271 call1 (Vtemp_buffer_show_function, buf);
3274 window = display_buffer (buf, Qnil, same_frame);
3276 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3277 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3279 Vminibuffer_scroll_window = window;
3280 w = XWINDOW (window);
3282 w->modeline_hscroll = 0;
3283 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3284 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3285 set_marker_restricted (w->sb_point, make_int (1), buf);
3287 /* Run temp-buffer-show-hook, with the chosen window selected. */
3288 if (!preparing_for_armageddon)
3291 tem = Fboundp (Qtemp_buffer_show_hook);
3294 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3297 int count = specpdl_depth ();
3299 /* Select the window that was chosen, for running
3301 record_unwind_protect (save_window_excursion_unwind,
3302 Fcurrent_window_configuration (Qnil));
3304 Fselect_window (window, Qnil);
3305 run_hook (Qtemp_buffer_show_hook);
3306 unbind_to (count, Qnil);
3314 make_dummy_parent (Lisp_Object window)
3317 struct window *o = XWINDOW (window);
3318 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
3320 XSETWINDOW (new, p);
3321 copy_lcrecord (p, o);
3323 /* Don't copy the pointers to the line start cache or the face
3325 p->line_start_cache = Dynarr_new (line_start_cache);
3326 p->face_cachels = Dynarr_new (face_cachel);
3327 p->glyph_cachels = Dynarr_new (glyph_cachel);
3329 /* Put new into window structure in place of window */
3330 replace_window (window, new);
3338 p->start[CURRENT_DISP] = Qnil;
3339 p->start[DESIRED_DISP] = Qnil;
3340 p->start[CMOTION_DISP] = Qnil;
3341 p->pointm[CURRENT_DISP] = Qnil;
3342 p->pointm[DESIRED_DISP] = Qnil;
3343 p->pointm[CMOTION_DISP] = Qnil;
3348 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3349 Split WINDOW, putting SIZE lines in the first of the pair.
3350 WINDOW defaults to selected one and SIZE to half its size.
3351 If optional third arg HOR-FLAG is non-nil, split side by side
3352 and put SIZE columns in the first of the pair.
3354 (window, chsize, horflag))
3357 struct window *o, *p;
3363 window = Fselected_window (Qnil);
3365 CHECK_WINDOW (window);
3367 o = XWINDOW (window);
3368 f = XFRAME (WINDOW_FRAME (o));
3372 if (!NILP (horflag))
3373 /* In the new scheme, we are symmetric with respect to separators
3374 so there is no need to do weird things here. */
3376 psize = WINDOW_WIDTH (o) >> 1;
3377 size = window_pixel_width_to_char_width (o, psize, 0);
3381 psize = WINDOW_HEIGHT (o) >> 1;
3382 size = window_pixel_height_to_char_height (o, psize, 1);
3388 size = XINT (chsize);
3389 if (!NILP (horflag))
3390 psize = window_char_width_to_pixel_width (o, size, 0);
3392 psize = window_char_height_to_pixel_height (o, size, 1);
3395 if (MINI_WINDOW_P (o))
3396 error ("Attempt to split minibuffer window");
3397 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3398 error ("Attempt to split unsplittable frame");
3400 check_min_window_sizes ();
3404 if (size < window_min_height)
3405 error ("Window height %d too small (after splitting)", size);
3406 if (size + window_min_height > window_char_height (o, 1))
3407 error ("Window height %d too small (after splitting)",
3408 window_char_height (o, 1) - size);
3409 if (NILP (o->parent)
3410 || NILP (XWINDOW (o->parent)->vchild))
3412 make_dummy_parent (window);
3413 reset_face_cachels (XWINDOW (window));
3415 XWINDOW (new)->vchild = window;
3416 XFRAME (o->frame)->mirror_dirty = 1;
3421 if (size < window_min_width)
3422 error ("Window width %d too small (after splitting)", size);
3423 if (size + window_min_width > window_char_width (o, 0))
3424 error ("Window width %d too small (after splitting)",
3425 window_char_width (o, 0) - size);
3426 if (NILP (o->parent)
3427 || NILP (XWINDOW (o->parent)->hchild))
3429 make_dummy_parent (window);
3430 reset_face_cachels (XWINDOW (window));
3432 XWINDOW (new)->hchild = window;
3433 XFRAME (o->frame)->mirror_dirty = 1;
3437 /* Now we know that window's parent is a vertical combination
3438 if we are dividing vertically, or a horizontal combination
3439 if we are making side-by-side windows */
3441 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3442 new = allocate_window ();
3445 p->frame = o->frame;
3447 if (!NILP (p->next))
3448 XWINDOW (p->next)->prev = new;
3451 p->parent = o->parent;
3454 reset_face_cachels (p);
3455 reset_glyph_cachels (p);
3458 /* Apportion the available frame space among the two new windows */
3460 if (!NILP (horflag))
3462 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3463 WINDOW_TOP (p) = WINDOW_TOP (o);
3464 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3465 WINDOW_WIDTH (o) = psize;
3466 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3470 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3471 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3472 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3473 WINDOW_HEIGHT (o) = psize;
3474 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3477 XFRAME (p->frame)->mirror_dirty = 1;
3478 /* do this last (after the window is completely initialized and
3479 the mirror-dirty flag is set) so that specifier recomputation
3480 caused as a result of this will work properly and not abort. */
3481 Fset_window_buffer (new, o->buffer);
3486 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3487 Make the selected window ARG lines bigger.
3488 From program, optional second arg non-nil means grow sideways ARG columns,
3489 and optional third ARG specifies the window to change instead of the
3494 struct window *w = decode_window (window);
3496 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3500 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3501 Make the selected window ARG pixels bigger.
3502 From program, optional second arg non-nil means grow sideways ARG pixels,
3503 and optional third ARG specifies the window to change instead of the
3508 struct window *w = decode_window (window);
3510 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3514 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3515 Make the selected window ARG lines smaller.
3516 From program, optional second arg non-nil means shrink sideways ARG columns,
3517 and optional third ARG specifies the window to change instead of the
3523 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3528 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3529 Make the selected window ARG pixels smaller.
3530 From program, optional second arg non-nil means shrink sideways ARG pixels,
3531 and optional third ARG specifies the window to change instead of the
3537 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3543 window_pixel_height (Lisp_Object window)
3545 return WINDOW_HEIGHT (XWINDOW (window));
3549 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3550 int include_gutters_p)
3553 int defheight, defwidth;
3557 XSETWINDOW (window, w);
3559 avail_height = (pixel_height -
3560 (include_gutters_p ? 0 :
3561 window_top_gutter_height (w) +
3562 window_bottom_gutter_height (w)));
3564 default_face_height_and_width (window, &defheight, &defwidth);
3566 char_height = avail_height / defheight;
3568 /* It's the calling function's responsibility to check these values
3569 and make sure they're not out of range.
3571 #### We need to go through the calling functions and actually
3573 return max (0, char_height);
3577 window_char_height_to_pixel_height (struct window *w, int char_height,
3578 int include_gutters_p)
3581 int defheight, defwidth;
3586 XSETWINDOW (window, w);
3588 default_face_height_and_width (window, &defheight, &defwidth);
3590 avail_height = char_height * defheight;
3591 pixel_height = (avail_height +
3592 (include_gutters_p ? 0 :
3593 window_top_gutter_height (w) +
3594 window_bottom_gutter_height (w)));
3596 /* It's the calling function's responsibility to check these values
3597 and make sure they're not out of range.
3599 #### We need to go through the calling functions and actually
3601 return max (0, pixel_height);
3604 /* Return number of default lines of text can fit in the window W.
3605 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3606 horizontal scrollbar) in the space that is used for the calculation.
3609 window_char_height (struct window *w, int include_gutters_p)
3611 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3616 * Return number of lines currently displayed in window w. If
3617 * end-of-buffer is displayed then the area below end-of-buffer is assume
3618 * to be blank lines of default height.
3619 * Does not include the modeline.
3622 window_displayed_height (struct window *w)
3624 struct buffer *b = XBUFFER (w->buffer);
3625 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3627 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3629 : w->window_end_pos[CURRENT_DISP]);
3631 if (!Dynarr_length (dla))
3632 return window_char_height (w, 0);
3634 num_lines = Dynarr_length (dla);
3636 /* #### Document and assert somewhere that w->window_end_pos == -1
3637 indicates that end-of-buffer is being displayed. */
3640 struct display_line *dl = Dynarr_atp (dla, 0);
3641 int ypos1 = dl->ypos + dl->descent;
3642 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3644 int defheight, defwidth;
3646 XSETWINDOW (window, w);
3652 if (Dynarr_length (dla) == 1)
3653 ypos1 = WINDOW_TEXT_TOP (w);
3656 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3657 /* If this line is clipped then we know that there is no
3658 blank room between eob and the modeline. If we are
3659 scrolling on clipped lines just know off the clipped
3661 if (scroll_on_clipped_lines && dl->clip)
3662 return num_lines - 1;
3663 ypos1 = dl->ypos + dl->descent - dl->clip;
3667 default_face_height_and_width (window, &defheight, &defwidth);
3668 /* #### This probably needs to know about the clipping area once a
3669 final definition is decided on. */
3670 num_lines += ((ypos2 - ypos1) / defheight);
3674 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3677 if (scroll_on_clipped_lines
3678 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3686 window_pixel_width (Lisp_Object window)
3688 return WINDOW_WIDTH (XWINDOW (window));
3692 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3693 int include_margins_p)
3697 int defheight, defwidth;
3700 XSETWINDOW (window, w);
3702 avail_width = (pixel_width -
3703 window_left_gutter_width (w, 0) -
3704 window_right_gutter_width (w, 0) -
3705 (include_margins_p ? 0 : window_left_margin_width (w)) -
3706 (include_margins_p ? 0 : window_right_margin_width (w)));
3708 default_face_height_and_width (window, &defheight, &defwidth);
3710 char_width = (avail_width / defwidth);
3712 /* It's the calling function's responsibility to check these values
3713 and make sure they're not out of range.
3715 #### We need to go through the calling functions and actually
3717 return max (0, char_width);
3721 window_char_width_to_pixel_width (struct window *w, int char_width,
3722 int include_margins_p)
3726 int defheight, defwidth;
3729 XSETWINDOW (window, w);
3731 default_face_height_and_width (window, &defheight, &defwidth);
3733 avail_width = char_width * defwidth;
3734 pixel_width = (avail_width +
3735 window_left_gutter_width (w, 0) +
3736 window_right_gutter_width (w, 0) +
3737 (include_margins_p ? 0 : window_left_margin_width (w)) +
3738 (include_margins_p ? 0 : window_right_margin_width (w)));
3740 /* It's the calling function's responsibility to check these values
3741 and make sure they're not out of range.
3743 #### We need to go through the calling functions and actually
3745 return max (0, pixel_width);
3748 /* This returns the usable space which doesn't include space needed by
3749 scrollbars or divider lines. */
3751 window_char_width (struct window *w, int include_margins_p)
3753 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3757 #define MINSIZE(w) \
3759 ? window_min_width * defwidth \
3760 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3763 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3765 #define CURSIZE(w) \
3766 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3768 #define CURCHARSIZE(w) \
3769 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3771 #define MINCHARSIZE(window) \
3772 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3773 ? 1 : window_min_height)
3775 /* Unlike set_window_pixheight, this function
3776 also changes the heights of the siblings so as to
3777 keep everything consistent. */
3780 change_window_height (struct window *win, int delta, int widthflag,
3788 int (*sizefun) (Lisp_Object) = (widthflag
3789 ? window_pixel_width
3790 : window_pixel_height);
3791 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3792 ? set_window_pixwidth
3793 : set_window_pixheight);
3795 int defheight, defwidth;
3800 check_min_window_sizes ();
3802 XSETWINDOW (window, win);
3803 f = XFRAME (win->frame);
3804 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3805 error ("Won't change only window");
3807 /* #### This is very likely incorrect and instead the char_to_pixel_
3808 functions should be called. */
3809 default_face_height_and_width (window, &defheight, &defwidth);
3813 w = XWINDOW (window);
3818 error ("No other window to side of this one");
3822 ? !NILP (XWINDOW (parent)->hchild)
3823 : !NILP (XWINDOW (parent)->vchild))
3828 sizep = &CURSIZE (w);
3829 dim = CURCHARSIZE (w);
3831 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3832 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3834 if (MINI_WINDOW_P (XWINDOW (window)))
3836 else if (!NILP (parent))
3838 Fdelete_window (window, Qnil);
3844 delta *= (widthflag ? defwidth : defheight);
3849 maxdelta = ((!NILP (parent))
3850 ? (*sizefun) (parent) - *sizep
3851 : ((!NILP (w->next))
3852 ? (*sizefun) (w->next) - MINSIZE (w->next)
3853 : ((!NILP (w->prev))
3854 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3855 /* This is a frame with only one window,
3856 a minibuffer-only or a minibufferless frame. */
3859 if (delta > maxdelta)
3860 /* This case traps trying to make the minibuffer
3861 the full frame, or make the only window aside from the
3862 minibuffer the full frame. */
3869 /* #### Chuck: is this correct? */
3870 if (*sizep + delta < MINSIZE (window))
3872 Fdelete_window (window);
3878 if (!NILP (w->next) &&
3879 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3881 CURBEG (XWINDOW (w->next)) += delta;
3882 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3883 (*setsizefun) (window, *sizep + delta, 0);
3885 else if (!NILP (w->prev) &&
3886 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3888 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3889 CURBEG (w) -= delta;
3890 (*setsizefun) (window, *sizep + delta, 0);
3895 int opht = (*sizefun) (parent);
3897 /* If trying to grow this window to or beyond size of the parent,
3898 make delta1 so big that, on shrinking back down,
3899 all the siblings end up with less than one line and are deleted. */
3900 if (opht <= *sizep + delta)
3901 delta1 = opht * opht * 2;
3902 /* Otherwise, make delta1 just right so that if we add delta1
3903 lines to this window and to the parent, and then shrink
3904 the parent back to its original size, the new proportional
3905 size of this window will increase by delta. */
3907 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3909 /* Add delta1 lines or columns to this window, and to the parent,
3910 keeping things consistent while not affecting siblings. */
3911 CURSIZE (XWINDOW (parent)) = opht + delta1;
3912 (*setsizefun) (window, *sizep + delta1, 0);
3914 /* Squeeze out delta1 lines or columns from our parent,
3915 shriking this window and siblings proportionately.
3916 This brings parent back to correct size.
3917 Delta1 was calculated so this makes this window the desired size,
3918 taking it all out of the siblings. */
3919 (*setsizefun) (parent, opht, 0);
3922 SET_LAST_MODIFIED (w, 0);
3923 SET_LAST_FACECHANGE (w);
3924 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3934 /* Scroll contents of window WINDOW up N lines. */
3936 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3937 Error_behavior errb)
3939 struct window *w = XWINDOW (window);
3940 struct buffer *b = XBUFFER (w->buffer);
3941 int selected = EQ (window, Fselected_window (Qnil));
3943 Lisp_Object point, tem;
3946 point = make_int (BUF_PT (b));
3949 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3951 if (pos < BUF_BEGV (b))
3953 else if (pos > BUF_ZV (b))
3956 point = make_int (pos);
3959 /* Always set force_start so that redisplay_window will run
3960 thw window-scroll-functions. */
3963 /* #### When the fuck does this happen? I'm so glad that history has
3964 completely documented the behavior of the scrolling functions under
3965 all circumstances. */
3966 tem = Fpos_visible_in_window_p (point, window);
3969 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
3971 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
3972 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
3973 MARK_WINDOWS_CHANGED (w);
3982 n = Fprefix_numeric_value (n);
3983 value = XINT (n) * direction;
3986 return; /* someone just made a pointless call */
3990 /* If the user didn't specify how far to scroll then we have to figure it
3991 out by ourselves. */
3992 if (NILP (n) || EQ (n, Qminus))
3994 /* Going forwards is easy. If that is what we are doing then just
3995 set value and the section which handles the user specifying a
3996 positive value will work. */
3999 value = window_displayed_height (w) - next_screen_context_lines;
4000 value = (value < 1 ? 1 : value);
4003 /* Going backwards is hard. We can't use the same loop used if the
4004 user specified a negative value because we care about
4005 next_screen_context_lines. In a variable height world you don't
4006 know how many lines above you can actually be displayed and still
4007 have the context lines appear. So we leave value set to 0 and add
4008 a separate section to deal with this. */
4012 if (direction == 1 && !value)
4019 Bufpos startp, old_start;
4021 old_start = marker_position (w->start[CURRENT_DISP]);
4022 startp = vmotion (w, old_start, value, &vtarget);
4024 if (vtarget < value &&
4025 (w->window_end_pos[CURRENT_DISP] == -1
4026 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4028 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4033 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4036 w->start_at_line_beg = beginning_of_line_p (b, startp);
4037 MARK_WINDOWS_CHANGED (w);
4039 if (!point_would_be_visible (w, startp, XINT (point)))
4042 BUF_SET_PT (b, startp);
4044 set_marker_restricted (w->pointm[CURRENT_DISP],
4053 Bufpos startp, old_start;
4055 old_start = marker_position (w->start[CURRENT_DISP]);
4056 startp = vmotion (w, old_start, value, &vtarget);
4059 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4061 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4066 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4069 w->start_at_line_beg = beginning_of_line_p (b, startp);
4070 MARK_WINDOWS_CHANGED (w);
4072 if (!point_would_be_visible (w, startp, XINT (point)))
4076 if (MINI_WINDOW_P (w))
4079 new_point = start_of_last_line (w, startp);
4082 BUF_SET_PT (b, new_point);
4084 set_marker_restricted (w->pointm[CURRENT_DISP],
4085 make_int (new_point),
4090 else /* value == 0 && direction == -1 */
4092 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4094 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4100 int movement = next_screen_context_lines - 1;
4101 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4102 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4104 start_with_point_on_display_line (w, bottom,
4105 -1 - (movement - vtarget));
4107 if (startp >= old_startp)
4108 startp = vmotion (w, old_startp, -1, NULL);
4110 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4113 w->start_at_line_beg = beginning_of_line_p (b, startp);
4114 MARK_WINDOWS_CHANGED (w);
4116 if (!point_would_be_visible (w, startp, XINT (point)))
4118 Bufpos new_point = start_of_last_line (w, startp);
4121 BUF_SET_PT (b, new_point);
4123 set_marker_restricted (w->pointm[CURRENT_DISP],
4124 make_int (new_point),
4132 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4133 Scroll text of current window upward ARG lines; or near full screen if no ARG.
4134 A near full screen is `next-screen-context-lines' less than a full screen.
4135 Negative ARG means scroll downward.
4136 When calling from a program, supply a number as argument or nil.
4137 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4138 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4143 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4147 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4148 Scroll text of current window downward ARG lines; or near full screen if no ARG.
4149 A near full screen is `next-screen-context-lines' less than a full screen.
4150 Negative ARG means scroll upward.
4151 When calling from a program, supply a number as argument or nil.
4152 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4153 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4158 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4162 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4163 Return the other window for "other window scroll" commands.
4164 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4165 specifies the window.
4166 If `other-window-scroll-buffer' is non-nil, a window
4167 showing that buffer is used.
4172 Lisp_Object selected_window = Fselected_window (Qnil);
4174 if (MINI_WINDOW_P (XWINDOW (selected_window))
4175 && !NILP (Vminibuffer_scroll_window))
4176 window = Vminibuffer_scroll_window;
4177 /* If buffer is specified, scroll that buffer. */
4178 else if (!NILP (Vother_window_scroll_buffer))
4180 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4182 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4186 /* Nothing specified; look for a neighboring window on the same
4188 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4190 if (EQ (window, selected_window))
4191 /* That didn't get us anywhere; look for a window on another
4194 window = Fnext_window (window, Qnil, Qt, Qnil);
4195 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4196 && ! EQ (window, selected_window));
4199 CHECK_LIVE_WINDOW (window);
4201 if (EQ (window, selected_window))
4202 error ("There is no other window");
4207 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4208 Scroll next window upward ARG lines; or near full frame if no ARG.
4209 The next window is the one below the current one; or the one at the top
4210 if the current one is at the bottom. Negative ARG means scroll downward.
4211 When calling from a program, supply a number as argument or nil.
4213 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4214 specifies the window to scroll.
4215 If `other-window-scroll-buffer' is non-nil, scroll the window
4216 showing that buffer, popping the buffer up if necessary.
4220 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4224 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4225 Scroll selected window display ARG columns left.
4226 Default for ARG is window width minus 2.
4230 Lisp_Object window = Fselected_window (Qnil);
4231 struct window *w = XWINDOW (window);
4234 arg = make_int (window_char_width (w, 0) - 2);
4236 arg = Fprefix_numeric_value (arg);
4238 return Fset_window_hscroll (window, make_int (w->hscroll + XINT (arg)));
4241 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4242 Scroll selected window display ARG columns right.
4243 Default for ARG is window width minus 2.
4247 Lisp_Object window = Fselected_window (Qnil);
4248 struct window *w = XWINDOW (window);
4251 arg = make_int (window_char_width (w, 0) - 2);
4253 arg = Fprefix_numeric_value (arg);
4255 return Fset_window_hscroll (window, make_int (w->hscroll - XINT (arg)));
4258 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4259 Center point in WINDOW. With N, put point on line N.
4260 The desired position of point is always relative to the window.
4261 If WINDOW is nil, the selected window is used.
4265 struct window *w = decode_window (window);
4266 struct buffer *b = XBUFFER (w->buffer);
4267 Bufpos opoint = BUF_PT (b);
4271 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4274 n = Fprefix_numeric_value (n);
4276 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4279 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4281 w->start_at_line_beg = beginning_of_line_p (b, startp);
4283 MARK_WINDOWS_CHANGED (w);
4287 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4288 Position point relative to WINDOW.
4289 With no argument, position text at center of window.
4290 An argument specifies window line; zero means top of window,
4291 negative means relative to bottom of window.
4292 If WINDOW is nil, the selected window is used.
4299 Bufpos start, new_point;
4302 /* Don't use decode_window() because we need the new value of
4305 window = Fselected_window (Qnil);
4307 CHECK_WINDOW (window);
4308 w = XWINDOW (window);
4309 b = XBUFFER (w->buffer);
4311 height = window_displayed_height (w);
4312 selected = EQ (window, Fselected_window (w->frame));
4318 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4319 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4321 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4324 BUF_SET_PT (b, new_point);
4326 Fset_window_point (window, make_int (new_point));
4328 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4332 start = marker_position (w->start[CURRENT_DISP]);
4333 if (start < BUF_BEGV (b))
4334 start = BUF_BEGV (b);
4335 else if (start > BUF_ZV (b))
4339 new_point = BUF_PT (b);
4341 new_point = marker_position (w->pointm[CURRENT_DISP]);
4343 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4346 BUF_SET_PT (b, new_point);
4348 Fset_window_point (window, make_int (new_point));
4350 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4353 return make_int (retval);
4357 /* #### Is this going to work right when at eob? */
4358 arg = Fprefix_numeric_value (arg);
4360 XSETINT (arg, XINT (arg) + height);
4363 start = marker_position (w->start[CURRENT_DISP]);
4364 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4367 new_point = BUF_PT (b);
4369 new_point = marker_position (w->pointm[CURRENT_DISP]);
4371 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4374 BUF_SET_PT (b, new_point);
4376 Fset_window_point (window, make_int (new_point));
4378 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4380 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4386 BUF_SET_PT (b, start);
4388 Fset_window_point (window, make_int (start));
4392 return Fvertical_motion (arg, window, Qnil);
4396 new_point = vmotion (XWINDOW (window),
4397 marker_position (w->pointm[CURRENT_DISP]),
4399 Fset_window_point (window, make_int (new_point));
4400 return make_int (vpos);
4406 map_windows_1 (Lisp_Object window,
4407 int (*mapfun) (struct window *w, void *closure),
4410 for (; !NILP (window); window = XWINDOW (window)->next)
4413 struct window *w = XWINDOW (window);
4415 if (!NILP (w->vchild))
4416 retval = map_windows_1 (w->vchild, mapfun, closure);
4417 else if (!NILP (w->hchild))
4418 retval = map_windows_1 (w->hchild, mapfun, closure);
4420 retval = (mapfun) (w, closure);
4429 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4430 invocation of MAPFUN. If any invocation of MAPFUN returns
4431 non-zero, the mapping is halted. Otherwise, map_windows() maps
4432 over all windows in F.
4434 If MAPFUN creates or deletes windows, the behaviour is undefined. */
4437 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4441 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4444 Lisp_Object frmcons, devcons, concons;
4446 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4448 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4460 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4463 w->shadow_thickness_changed = 1;
4464 MARK_WINDOWS_CHANGED (w);
4468 vertical_divider_changed_in_window (Lisp_Object specifier,
4472 MARK_WINDOWS_CHANGED (w);
4473 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4476 /* also used in scrollbar.c */
4478 some_window_value_changed (Lisp_Object specifier, struct window *w,
4481 MARK_WINDOWS_CHANGED (w);
4484 #ifdef MEMORY_USAGE_STATS
4490 #ifdef HAVE_SCROLLBARS
4494 int other_redisplay;
4499 compute_window_mirror_usage (struct window_mirror *mir,
4500 struct window_stats *stats,
4501 struct overhead_stats *ovstats)
4505 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4507 #ifdef HAVE_SCROLLBARS
4509 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4512 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4515 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4518 #endif /* HAVE_SCROLLBARS */
4519 stats->other_redisplay +=
4520 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4521 stats->other_redisplay +=
4522 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4526 compute_window_usage (struct window *w, struct window_stats *stats,
4527 struct overhead_stats *ovstats)
4530 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4531 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4532 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4533 stats->line_start +=
4534 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4535 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4538 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4539 Return stats about the memory usage of window WINDOW.
4540 The values returned are in the form of an alist of usage types and byte
4541 counts. The byte counts attempt to encompass all the memory used
4542 by the window (separate from the memory logically associated with a
4543 buffer or frame), including internal structures and any malloc()
4544 overhead associated with them. In practice, the byte counts are
4545 underestimated because certain memory usage is very hard to determine
4546 \(e.g. the amount of memory used inside the Xt library or inside the
4547 X server) and because there is other stuff that might logically
4548 be associated with a window, buffer, or frame (e.g. window configurations,
4549 glyphs) but should not obviously be included in the usage counts.
4551 Multiple slices of the total memory usage may be returned, separated
4552 by a nil. Each slice represents a particular view of the memory, a
4553 particular way of partitioning it into groups. Within a slice, there
4554 is no overlap between the groups of memory, and each slice collectively
4555 represents all the memory concerned.
4559 struct window_stats stats;
4560 struct overhead_stats ovstats;
4561 Lisp_Object val = Qnil;
4563 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4565 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4567 val = acons (Qface_cache, make_int (stats.face), val);
4568 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4569 #ifdef HAVE_SCROLLBARS
4570 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4572 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4573 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4574 val = acons (Qother, make_int (stats.other), val);
4575 val = Fcons (Qnil, val);
4576 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4577 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4578 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4580 return Fnreverse (val);
4583 #endif /* MEMORY_USAGE_STATS */
4586 /************************************************************************/
4587 /* Window configurations */
4588 /************************************************************************/
4590 /* #### This window configuration stuff has had serious bugs lurking in it
4591 for years; it would be a -huge- win if this was reimplemented in lisp.
4594 /* If you add anything to this structure make sure saved_window_equal
4598 Lisp_Object window; /* window */
4599 Lisp_Object buffer; /* buffer */
4600 Lisp_Object start; /* copied marker */
4601 Lisp_Object pointm; /* copied marker */
4602 Lisp_Object sb_point; /* copied marker */
4603 Lisp_Object mark; /* copied marker */
4609 int modeline_hscroll;
4610 int parent_index; /* index into saved_windows */
4611 int prev_index; /* index into saved_windows */
4612 char start_at_line_beg; /* boolean */
4614 #define WINDOW_SLOT_DECLARATION
4615 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4616 #include "winslots.h"
4619 /* If you add anything to this structure make sure window_config_equal
4621 struct window_config
4623 struct lcrecord_header header;
4627 Lisp_Object selected_frame;
4629 Lisp_Object current_window;
4630 Lisp_Object current_buffer;
4631 Lisp_Object minibuffer_scroll_window;
4632 Lisp_Object root_window;
4633 /* Record the values of window-min-width and window-min-height
4634 so that window sizes remain consistent with them. */
4635 int min_width, min_height;
4636 int saved_windows_count;
4637 /* Zero-sized arrays aren't ANSI C */
4638 struct saved_window saved_windows[1];
4641 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4642 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4643 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4644 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4645 #define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
4646 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4649 mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
4651 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4653 ((markobj) (config->current_window));
4654 ((markobj) (config->current_buffer));
4655 ((markobj) (config->minibuffer_scroll_window));
4656 ((markobj) (config->root_window));
4658 for (i = 0; i < config->saved_windows_count; i++)
4660 struct saved_window *s = SAVED_WINDOW_N (config, i);
4661 ((markobj) (s->window));
4662 ((markobj) (s->buffer));
4663 ((markobj) (s->start));
4664 ((markobj) (s->pointm));
4665 ((markobj) (s->sb_point));
4666 ((markobj) (s->mark));
4668 /* #### This looked like this. I do not see why specifier cached
4669 values should not be marked, as such specifiers as toolbars
4670 might have GC-able instances. Freed configs are not marked,
4671 aren't they? -- kkm */
4672 ((markobj) (s->dedicated));
4674 #define WINDOW_SLOT(slot, compare) ((markobj) (s->slot))
4675 #include "winslots.h"
4682 sizeof_window_config_for_n_windows (int n)
4684 return (sizeof (struct window_config) +
4685 /* n - 1 because zero-sized arrays aren't ANSI C */
4686 (n - 1) *sizeof (struct saved_window));
4690 sizeof_window_config (CONST void *h)
4692 CONST struct window_config *c = (CONST struct window_config *) h;
4693 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4697 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4699 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4702 error ("printing unreadable object #<window-configuration 0x%x>",
4703 config->header.uid);
4704 write_c_string ("#<window-configuration ", printcharfun);
4705 sprintf (buf, "0x%x>", config->header.uid);
4706 write_c_string (buf, printcharfun);
4709 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4710 window_configuration,
4712 print_window_config,
4713 0, 0, 0, sizeof_window_config,
4714 struct window_config);
4717 /* Returns a boolean indicating whether the two saved windows are
4720 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4722 #define WINDOW_SLOT(slot, compare) \
4723 if (!compare (win1->slot, win2->slot)) \
4725 #include "winslots.h"
4728 EQ (win1->window, win2->window) &&
4729 EQ (win1->buffer, win2->buffer) &&
4730 internal_equal (win1->start, win2->start, 0) &&
4731 internal_equal (win1->pointm, win2->pointm, 0) &&
4732 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4733 internal_equal (win1->mark, win2->mark, 0) &&
4734 win1->pixel_left == win2->pixel_left &&
4735 win1->pixel_top == win2->pixel_top &&
4736 win1->pixel_width == win2->pixel_width &&
4737 win1->pixel_height == win2->pixel_height &&
4738 win1->hscroll == win2->hscroll &&
4739 win1->modeline_hscroll == win2->modeline_hscroll &&
4740 win1->parent_index == win2->parent_index &&
4741 win1->prev_index == win2->prev_index &&
4742 win1->start_at_line_beg == win2->start_at_line_beg;
4745 /* Returns a boolean indicating whether the two given configurations
4748 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4750 struct window_config *fig1, *fig2;
4753 /* First check if they are truly the same. */
4754 if (EQ (conf1, conf2))
4757 fig1 = XWINDOW_CONFIGURATION (conf1);
4758 fig2 = XWINDOW_CONFIGURATION (conf2);
4760 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4761 EQ (fig1->current_window, fig2->current_window) &&
4762 EQ (fig1->current_buffer, fig2->current_buffer) &&
4763 EQ (fig1->root_window, fig2->root_window) &&
4764 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window) &&
4765 fig1->frame_width == fig2->frame_width &&
4766 fig1->frame_height == fig2->frame_height))
4769 for (i = 0; i < fig1->saved_windows_count; i++)
4771 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4772 SAVED_WINDOW_N (fig2, i)))
4779 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4780 Return t if OBJECT is a window-configuration object.
4784 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4788 mark_windows_in_use_closure (struct window *w, void *closure)
4790 int mark = *(int *)closure;
4791 w->config_mark = mark;
4796 mark_windows_in_use (struct frame *f, int mark)
4798 map_windows (f, mark_windows_in_use_closure, &mark);
4801 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4803 free_window_configuration (Lisp_Object window_config)
4806 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4808 /* Free all the markers. It's not completely necessary that
4809 we do this (window configs sitting in a free list aren't
4810 marked normally so the markers wouldn't be marked anyway)
4811 but it's more efficient. */
4812 for (i = 0; i < config->saved_windows_count; i++)
4814 struct saved_window *p = SAVED_WINDOW_N (config, i);
4816 if (!NILP (p->pointm))
4818 free_marker (XMARKER (p->pointm));
4821 if (!NILP (p->start))
4823 free_marker (XMARKER (p->start));
4826 if (!NILP (p->sb_point))
4828 free_marker (XMARKER (p->sb_point));
4831 if (!NILP (p->mark))
4833 free_marker (XMARKER (p->mark));
4838 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4839 free_managed_lcrecord (Vwindow_configuration_free_list
4840 [config->saved_windows_count - 1],
4846 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4847 Set the configuration of windows and buffers as specified by CONFIGURATION.
4848 CONFIGURATION must be a value previously returned
4849 by `current-window-configuration' (which see).
4854 struct window_config *config;
4855 struct saved_window *p;
4856 Lisp_Object new_current_buffer;
4860 struct gcpro gcpro1;
4861 Lisp_Object old_window_config;
4862 int previous_frame_height;
4863 int previous_frame_width;
4864 int specpdl_count = specpdl_depth ();
4866 GCPRO1 (configuration);
4868 CHECK_WINDOW_CONFIGURATION (configuration);
4869 config = XWINDOW_CONFIGURATION (configuration);
4871 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4874 /* Do not signal an error here if the frame was deleted. There are
4875 reasonable cases where we could get here with a deleted frame and
4876 just want to do close to nothing instead. */
4878 if (FRAME_LIVE_P (f))
4880 /* restore the frame characteristics */
4882 new_current_buffer = config->current_buffer;
4883 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4884 new_current_buffer = Qnil;
4887 * Assumed precondition: w->config_mark = 0 for all w
4888 * This procedure should ensure this is true by the time it exits
4889 * to ensure the precondition for future calls.
4891 * We use w->config_mark to know whether we're modifying a
4892 * window that is currently visible on the frame (#### we
4893 * should just be able to check whether the window is dead
4894 * or not, but this way is safer?). As we process each
4895 * window, we set its config_mark to 0. At the end, we
4896 * go through all the windows that used to be on the frame,
4897 * set each one's config_mark to 0 (to maintain the
4898 * assumed precondition) and delete each one that's no
4901 * #### Using a window-configuration to keep track of
4902 * the current windows is wasteful. All we need is the
4903 * list of windows, so we could just use a dynarr.
4905 old_window_config = Fcurrent_window_configuration (frame);
4907 /* If the new configuration is already equal to the old, then stop
4908 right here. This saves the work below and it also saves
4909 triggering a full redisplay of this window. This is a huge win
4910 when using the mouse since the mode motion code uses
4911 save-window-excursion extensively but will rarely cause the
4912 configuration to actually change. */
4913 if (window_config_equal (configuration, old_window_config))
4915 free_window_configuration (old_window_config);
4920 /* We can't quit or even check for quit because that may cause
4921 investigation of the frame state, which may crash if the frame is
4922 in an inconsistent state. */
4923 begin_dont_check_for_quit ();
4924 record_unwind_protect (free_window_configuration, old_window_config);
4926 mark_windows_in_use (f, 1);
4928 previous_frame_width = FRAME_WIDTH (f);
4929 previous_frame_height = FRAME_HEIGHT (f);
4930 /* If the frame has been resized since this window configuration was
4931 made, we change the frame to the size specified in the
4932 configuration, restore the configuration, and then resize it
4933 back. We keep track of the prevailing height in these variables. */
4934 if (config->frame_height != FRAME_HEIGHT (f)
4935 || config->frame_width != FRAME_WIDTH (f))
4936 change_frame_size (f, config->frame_height, config->frame_width, 0);
4938 /* Temporarily avoid any problems with windows that are smaller
4939 than they are supposed to be. */
4940 window_min_height = 1;
4941 window_min_width = 1;
4943 /* OK, now restore all the windows in the window config.
4944 This may involve "undeleting" windows, since the
4945 windows in the window config may be deleted.
4947 for (k = 0; k < config->saved_windows_count; k++)
4949 p = SAVED_WINDOW_N (config, k);
4950 w = XWINDOW (p->window);
4953 /* The window might be dead. In this case, its redisplay
4954 structures were freed, so we need to reallocate them. */
4955 if (!w->face_cachels)
4957 w->face_cachels = Dynarr_new (face_cachel);
4958 reset_face_cachels (w);
4960 if (!w->glyph_cachels)
4961 w->glyph_cachels = Dynarr_new (glyph_cachel);
4962 if (!w->line_start_cache)
4963 w->line_start_cache = Dynarr_new (line_start_cache);
4966 if (p->parent_index >= 0)
4967 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
4971 if (p->prev_index >= 0)
4973 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
4975 /* This is true for a minibuffer-only frame. */
4976 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
4979 XWINDOW (w->prev)->next = p->window;
4984 if (!NILP (w->parent))
4986 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
4988 XWINDOW (w->parent)->vchild = p->window;
4989 XWINDOW (w->parent)->hchild = Qnil;
4993 XWINDOW (w->parent)->hchild = p->window;
4994 XWINDOW (w->parent)->vchild = Qnil;
4998 if (!w->config_mark)
5000 /* #### This should be equivalent to the window previously
5001 having been dead. If we're brave, we'll put in an
5002 assertion to this effect. */
5003 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5005 else /* if (!EQ (w->buffer, p->buffer)) */
5007 /* With the new redisplay we let it know that a change has
5008 been made and it will take care of the rest. If we don't
5009 tell it something has possibly changed it could lead to
5010 incorrect display. */
5011 MARK_WINDOWS_CHANGED (w);
5014 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5015 WINDOW_TOP (w) = WINDOW_TOP (p);
5016 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5017 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5018 w->hscroll = p->hscroll;
5019 w->modeline_hscroll = p->modeline_hscroll;
5020 w->line_cache_last_updated = Qzero;
5021 SET_LAST_MODIFIED (w, 1);
5022 SET_LAST_FACECHANGE (w);
5025 #define WINDOW_SLOT(slot, compare) w->slot = p->slot;
5026 #include "winslots.h"
5028 /* Reinstall the saved buffer and pointers into it. */
5029 if (NILP (p->buffer))
5030 w->buffer = p->buffer;
5033 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5034 /* If saved buffer is alive, install it. */
5036 w->buffer = p->buffer;
5037 w->start_at_line_beg = p->start_at_line_beg;
5038 set_marker_restricted (w->start[CURRENT_DISP],
5039 Fmarker_position (p->start),
5041 set_marker_restricted (w->pointm[CURRENT_DISP],
5042 Fmarker_position (p->pointm),
5044 set_marker_restricted (w->sb_point,
5045 Fmarker_position (p->sb_point),
5047 Fset_marker (XBUFFER (w->buffer)->mark,
5048 Fmarker_position (p->mark), w->buffer);
5050 /* As documented in Fcurrent_window_configuration, don't
5051 save the location of point in the buffer which was current
5052 when the window configuration was recorded. */
5053 if (!EQ (p->buffer, new_current_buffer) &&
5054 XBUFFER (p->buffer) == current_buffer)
5055 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5057 else if (NILP (w->buffer) ||
5058 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5059 /* Else if window's old buffer is dead too, get a live one. */
5061 /* #### The following line makes me nervous... */
5062 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5063 w->buffer = Fget_buffer_create (QSscratch);
5064 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5065 /* This will set the markers to beginning of visible
5067 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5068 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5070 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5071 w->start_at_line_beg = 1;
5074 /* Keeping window's old buffer; make sure the markers
5077 /* Set window markers at start of visible range. */
5078 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5079 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5081 if (XMARKER (w->sb_point)->buffer == 0)
5082 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5083 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5084 set_marker_restricted (w->pointm[CURRENT_DISP],
5086 (BUF_PT (XBUFFER (w->buffer))),
5088 w->start_at_line_beg = 1;
5093 FRAME_ROOT_WINDOW (f) = config->root_window;
5094 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5095 then calls do_switch_frame() below to select the frame that was
5096 recorded in the window config as being selected.
5098 Instead, we don't ever change the selected frame, and either
5099 call Fselect_window() below if the window config's frame is
5100 currently selected, or just set the selected window of the
5101 window config's frame. */
5103 /* Set the frame height to the value it had before this function. */
5104 if (previous_frame_height != FRAME_HEIGHT (f)
5105 || previous_frame_width != FRAME_WIDTH (f))
5106 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5108 /* If restoring in the current frame make the window current,
5109 otherwise just update the frame selected_window slot to be
5110 the restored current_window. */
5111 if (f == selected_frame ())
5113 /* When using `pop-window-configuration', often the minibuffer
5114 ends up as the selected window even though it's not active ...
5115 I really don't know the cause of this, but it should never
5116 happen. This kludge should fix it.
5118 #### Find out why this is really going wrong. */
5119 if (!minibuf_level &&
5120 MINI_WINDOW_P (XWINDOW (config->current_window)))
5121 Fselect_window (Fnext_window (config->current_window,
5125 Fselect_window (config->current_window, Qnil);
5126 if (!NILP (new_current_buffer))
5127 Fset_buffer (new_current_buffer);
5129 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5132 set_frame_selected_window (f, config->current_window);
5135 old_window_config = Qnil; /* Warning suppression */
5137 /* Restore the minimum heights recorded in the configuration. */
5138 window_min_height = config->min_height;
5139 window_min_width = config->min_width;
5142 /* see above comment */
5143 /* Fselect_window will have made f the selected frame, so we
5144 reselect the proper frame here. Fhandle_switch_frame will change the
5145 selected window too, but that doesn't make the call to
5146 Fselect_window above totally superfluous; it still sets f's
5148 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5149 do_switch_frame (config->selected_frame, Qnil, 0);
5152 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5154 if (FRAME_LIVE_P (f))
5156 /* Do this before calling recompute_all_cached_specifiers_in_window()
5157 so that things like redisplay_redraw_cursor() won't abort due
5158 to no window mirror present. */
5159 f->mirror_dirty = 1;
5161 config = XWINDOW_CONFIGURATION (old_window_config);
5162 for (k = 0; k < config->saved_windows_count; k++)
5164 p = SAVED_WINDOW_N (config, k);
5165 w = XWINDOW (p->window);
5166 /* Remember, we set w->config_mark on all currently visible
5167 windows, and reset it on all newly visible windows.
5168 Any windows still marked need to be deleted. */
5171 mark_window_as_deleted (w);
5176 /* We just potentially changed the window's buffer and
5177 potentially turned a dead window into a live one,
5178 so we need to recompute the cached specifier values. */
5179 recompute_all_cached_specifiers_in_window (w);
5184 /* Now restore things, when everything else if OK. */
5186 unbind_to (specpdl_count, Qnil);
5193 /* Mark all subwindows of a window as deleted. The argument
5194 W is actually the subwindow tree of the window in question. */
5197 delete_all_subwindows (struct window *w)
5199 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5200 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5201 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5203 mark_window_as_deleted (w);
5208 count_windows (struct window *window)
5211 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5212 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5213 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5217 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5220 for (j = 0; j < lim; j++)
5222 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5226 return 0; /* suppress compiler warning */
5230 save_window_save (Lisp_Object window, struct window_config *config, int i)
5234 for (; !NILP (window); window = w->next)
5236 struct saved_window *p = SAVED_WINDOW_N (config, i);
5238 w = XWINDOW (window);
5241 p->buffer = w->buffer;
5242 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5243 WINDOW_TOP (p) = WINDOW_TOP (w);
5244 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5245 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5246 p->hscroll = w->hscroll;
5247 p->modeline_hscroll = w->modeline_hscroll;
5249 #define WINDOW_SLOT(slot, compare) p->slot = w->slot;
5250 #include "winslots.h"
5252 if (!NILP (w->buffer))
5254 /* Save w's value of point in the window configuration.
5255 If w is the selected window, then get the value of point
5256 from the buffer; pointm is garbage in the selected window. */
5257 if (EQ (window, Fselected_window (Qnil)))
5259 p->pointm = noseeum_make_marker ();
5260 Fset_marker (p->pointm,
5261 make_int (BUF_PT (XBUFFER (w->buffer))),
5265 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5267 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5268 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5269 p->start_at_line_beg = w->start_at_line_beg;
5271 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5279 p->start_at_line_beg = 0;
5282 if (NILP (w->parent))
5283 p->parent_index = -1;
5285 p->parent_index = saved_window_index (w->parent, config, i);
5289 p->prev_index = saved_window_index (w->prev, config, i);
5290 if (!NILP (w->vchild))
5291 i = save_window_save (w->vchild, config, i);
5292 if (!NILP (w->hchild))
5293 i = save_window_save (w->hchild, config, i);
5300 /* Added to doc string:
5302 This also records the currently selected frame, and FRAME's focus
5303 redirection (see `redirect-frame-focus').
5308 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5309 Return an object representing the current window configuration of FRAME.
5310 If FRAME is nil or omitted, use the selected frame.
5311 This describes the number of windows, their sizes and current buffers,
5312 and for each displayed buffer, where display starts, and the positions of
5313 point and mark. An exception is made for point in the current buffer:
5314 its value is -not- saved.
5319 struct frame *f = decode_frame (frame);
5320 struct window_config *config;
5321 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5323 if (n_windows <= countof (Vwindow_configuration_free_list))
5324 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5325 (Vwindow_configuration_free_list
5328 /* More than ten windows; just allocate directly */
5329 config = (struct window_config *)
5330 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5331 lrecord_window_configuration);
5332 XSETWINDOW_CONFIGURATION (result, config);
5334 config->frame_width = FRAME_WIDTH (f);
5335 config->frame_height = FRAME_HEIGHT (f);
5336 config->current_window = FRAME_SELECTED_WINDOW (f);
5337 XSETBUFFER (config->current_buffer, current_buffer);
5338 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5339 config->root_window = FRAME_ROOT_WINDOW (f);
5340 config->min_height = window_min_height;
5341 config->min_width = window_min_width;
5342 config->saved_windows_count = n_windows;
5343 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5348 save_window_excursion_unwind (Lisp_Object window_config)
5350 Lisp_Object val = Fset_window_configuration (window_config);
5351 free_window_configuration (window_config);
5355 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5356 Execute body, preserving window sizes and contents.
5357 Restores which buffer appears in which window, where display starts,
5358 as well as the current buffer.
5359 Does not restore the value of point in current buffer.
5363 /* This function can GC */
5365 int speccount = specpdl_depth ();
5367 record_unwind_protect (save_window_excursion_unwind,
5368 Fcurrent_window_configuration (Qnil));
5369 val = Fprogn (args);
5370 return unbind_to (speccount, val);
5375 /* This is short and simple in elisp, but... it was written to debug
5376 problems purely on the C side. That is where we need to call it so
5379 debug_print_window (Lisp_Object window, int level)
5382 Lisp_Object child = Fwindow_first_vchild (window);
5385 child = Fwindow_first_hchild (window);
5387 for (i = level; i > 0; i--)
5388 putc ('\t', stderr);
5390 fputs ("#<window", stderr);
5392 Lisp_Object buffer = XWINDOW (window)->buffer;
5393 if (!NILP (buffer) && BUFFERP (buffer))
5394 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5396 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5398 while (!NILP (child))
5400 debug_print_window (child, level + 1);
5401 child = Fwindow_next_child (child);
5405 void debug_print_windows (struct frame *f);
5407 debug_print_windows (struct frame *f)
5409 debug_print_window (f->root_window, 0);
5410 putc ('\n', stderr);
5412 #endif /* DEBUG_XEMACS */
5415 /************************************************************************/
5416 /* initialization */
5417 /************************************************************************/
5420 syms_of_window (void)
5422 defsymbol (&Qwindowp, "windowp");
5423 defsymbol (&Qwindow_live_p, "window-live-p");
5424 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5425 defsymbol (&Qscroll_up, "scroll-up");
5426 defsymbol (&Qscroll_down, "scroll-down");
5427 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5428 defsymbol (&Qdisplay_buffer, "display-buffer");
5430 #ifdef MEMORY_USAGE_STATS
5431 defsymbol (&Qface_cache, "face-cache");
5432 defsymbol (&Qglyph_cache, "glyph-cache");
5433 defsymbol (&Qline_start_cache, "line-start-cache");
5434 #ifdef HAVE_SCROLLBARS
5435 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5437 defsymbol (&Qother_redisplay, "other-redisplay");
5438 /* Qother in general.c */
5441 DEFSUBR (Fselected_window);
5442 DEFSUBR (Fminibuffer_window);
5443 DEFSUBR (Fwindow_minibuffer_p);
5445 DEFSUBR (Fwindow_live_p);
5446 DEFSUBR (Fwindow_first_hchild);
5447 DEFSUBR (Fwindow_first_vchild);
5448 DEFSUBR (Fwindow_next_child);
5449 DEFSUBR (Fwindow_previous_child);
5450 DEFSUBR (Fwindow_parent);
5451 DEFSUBR (Fwindow_lowest_p);
5452 DEFSUBR (Fwindow_highest_p);
5453 DEFSUBR (Fwindow_leftmost_p);
5454 DEFSUBR (Fwindow_rightmost_p);
5455 DEFSUBR (Fpos_visible_in_window_p);
5456 DEFSUBR (Fwindow_buffer);
5457 DEFSUBR (Fwindow_frame);
5458 DEFSUBR (Fwindow_height);
5459 DEFSUBR (Fwindow_displayed_height);
5460 DEFSUBR (Fwindow_width);
5461 DEFSUBR (Fwindow_pixel_height);
5462 DEFSUBR (Fwindow_pixel_width);
5463 DEFSUBR (Fwindow_text_area_pixel_height);
5464 DEFSUBR (Fwindow_displayed_text_pixel_height);
5465 DEFSUBR (Fwindow_text_area_pixel_width);
5466 DEFSUBR (Fwindow_hscroll);
5467 #ifdef MODELINE_IS_SCROLLABLE
5468 DEFSUBR (Fmodeline_hscroll);
5469 DEFSUBR (Fset_modeline_hscroll);
5470 #endif /* MODELINE_IS_SCROLLABLE */
5471 #if 0 /* bogus FSF crock */
5472 DEFSUBR (Fwindow_redisplay_end_trigger);
5473 DEFSUBR (Fset_window_redisplay_end_trigger);
5475 DEFSUBR (Fset_window_hscroll);
5476 DEFSUBR (Fwindow_pixel_edges);
5477 DEFSUBR (Fwindow_text_area_pixel_edges);
5478 DEFSUBR (Fwindow_point);
5479 DEFSUBR (Fwindow_start);
5480 DEFSUBR (Fwindow_end);
5481 DEFSUBR (Fset_window_point);
5482 DEFSUBR (Fset_window_start);
5483 DEFSUBR (Fwindow_dedicated_p);
5484 DEFSUBR (Fset_window_dedicated_p);
5485 DEFSUBR (Fnext_window);
5486 DEFSUBR (Fprevious_window);
5487 DEFSUBR (Fnext_vertical_window);
5488 DEFSUBR (Fother_window);
5489 DEFSUBR (Fget_lru_window);
5490 DEFSUBR (Fget_largest_window);
5491 DEFSUBR (Fget_buffer_window);
5492 DEFSUBR (Fwindow_left_margin_pixel_width);
5493 DEFSUBR (Fwindow_right_margin_pixel_width);
5494 DEFSUBR (Fdelete_other_windows);
5495 DEFSUBR (Fdelete_windows_on);
5496 DEFSUBR (Freplace_buffer_in_windows);
5497 DEFSUBR (Fdelete_window);
5498 DEFSUBR (Fset_window_buffer);
5499 DEFSUBR (Fselect_window);
5500 DEFSUBR (Fsplit_window);
5501 DEFSUBR (Fenlarge_window);
5502 DEFSUBR (Fenlarge_window_pixels);
5503 DEFSUBR (Fshrink_window);
5504 DEFSUBR (Fshrink_window_pixels);
5505 DEFSUBR (Fscroll_up);
5506 DEFSUBR (Fscroll_down);
5507 DEFSUBR (Fscroll_left);
5508 DEFSUBR (Fscroll_right);
5509 DEFSUBR (Fother_window_for_scrolling);
5510 DEFSUBR (Fscroll_other_window);
5511 DEFSUBR (Fcenter_to_window_line);
5512 DEFSUBR (Fmove_to_window_line);
5513 #ifdef MEMORY_USAGE_STATS
5514 DEFSUBR (Fwindow_memory_usage);
5516 DEFSUBR (Fwindow_configuration_p);
5517 DEFSUBR (Fset_window_configuration);
5518 DEFSUBR (Fcurrent_window_configuration);
5519 DEFSUBR (Fsave_window_excursion);
5523 vars_of_window (void)
5525 /* Make sure all windows get marked */
5526 minibuf_window = Qnil;
5527 staticpro (&minibuf_window);
5529 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5530 *Non-nil means to scroll if point lands on a line which is clipped.
5532 scroll_on_clipped_lines = 1;
5534 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5535 See `temp-buffer-show-function'.
5537 Vtemp_buffer_show_hook = Qnil;
5539 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5540 Non-nil means call as function to display a help buffer.
5541 The function is called with one argument, the buffer to be displayed.
5542 Used by `with-output-to-temp-buffer'.
5543 If this function is used, then it must do the entire job of showing
5544 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5546 Vtemp_buffer_show_function = Qnil;
5548 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5549 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5551 Vminibuffer_scroll_window = Qnil;
5553 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5554 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5556 Vother_window_scroll_buffer = Qnil;
5558 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5559 *Number of lines of continuity when scrolling by screenfuls.
5561 next_screen_context_lines = 2;
5563 DEFVAR_INT ("window-min-height", &window_min_height /*
5564 *Delete any window less than this tall (including its modeline).
5566 window_min_height = 4;
5568 DEFVAR_INT ("window-min-width", &window_min_width /*
5569 *Delete any window less than this wide.
5571 window_min_width = 10;
5576 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5578 Vwindow_configuration_free_list[i] =
5579 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5580 lrecord_window_configuration);
5581 staticpro (&Vwindow_configuration_free_list[i]);
5587 specifier_vars_of_window (void)
5589 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5590 *How thick to draw 3D shadows around modelines.
5591 If this is set to 0, modelines will be the traditional 2D. Sizes above
5592 10 will be accepted but the maximum thickness that will be drawn is 10.
5593 This is a specifier; use `set-specifier' to change it.
5595 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5596 /* The initial value for modeline-shadow-thickness is 2, but if the
5597 user removes all specifications we provide a fallback value of 0,
5598 which is probably what was expected. */
5599 set_specifier_fallback (Vmodeline_shadow_thickness,
5600 list1 (Fcons (Qnil, Qzero)));
5601 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5603 set_specifier_caching (Vmodeline_shadow_thickness,
5604 slot_offset (struct window,
5605 modeline_shadow_thickness),
5606 modeline_shadow_thickness_changed,
5609 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5610 *Whether the modeline should be displayed.
5611 This is a specifier; use `set-specifier' to change it.
5613 Vhas_modeline_p = Fmake_specifier (Qboolean);
5614 set_specifier_fallback (Vhas_modeline_p,
5615 list1 (Fcons (Qnil, Qt)));
5616 set_specifier_caching (Vhas_modeline_p,
5617 slot_offset (struct window,
5619 /* #### It's strange that we need a special
5620 flag to indicate that the shadow-thickness
5621 has changed, but not one to indicate that
5622 the modeline has been turned off or on. */
5623 some_window_value_changed,
5626 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5627 &Vvertical_divider_always_visible_p /*
5628 *Should XEmacs always display vertical dividers between windows.
5630 When this is non-nil, vertical dividers are always shown, and are
5631 draggable. When it is nil, vertical dividers are shown only when
5632 there are no scrollbars in between windows, and are not draggable.
5634 This is a specifier; use `set-specifier' to change it.
5636 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5637 set_specifier_fallback (Vvertical_divider_always_visible_p,
5638 list1 (Fcons (Qnil, Qt)));
5639 set_specifier_caching (Vvertical_divider_always_visible_p,
5640 slot_offset (struct window,
5641 vertical_divider_always_visible_p),
5642 vertical_divider_changed_in_window,
5645 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5646 *How thick to draw 3D shadows around vertical dividers.
5647 This is a specifier; use `set-specifier' to change it.
5649 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5650 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5651 list1 (Fcons (Qnil, Qzero)));
5652 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5654 set_specifier_caching (Vvertical_divider_shadow_thickness,
5655 slot_offset (struct window,
5656 vertical_divider_shadow_thickness),
5657 vertical_divider_changed_in_window,
5659 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5660 *The width of the vertical dividers, not including shadows.
5662 For TTY windows, divider line is always one character wide. When
5663 instance of this specifier is zero in a TTY window, no divider is
5664 drawn at all between windows. When non-zero, a one character wide
5665 divider is displayed.
5667 This is a specifier; use `set-specifier' to change it.
5670 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5672 Lisp_Object fb = Qnil;
5674 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
5676 #ifdef HAVE_X_WINDOWS
5677 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5679 #ifdef HAVE_MS_WINDOWS
5680 /* #### This should be made magic and made to obey system settings */
5681 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5683 set_specifier_fallback (Vvertical_divider_line_width, fb);
5685 set_specifier_caching (Vvertical_divider_line_width,
5686 slot_offset (struct window,
5687 vertical_divider_line_width),
5688 vertical_divider_changed_in_window,
5691 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5692 *How much space to leave around the vertical dividers.
5694 In TTY windows, spacing is always zero, and the value of this
5695 specifier is ignored.
5697 This is a specifier; use `set-specifier' to change it.
5699 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5701 Lisp_Object fb = Qnil;
5703 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5705 #ifdef HAVE_X_WINDOWS
5706 /* #### 3D dividers look great on MS Windows with spacing = 0.
5707 Should not the same value be the fallback under X? - kkm */
5708 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
5710 #ifdef HAVE_MS_WINDOWS
5711 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
5713 set_specifier_fallback (Vvertical_divider_spacing, fb);
5715 set_specifier_caching (Vvertical_divider_spacing,
5716 slot_offset (struct window,
5717 vertical_divider_spacing),
5718 vertical_divider_changed_in_window,