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), XINT (pos));
1641 w->redo_modeline = 1;
1642 SET_LAST_MODIFIED (w, 0);
1643 SET_LAST_FACECHANGE (w);
1645 MARK_WINDOWS_CHANGED (w);
1650 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1651 Return WINDOW's dedicated object, usually t or nil.
1652 See also `set-window-dedicated-p'.
1656 return decode_window (window)->dedicated;
1659 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1660 Control whether WINDOW is dedicated to the buffer it displays.
1661 If it is dedicated, Emacs will not automatically change
1662 which buffer appears in it.
1663 The second argument is the new value for the dedication flag;
1668 struct window *w = decode_window (window);
1670 w->dedicated = NILP (arg) ? Qnil : Qt;
1672 return w->dedicated;
1675 /* FSFmacs has window-display-table here. We have display table as a
1679 /* Record info on buffer window w is displaying
1680 when it is about to cease to display that buffer. */
1682 unshow_buffer (struct window *w)
1684 Lisp_Object buf = w->buffer;
1686 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1689 /* FSF disables this check, so I'll do it too. I hope it won't
1690 break things. --ben */
1692 if (w == XWINDOW (Fselected_window (Qnil))
1693 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1694 /* Do this except when the selected window's buffer
1695 is being removed from some other window. */
1697 /* last_window_start records the start position that this buffer
1698 had in the last window to be disconnected from it.
1699 Now that this statement is unconditional,
1700 it is possible for the buffer to be displayed in the
1701 selected window, while last_window_start reflects another
1702 window which was recently showing the same buffer.
1703 Some people might say that might be a good thing. Let's see. */
1704 XBUFFER (buf)->last_window_start =
1705 marker_position (w->start[CURRENT_DISP]);
1707 /* Point in the selected window's buffer
1708 is actually stored in that buffer, and the window's pointm isn't used.
1709 So don't clobber point in that buffer. */
1710 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1712 struct buffer *b= XBUFFER (buf);
1713 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1714 marker_position (w->pointm[CURRENT_DISP]),
1719 /* Put REPLACEMENT into the window structure in place of OLD. */
1721 replace_window (Lisp_Object old, Lisp_Object replacement)
1724 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1726 /* If OLD is its frame's root_window, then replacement is the new
1727 root_window for that frame. */
1729 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1730 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1732 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1733 WINDOW_TOP (p) = WINDOW_TOP (o);
1734 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1735 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1737 p->next = tem = o->next;
1739 XWINDOW (tem)->prev = replacement;
1741 p->prev = tem = o->prev;
1743 XWINDOW (tem)->next = replacement;
1745 p->parent = tem = o->parent;
1748 if (EQ (XWINDOW (tem)->vchild, old))
1749 XWINDOW (tem)->vchild = replacement;
1750 if (EQ (XWINDOW (tem)->hchild, old))
1751 XWINDOW (tem)->hchild = replacement;
1754 /* #### Here, if replacement is a vertical combination
1755 and so is its new parent, we should make replacement's
1756 children be children of that parent instead. */
1759 /* we're deleting W; set the structure of W to indicate this. */
1762 mark_window_as_deleted (struct window *w)
1765 (while t (split-window) (delete-window))
1766 we end up with a tree of deleted windows which are all connected
1767 through the `next' slot. This might not seem so bad, as they're
1768 deleted, and will presumably be GCed - but if even *one* of those
1769 windows is still being pointed to, by the user, or by a window
1770 configuration, then *all* of those windows stick around.
1772 Since the window-configuration code doesn't need any of the
1773 pointers to other windows (they are all recreated from the
1774 window-config data), we set them all to nil so that we
1775 are able to collect more actual garbage.
1785 /* Free the extra data structures attached to windows immediately so
1786 they don't sit around consuming excess space. They will be
1787 reinitialized by the window-configuration code as necessary. */
1788 finalize_window ((void *) w, 0);
1791 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1792 Remove WINDOW from the display. Default is selected window.
1793 If window is the only one on the frame, the frame is destroyed.
1794 Normally, you cannot delete the last non-minibuffer-only frame (you must
1795 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1796 second argument FORCE is non-nil, you can delete the last frame. (This
1797 will automatically call `save-buffers-kill-emacs'.)
1801 /* This function can GC if this is the only window in the frame */
1809 /* Note: this function is called by other C code on non-leaf
1812 /* Do the equivalent of decode_window() but don't error out on
1813 deleted window; it's OK to delete an already-deleted window. */
1815 window = Fselected_window (Qnil);
1817 CHECK_WINDOW (window);
1818 w = XWINDOW (window);
1820 /* It's okay to delete an already-deleted window. */
1821 if (! WINDOW_LIVE_P (w))
1824 frame = WINDOW_FRAME (w);
1826 d = XDEVICE (FRAME_DEVICE (f));
1828 if (TOP_LEVEL_WINDOW_P (w))
1830 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1831 /* this frame isn't fully initialized yet; don't blow up. */
1834 if (MINI_WINDOW_P (XWINDOW (window)))
1835 error ("Attempt to delete the minibuffer window");
1837 /* It has been suggested that it's a good thing for C-x 0 to have this
1838 behavior, but not such a good idea for #'delete-window to have it.
1839 Maybe C-x 0 should be bound to something else, or maybe frame
1840 deletion should only happen when this is called interactively.
1842 delete_frame_internal (f, !NILP (force), 0, 0);
1846 /* At this point, we know the window has a parent. */
1848 par = XWINDOW (parent);
1850 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1852 /* Are we trying to delete any frame's selected window?
1853 Note that we could be dealing with a non-leaf window
1854 where the selected window is one of our children.
1855 So, we check by scanning all the ancestors of the
1856 frame's selected window and comparing each one with
1859 Lisp_Object pwindow;
1861 pwindow = FRAME_SELECTED_WINDOW (f);
1863 while (!NILP (pwindow))
1865 if (EQ (window, pwindow))
1867 pwindow = XWINDOW (pwindow)->parent;
1870 if (EQ (window, pwindow))
1872 /* OK, we found it. */
1873 Lisp_Object alternative;
1874 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1876 /* If we're about to delete the selected window on the
1877 selected frame, then we should use Fselect_window to select
1878 the new window. On the other hand, if we're about to
1879 delete the selected window on any other frame, we shouldn't do
1880 anything but set the frame's selected_window slot. */
1881 if (EQ (frame, Fselected_frame (Qnil)))
1882 Fselect_window (alternative, Qnil);
1884 set_frame_selected_window (f, alternative);
1888 /* w->buffer is nil in a non-leaf window; in this case,
1889 get rid of the markers we maintain that point into that buffer. */
1890 if (!NILP (w->buffer))
1893 unchain_marker (w->pointm[CURRENT_DISP]);
1894 unchain_marker (w->pointm[DESIRED_DISP]);
1895 unchain_marker (w->pointm[CMOTION_DISP]);
1896 unchain_marker (w->start[CURRENT_DISP]);
1897 unchain_marker (w->start[DESIRED_DISP]);
1898 unchain_marker (w->start[CMOTION_DISP]);
1899 unchain_marker (w->sb_point);
1900 /* This breaks set-window-configuration if windows in the saved
1901 configuration get deleted and multiple frames are in use. */
1902 /* w->buffer = Qnil; */
1905 /* close up the hole in the sibling list */
1906 if (!NILP (w->next))
1907 XWINDOW (w->next)->prev = w->prev;
1908 if (!NILP (w->prev))
1909 XWINDOW (w->prev)->next = w->next;
1910 if (EQ (window, par->hchild))
1911 par->hchild = w->next;
1912 if (EQ (window, par->vchild))
1913 par->vchild = w->next;
1915 /* Find one of our siblings to give our space to. */
1917 Lisp_Object sib = w->prev;
1920 /* If w gives its space to its next sibling, that sibling needs
1921 to have its top/left side pulled back to where w's is.
1922 set_window_{height,width} will re-position the sibling's
1925 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1926 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1929 /* Stretch that sibling. */
1930 if (!NILP (par->vchild))
1931 set_window_pixheight
1932 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1933 if (!NILP (par->hchild))
1935 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1938 /* If parent now has only one child,
1939 put the child into the parent's place. */
1941 Lisp_Object parchild = par->hchild;
1942 if (NILP (parchild))
1943 parchild = par->vchild;
1944 if (NILP (XWINDOW (parchild)->next))
1946 replace_window (parent, parchild);
1947 mark_window_as_deleted (XWINDOW (parent));
1951 /* Since we may be deleting combination windows, we must make sure that
1952 not only W but all its children have been marked as deleted. */
1953 if (!NILP (w->hchild))
1954 delete_all_subwindows (XWINDOW (w->hchild));
1955 else if (!NILP (w->vchild))
1956 delete_all_subwindows (XWINDOW (w->vchild));
1958 mark_window_as_deleted (w);
1960 f->mirror_dirty = 1;
1965 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1966 Return next window after WINDOW in canonical ordering of windows.
1967 If omitted, WINDOW defaults to the selected window.
1969 Optional second arg MINIBUF t means count the minibuffer window even
1970 if not active. MINIBUF nil or omitted means count the minibuffer iff
1971 it is active. MINIBUF neither t nor nil means not to count the
1972 minibuffer even if it is active.
1974 Several frames may share a single minibuffer; if the minibuffer
1975 counts, all windows on all frames that share that minibuffer count
1976 too. Therefore, `next-window' can be used to iterate through the
1977 set of windows even when the minibuffer is on another frame. If the
1978 minibuffer does not count, only windows from WINDOW's frame count.
1980 Optional third arg ALL-FRAMES t means include windows on all frames.
1981 ALL-FRAMES nil or omitted means cycle within the frames as specified
1982 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1983 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1984 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1985 Anything else means restrict to WINDOW's frame.
1987 Optional fourth argument CONSOLE controls which consoles or devices the
1988 returned window may be on. If CONSOLE is a console, return windows only
1989 on that console. If CONSOLE is a device, return windows only on that
1990 device. If CONSOLE is a console type, return windows only on consoles
1991 of that type. If CONSOLE is 'window-system, return any windows on any
1992 window-system consoles. If CONSOLE is nil or omitted, return windows only
1993 on WINDOW's console. Otherwise, all windows are considered.
1995 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
1996 can use `next-window' to iterate through the entire cycle of acceptable
1997 windows, eventually ending up back at the window you started with.
1998 `previous-window' traverses the same cycle, in the reverse order.
2000 (window, minibuf, all_frames, console))
2003 Lisp_Object start_window;
2006 window = Fselected_window (Qnil);
2008 CHECK_LIVE_WINDOW (window);
2010 start_window = window;
2012 /* minibuf == nil may or may not include minibuffers.
2013 Decide if it does. */
2015 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2016 else if (! EQ (minibuf, Qt))
2018 /* Now minibuf can be t => count all minibuffer windows,
2019 lambda => count none of them,
2020 or a specific minibuffer window (the active one) to count. */
2022 /* all_frames == nil doesn't specify which frames to include. */
2023 if (NILP (all_frames))
2024 all_frames = (! EQ (minibuf, Qlambda)
2025 ? (FRAME_MINIBUF_WINDOW
2028 (XWINDOW (window)))))
2030 else if (EQ (all_frames, Qvisible))
2032 else if (ZEROP (all_frames))
2034 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2035 /* If all_frames is a frame and window arg isn't on that frame, just
2036 return the first window on the frame. */
2037 return frame_first_window (XFRAME (all_frames));
2038 else if (! EQ (all_frames, Qt))
2040 /* Now all_frames is t meaning search all frames,
2041 nil meaning search just current frame,
2042 visible meaning search just visible frames,
2043 0 meaning search visible and iconified frames,
2044 or a window, meaning search the frame that window belongs to. */
2046 /* Do this loop at least once, to get the next window, and perhaps
2047 again, if we hit the minibuffer and that is not acceptable. */
2050 /* Find a window that actually has a next one. This loop
2051 climbs up the tree. */
2052 while (tem = XWINDOW (window)->next, NILP (tem))
2053 if (tem = XWINDOW (window)->parent, !NILP (tem))
2055 else /* window must be minibuffer window now */
2057 /* We've reached the end of this frame.
2058 Which other frames are acceptable? */
2059 tem = WINDOW_FRAME (XWINDOW (window));
2061 if (! NILP (all_frames))
2066 tem = next_frame (tem, all_frames, console);
2067 /* In the case where the minibuffer is active,
2068 and we include its frame as well as the selected one,
2069 next_frame may get stuck in that frame.
2070 If that happens, go back to the selected frame
2071 so we can complete the cycle. */
2073 XSETFRAME (tem, selected_frame ());
2076 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2082 /* If we're in a combination window, find its first child and
2083 recurse on that. Otherwise, we've found the window we want. */
2086 if (!NILP (XWINDOW (window)->hchild))
2087 window = XWINDOW (window)->hchild;
2088 else if (!NILP (XWINDOW (window)->vchild))
2089 window = XWINDOW (window)->vchild;
2093 /* "acceptable" is the correct spelling. */
2094 /* Which windows are acceptable?
2095 Exit the loop and accept this window if
2096 this isn't a minibuffer window,
2097 or we're accepting all minibuffer windows,
2098 or this is the active minibuffer and we are accepting that one, or
2099 we've come all the way around and we're back at the original window. */
2100 while (MINI_WINDOW_P (XWINDOW (window))
2101 && ! EQ (minibuf, Qt)
2102 && ! EQ (minibuf, window)
2103 && ! EQ (window, start_window));
2108 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2109 Return the window preceding WINDOW in canonical ordering of windows.
2110 If omitted, WINDOW defaults to the selected window.
2112 Optional second arg MINIBUF t means count the minibuffer window even
2113 if not active. MINIBUF nil or omitted means count the minibuffer iff
2114 it is active. MINIBUF neither t nor nil means not to count the
2115 minibuffer even if it is active.
2117 Several frames may share a single minibuffer; if the minibuffer
2118 counts, all windows on all frames that share that minibuffer count
2119 too. Therefore, `previous-window' can be used to iterate through
2120 the set of windows even when the minibuffer is on another frame. If
2121 the minibuffer does not count, only windows from WINDOW's frame count
2123 If optional third arg ALL-FRAMES t means include windows on all frames.
2124 ALL-FRAMES nil or omitted means cycle within the frames as specified
2125 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2126 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2127 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2128 Anything else means restrict to WINDOW's frame.
2130 Optional fourth argument CONSOLE controls which consoles or devices the
2131 returned window may be on. If CONSOLE is a console, return windows only
2132 on that console. If CONSOLE is a device, return windows only on that
2133 device. If CONSOLE is a console type, return windows only on consoles
2134 of that type. If CONSOLE is 'window-system, return any windows on any
2135 window-system consoles. If CONSOLE is nil or omitted, return windows only
2136 on WINDOW's console. Otherwise, all windows are considered.
2138 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2139 can use `previous-window' to iterate through the entire cycle of acceptable
2140 windows, eventually ending up back at the window you started with.
2141 `next-window' traverses the same cycle, in the reverse order.
2143 (window, minibuf, all_frames, console))
2146 Lisp_Object start_window;
2149 window = Fselected_window (Qnil);
2151 CHECK_LIVE_WINDOW (window);
2153 start_window = window;
2155 /* minibuf == nil may or may not include minibuffers.
2156 Decide if it does. */
2158 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2159 else if (! EQ (minibuf, Qt))
2161 /* Now minibuf can be t => count all minibuffer windows,
2162 lambda => count none of them,
2163 or a specific minibuffer window (the active one) to count. */
2165 /* all_frames == nil doesn't specify which frames to include.
2166 Decide which frames it includes. */
2167 if (NILP (all_frames))
2168 all_frames = (! EQ (minibuf, Qlambda)
2169 ? (FRAME_MINIBUF_WINDOW
2172 (XWINDOW (window)))))
2174 else if (EQ (all_frames, Qvisible))
2176 else if (ZEROP (all_frames))
2178 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2179 /* If all_frames is a frame and window arg isn't on that frame, just
2180 return the first window on the frame. */
2181 return frame_first_window (XFRAME (all_frames));
2182 else if (! EQ (all_frames, Qt))
2184 /* Now all_frames is t meaning search all frames,
2185 nil meaning search just current frame,
2186 visible meaning search just visible frames,
2187 0 meaning search visible and iconified frames,
2188 or a window, meaning search the frame that window belongs to. */
2190 /* Do this loop at least once, to get the next window, and perhaps
2191 again, if we hit the minibuffer and that is not acceptable. */
2194 /* Find a window that actually has a next one. This loop
2195 climbs up the tree. */
2196 while (tem = XWINDOW (window)->prev, NILP (tem))
2197 if (tem = XWINDOW (window)->parent, !NILP (tem))
2199 else /* window must be minibuffer window now */
2201 /* We have found the top window on the frame.
2202 Which frames are acceptable? */
2203 tem = WINDOW_FRAME (XWINDOW (window));
2205 if (! NILP (all_frames))
2206 /* It's actually important that we use prev_frame here,
2207 rather than next_frame. All the windows acceptable
2208 according to the given parameters should form a ring;
2209 Fnext_window and Fprevious_window should go back and
2210 forth around the ring. If we use next_frame here,
2211 then Fnext_window and Fprevious_window take different
2212 paths through the set of acceptable windows.
2213 window_loop assumes that these `ring' requirement are
2219 tem = prev_frame (tem, all_frames, console);
2220 /* In the case where the minibuffer is active,
2221 and we include its frame as well as the selected one,
2222 next_frame may get stuck in that frame.
2223 If that happens, go back to the selected frame
2224 so we can complete the cycle. */
2226 XSETFRAME (tem, selected_frame ());
2229 /* If this frame has a minibuffer, find that window first,
2230 because it is conceptually the last window in that frame. */
2231 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2232 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2234 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2241 /* If we're in a combination window, find its first child and
2242 recurse on that. Otherwise, we've found the window we want. */
2245 if (!NILP (XWINDOW (window)->hchild))
2246 window = XWINDOW (window)->hchild;
2247 else if (!NILP (XWINDOW (window)->vchild))
2248 window = XWINDOW (window)->vchild;
2250 while (tem = XWINDOW (window)->next, !NILP (tem))
2254 /* Which windows are acceptable?
2255 Exit the loop and accept this window if
2256 this isn't a minibuffer window,
2257 or we're accepting all minibuffer windows,
2258 or this is the active minibuffer and we are accepting that one, or
2259 we've come all the way around and we're back at the original window. */
2260 while (MINI_WINDOW_P (XWINDOW (window))
2261 && ! EQ (minibuf, Qt)
2262 && ! EQ (minibuf, window)
2263 && ! EQ (window, start_window));
2268 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2269 Return the next window which is vertically after WINDOW.
2274 struct window *w = decode_window (window);
2275 XSETWINDOW (window, w);
2277 if (MINI_WINDOW_P (XWINDOW (window)))
2280 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2282 if (EQ (window, root))
2285 if (!NILP (XWINDOW (window)->hchild))
2286 window = XWINDOW (window)->hchild;
2287 else if (!NILP (XWINDOW (window)->vchild))
2288 window = XWINDOW (window)->vchild;
2295 if (!NILP (XWINDOW (window)->parent) &&
2296 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2298 if (!NILP (XWINDOW (window)->next))
2299 return XWINDOW (window)->next;
2301 window = XWINDOW (window)->parent;
2304 window = XWINDOW (window)->parent;
2306 while (!EQ (window, root));
2309 if (!NILP (XWINDOW (window)->hchild))
2310 window = XWINDOW (window)->hchild;
2311 else if (!NILP (XWINDOW (window)->vchild))
2312 window = XWINDOW (window)->vchild;
2317 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2318 Select the N'th different window on this frame.
2319 All windows on current frame are arranged in a cyclic order.
2320 This command selects the window N steps away in that order.
2321 A negative N moves in the opposite order.
2323 If optional argument FRAME is `visible', search all visible frames.
2324 If FRAME is 0, search all visible and iconified frames.
2325 If FRAME is t, search all frames.
2326 If FRAME is nil, search only the selected frame.
2327 If FRAME is a frame, search only that frame.
2329 Optional third argument CONSOLE controls which consoles or devices the
2330 returned window may be on. If CONSOLE is a console, return windows only
2331 on that console. If CONSOLE is a device, return windows only on that
2332 device. If CONSOLE is a console type, return windows only on consoles
2333 of that type. If CONSOLE is 'window-system, return any windows on any
2334 window-system consoles. If CONSOLE is nil or omitted, return windows only
2335 on FRAME'S console, or on the selected console if FRAME is not a frame.
2336 Otherwise, all windows are considered.
2338 (n, frame, console))
2344 w = Fselected_window (Qnil);
2349 w = Fnext_window (w, Qnil, frame, console);
2354 w = Fprevious_window (w, Qnil, frame, console);
2357 Fselect_window (w, Qnil);
2362 /* Look at all windows, performing an operation specified by TYPE
2365 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2366 frame. If FRAMES is a frame, just look at windows on that frame.
2367 If MINI is non-zero, perform the operation on minibuffer windows too.
2373 GET_BUFFER_WINDOW, /* Arg is buffer */
2374 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2375 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2376 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2378 UNSHOW_BUFFER, /* Arg is buffer */
2379 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2380 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2384 window_loop (enum window_loop type,
2389 Lisp_Object console)
2391 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2393 Lisp_Object best_window = Qnil;
2394 Lisp_Object next_window;
2395 Lisp_Object last_window;
2396 struct frame *frame;
2397 Lisp_Object frame_arg = Qt;
2398 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2399 /* #### I think the change of "precomputing" last_window and next_window
2400 * #### catch the lossage this is meant(?) to punt on...
2403 Lisp_Object devcons, concons;
2405 /* FRAME_ARG is Qlambda to stick to one frame,
2406 Qvisible to consider all visible frames,
2409 /* If we're only looping through windows on a particular frame,
2410 FRAME points to that frame. If we're looping through windows
2411 on all frames, FRAME is 0. */
2413 if (FRAMEP (frames))
2414 frame = XFRAME (frames);
2415 else if (NILP (frames))
2416 frame = selected_frame ();
2420 frame_arg = Qlambda;
2421 else if (ZEROP (frames))
2423 else if (EQ (frames, Qvisible))
2426 DEVICE_LOOP_NO_BREAK (devcons, concons)
2428 Lisp_Object device = XCAR (devcons);
2429 Lisp_Object the_frame;
2432 XSETFRAME (the_frame, frame);
2434 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2436 if (NILP (the_frame))
2439 if (!device_matches_console_spec (the_frame, device, console))
2442 /* Pick a window to start with. */
2446 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2448 /* Figure out the last window we're going to mess with. Since
2449 Fnext_window, given the same options, is guaranteed to go in a
2450 ring, we can just use Fprevious_window to find the last one.
2452 We can't just wait until we hit the first window again,
2453 because it might be deleted. */
2455 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2460 struct window *p = XWINDOW (w);
2461 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2463 /* Pick the next window now, since some operations will delete
2464 the current window. */
2465 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2467 /* #### Still needed ?? */
2468 /* Given the outstanding quality of the rest of this code,
2469 I feel no shame about putting this piece of shit in. */
2470 if (++lose_lose >= 500)
2473 /* Note that we do not pay attention here to whether
2474 the frame is visible, since Fnext_window skips non-visible frames
2475 if that is desired, under the control of frame_arg. */
2476 if (! MINI_WINDOW_P (p)
2477 || (mini && minibuf_level > 0))
2480 case GET_BUFFER_WINDOW:
2482 if (XBUFFER (p->buffer) == XBUFFER (obj))
2487 case GET_BUFFER_WINDOW_COUNT:
2489 if (XBUFFER (p->buffer) == XBUFFER (obj))
2494 case GET_LRU_WINDOW:
2496 /* t as arg means consider only full-width windows */
2498 && !window_full_width_p (p))
2500 /* Ignore dedicated windows and minibuffers. */
2501 if (MINI_WINDOW_P (p)
2502 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2504 if (NILP (best_window)
2505 || (XINT (XWINDOW (best_window)->use_time)
2506 > XINT (p->use_time)))
2511 case GET_BUFFER_MRU_WINDOW:
2513 /* #### what about the first check in GET_LRU_WINDOW? */
2514 /* Ignore dedicated windows and minibuffers. */
2515 if (MINI_WINDOW_P (p)
2516 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2519 if (XBUFFER (p->buffer) == XBUFFER (obj))
2521 if (NILP (best_window)
2522 || (XINT (XWINDOW (best_window)->use_time)
2523 < XINT (p->use_time)))
2529 case DELETE_OTHER_WINDOWS:
2531 /* Don't delete the last window on a frame; this can
2532 happen when the minibuffer is selected, and would
2533 cause the frame to be deleted. */
2534 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2535 Fdelete_window (w, Qnil);
2539 case DELETE_BUFFER_WINDOWS:
2541 if (EQ (p->buffer, obj))
2543 struct frame *f = XFRAME (WINDOW_FRAME (p));
2545 /* If this window is dedicated, and in a frame
2546 of its own, kill the frame. */
2547 if (EQ (w, FRAME_ROOT_WINDOW (f))
2548 && !NILP (p->dedicated)
2549 && other_visible_frames (f))
2551 /* Skip the other windows on this frame.
2552 There might be one, the minibuffer! */
2553 if (! EQ (w, last_window))
2554 while (f == XFRAME (WINDOW_FRAME
2555 (XWINDOW (next_window))))
2557 /* As we go, check for the end of the
2558 loop. We mustn't start going
2559 around a second time. */
2560 if (EQ (next_window, last_window))
2565 next_window = Fnext_window (next_window,
2569 /* Now we can safely delete the frame. */
2570 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2573 /* If we're deleting the buffer displayed in
2574 the only window on the frame, find a new
2575 buffer to display there. */
2576 if (NILP (p->parent))
2578 Lisp_Object new_buffer;
2579 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2580 if (NILP (new_buffer))
2581 new_buffer = Fget_buffer_create (QSscratch);
2582 Fset_window_buffer (w, new_buffer);
2583 if (EQ (w, Fselected_window (Qnil)))
2584 Fset_buffer (p->buffer);
2587 Fdelete_window (w, Qnil);
2592 case GET_LARGEST_WINDOW:
2594 /* Ignore dedicated windows and minibuffers. */
2595 if (MINI_WINDOW_P (p)
2596 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2599 /* write the check as follows to avoid tripping
2600 error_check_window() --ben */
2601 struct window *b = NILP (best_window) ? 0 :
2602 XWINDOW (best_window);
2603 if (NILP (best_window)
2604 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2605 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2613 if (EQ (p->buffer, obj))
2615 /* Find another buffer to show in this window. */
2616 Lisp_Object another_buffer =
2617 Fother_buffer (obj, Qnil, Qnil);
2618 if (NILP (another_buffer))
2620 = Fget_buffer_create (QSscratch);
2621 /* If this window is dedicated, and in a frame
2622 of its own, kill the frame. */
2623 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2624 && !NILP (p->dedicated)
2625 && other_visible_frames (w_frame))
2627 /* Skip the other windows on this frame.
2628 There might be one, the minibuffer! */
2629 if (! EQ (w, last_window))
2630 while (w_frame == XFRAME (WINDOW_FRAME
2631 (XWINDOW (next_window))))
2633 /* As we go, check for the end of the
2634 loop. We mustn't start going
2635 around a second time. */
2636 if (EQ (next_window, last_window))
2641 next_window = Fnext_window (next_window,
2645 /* Now we can safely delete the frame. */
2646 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2651 /* Otherwise show a different buffer in the
2653 p->dedicated = Qnil;
2654 Fset_window_buffer (w, another_buffer);
2655 if (EQ (w, Fselected_window (Qnil)))
2656 Fset_buffer (p->buffer);
2666 if (EQ (w, last_window))
2673 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2676 #if 0 /* not currently used */
2679 buffer_window_count (struct buffer *b, struct frame *f)
2681 Lisp_Object buffer, frame;
2683 XSETFRAME (frame, f);
2684 XSETBUFFER (buffer, b);
2686 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2691 buffer_window_mru (struct window *w)
2693 Lisp_Object window =
2694 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2698 else if (XWINDOW (window) == w)
2707 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2708 Return the window least recently selected or used for display.
2709 If optional argument FRAME is `visible', search all visible frames.
2710 If FRAME is 0, search all visible and iconified frames.
2711 If FRAME is t, search all frames.
2712 If FRAME is nil, search only the selected frame.
2713 If FRAME is a frame, search only that frame.
2715 Optional second argument CONSOLE controls which consoles or devices the
2716 returned window may be on. If CONSOLE is a console, return windows only
2717 on that console. If CONSOLE is a device, return windows only on that
2718 device. If CONSOLE is a console type, return windows only on consoles
2719 of that type. If CONSOLE is 'window-system, return any windows on any
2720 window-system consoles. If CONSOLE is nil or omitted, return windows only
2721 on FRAME'S console, or on the selected console if FRAME is not a frame.
2722 Otherwise, all windows are considered.
2727 /* First try for a non-dedicated window that is full-width */
2728 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2729 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2732 /* Then try for any non-dedicated window */
2733 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2734 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2738 /* FSFmacs never returns a dedicated window here. If we do,
2739 it makes `display-buffer' not work right. #### All of this
2740 shit is so disgusting and awful that it needs to be rethought
2742 /* then try for a dedicated window that is full-width */
2743 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2744 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2747 /* If none of them, then all windows, dedicated or not. */
2748 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2750 /* At this point we damn well better have found something. */
2751 if (NILP (w)) abort ();
2757 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2758 Return the window largest in area.
2759 If optional argument FRAME is `visible', search all visible frames.
2760 If FRAME is 0, search all visible and iconified frames.
2761 If FRAME is t, search all frames.
2762 If FRAME is nil, search only the selected frame.
2763 If FRAME is a frame, search only that frame.
2765 Optional second argument CONSOLE controls which consoles or devices the
2766 returned window may be on. If CONSOLE is a console, return windows only
2767 on that console. If CONSOLE is a device, return windows only on that
2768 device. If CONSOLE is a console type, return windows only on consoles
2769 of that type. If CONSOLE is 'window-system, return any windows on any
2770 window-system consoles. If CONSOLE is nil or omitted, return windows only
2771 on FRAME'S console, or on the selected console if FRAME is not a frame.
2772 Otherwise, all windows are considered.
2776 /* Don't search dedicated windows because FSFmacs doesn't.
2777 This stuff is all black magic so don't try to apply common
2779 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2782 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2783 Return a window currently displaying BUFFER, or nil if none.
2784 If optional argument FRAME is `visible', search all visible frames.
2785 If optional argument FRAME is 0, search all visible and iconified frames.
2786 If FRAME is t, search all frames.
2787 If FRAME is nil, search only the selected frame.
2788 If FRAME is a frame, search only that frame.
2790 Optional third argument CONSOLE controls which consoles or devices the
2791 returned window may be on. If CONSOLE is a console, return windows only
2792 on that console. If CONSOLE is a device, return windows only on that
2793 device. If CONSOLE is a console type, return windows only on consoles
2794 of that type. If CONSOLE is 'window-system, return any windows on any
2795 window-system consoles. If CONSOLE is nil or omitted, return windows only
2796 on FRAME'S console, or on the selected console if FRAME is not a frame.
2797 Otherwise, all windows are considered.
2799 (buffer, frame, console))
2801 buffer = Fget_buffer (buffer);
2802 if (BUFFERP (buffer))
2803 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2804 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2809 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2810 but there is no sensible way to implement those functions, since
2811 you can't in general derive a window from a buffer. */
2813 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2815 Return the width in pixels of the left outside margin of window WINDOW.
2816 If WINDOW is nil, the selected window is assumed.
2820 return make_int (window_left_margin_width (decode_window (window)));
2823 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2825 Return the width in pixels of the right outside margin of window WINDOW.
2826 If WINDOW is nil, the selected window is assumed.
2830 return make_int (window_right_margin_width (decode_window (window)));
2833 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2834 Make WINDOW (or the selected window) fill its frame.
2835 Only the frame WINDOW is on is affected.
2836 This function tries to reduce display jumps
2837 by keeping the text previously visible in WINDOW
2838 in the same place on the frame. Doing this depends on
2839 the value of (window-start WINDOW), so if calling this function
2840 in a program gives strange scrolling, make sure the window-start
2841 value is reasonable when this function is called.
2845 struct window *w = decode_window (window);
2846 struct buffer *b = XBUFFER (w->buffer);
2848 int old_top = WINDOW_TOP (w);
2850 XSETWINDOW (window, w);
2852 if (MINI_WINDOW_P (w) && old_top > 0)
2853 error ("Can't expand minibuffer to full frame");
2855 /* Ignore dedicated windows. */
2856 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2858 start_pos = marker_position (w->start[CURRENT_DISP]);
2860 /* Try to minimize scrolling, by setting the window start to the
2861 point which will cause the text at the old window start to be at
2862 the same place on the frame. But don't try to do this if the
2863 window start is outside the visible portion (as might happen when
2864 the display is not current, due to typeahead). */
2865 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2866 && !MINI_WINDOW_P (w))
2868 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2870 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2872 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2874 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2876 /* We need to do this, so that the window-scroll-functions
2884 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2885 "bDelete windows on (buffer): ", /*
2886 Delete all windows showing BUFFER.
2887 Optional second argument FRAME controls which frames are affected.
2888 If nil or omitted, delete all windows showing BUFFER in any frame.
2889 If t, delete only windows showing BUFFER in the selected frame.
2890 If `visible', delete all windows showing BUFFER in any visible frame.
2891 If a frame, delete only windows showing BUFFER in that frame.
2893 Optional third argument CONSOLE controls which consoles or devices the
2894 returned window may be on. If CONSOLE is a console, return windows only
2895 on that console. If CONSOLE is a device, return windows only on that
2896 device. If CONSOLE is a console type, return windows only on consoles
2897 of that type. If CONSOLE is 'window-system, return any windows on any
2898 window-system consoles. If CONSOLE is nil or omitted, return windows only
2899 on FRAME'S console, or on the selected console if FRAME is not a frame.
2900 Otherwise, all windows are considered.
2902 (buffer, frame, console))
2904 /* This function can GC */
2905 /* FRAME uses t and nil to mean the opposite of what window_loop
2907 if (!FRAMEP (frame))
2908 frame = NILP (frame) ? Qt : Qnil;
2912 buffer = Fget_buffer (buffer);
2913 CHECK_BUFFER (buffer);
2914 /* Ignore dedicated windows. */
2915 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2920 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2921 "bReplace buffer in windows: ", /*
2922 Replace BUFFER with some other buffer in all windows showing it.
2926 /* This function can GC */
2929 buffer = Fget_buffer (buffer);
2930 CHECK_BUFFER (buffer);
2931 /* Ignore dedicated windows. */
2932 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2937 /* The smallest acceptable dimensions for a window. Anything smaller
2938 might crash Emacs. */
2939 #define MIN_SAFE_WINDOW_WIDTH (2)
2940 #define MIN_SAFE_WINDOW_HEIGHT (2)
2942 /* Make sure that window_min_height and window_min_width are
2943 not too small; if they are, set them to safe minima. */
2946 check_min_window_sizes (void)
2948 /* Smaller values might permit a crash. */
2949 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2950 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2951 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2952 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2955 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2956 minimum allowable size. */
2958 check_frame_size (struct frame *frame, int *rows, int *cols)
2960 /* For height, we have to see whether the frame has a minibuffer, and
2961 whether it wants a modeline. */
2963 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2964 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2965 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2967 if (*rows < min_height)
2969 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2970 *cols = MIN_SAFE_WINDOW_WIDTH;
2973 /* Normally the window is deleted if it gets too small.
2974 nodelete nonzero means do not do this.
2975 (The caller should check later and do so if appropriate) */
2977 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
2980 struct window *w = XWINDOW (window);
2981 struct frame *f = XFRAME (w->frame);
2983 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
2984 Lisp_Object child, minor_kid, major_kid;
2987 int defheight, defwidth;
2989 /* #### This is very likely incorrect and instead the char_to_pixel_
2990 functions should be called. */
2991 default_face_height_and_width (window, &defheight, &defwidth);
2992 line_size = (set_height ? defheight : defwidth);
2994 check_min_window_sizes ();
2996 minsize = (set_height ? window_min_height : window_min_width);
2997 minsize *= line_size;
3000 && !TOP_LEVEL_WINDOW_P (w)
3001 && new_pixsize < minsize)
3003 Fdelete_window (window, Qnil);
3007 SET_LAST_MODIFIED (w, 0);
3008 SET_LAST_FACECHANGE (w);
3009 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3012 WINDOW_HEIGHT (w) = new_pixsize;
3013 major_kid = w->vchild;
3014 minor_kid = w->hchild;
3018 WINDOW_WIDTH (w) = new_pixsize;
3019 major_kid = w->hchild;
3020 minor_kid = w->vchild;
3023 if (!NILP (minor_kid))
3025 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3028 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3030 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3032 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3035 else if (!NILP (major_kid))
3037 int last_pos, last_old_pos, pos, old_pos, first;
3038 int pixel_adj_left = new_pixsize - old_pixsize;
3039 int div_val = old_pixsize << 1;
3042 * Previously we bailed out here if there was no size change.
3043 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3044 * toolbar appears or disappears, windows may not change size,
3045 * but their top and left coordinates need to be updated.
3047 * So we don't bail until after the loop below.
3050 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3053 for (child = major_kid; !NILP (child); child = c->next)
3055 c = XWINDOW (child);
3059 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3060 WINDOW_TOP (c) = last_pos;
3064 old_pos = last_old_pos + WINDOW_WIDTH (c);
3065 WINDOW_LEFT (c) = last_pos;
3068 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3069 /* All but the last window should have a height which is
3070 a multiple of the default line height. */
3071 if (!NILP (c->next))
3072 pos = (pos / line_size) * line_size;
3074 /* Avoid confusion: don't delete child if it becomes too small */
3075 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3077 last_pos = pos + first;
3078 last_old_pos = old_pos;
3081 /* Sometimes we may get called with our old size. In that case
3082 we don't need to do anything else. */
3083 if (!pixel_adj_left)
3086 /* Now delete any children that became too small. */
3088 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3091 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3093 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3098 /* Set the height of WINDOW and all its inferiors. */
3100 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3102 set_window_pixsize (window, new_pixheight, nodelete, 1);
3105 /* Recursively set width of WINDOW and its inferiors. */
3107 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3109 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3113 static int window_select_count;
3115 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3116 Make WINDOW display BUFFER as its contents.
3117 BUFFER can be a buffer or buffer name.
3122 struct window *w = decode_window (window);
3124 buffer = Fget_buffer (buffer);
3125 CHECK_BUFFER (buffer);
3127 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3128 error ("Attempt to display deleted buffer");
3132 error ("Window is deleted");
3134 /* While this seems like a logical thing to do, it causes problems
3135 because of saved window configurations. It is possible for a
3136 buffer to get restored into a window in which it is already being
3137 displayed, but start and point are actually at completely
3138 different locations. So we let this function complete fully and
3139 it will then make sure redisplay correctly updates things.
3141 #### This is a kludge. The correct approach is not to do this
3142 but to fix set-window-configuration. */
3144 else if (EQ (tem, buffer))
3147 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3148 is first being set up. */
3150 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3151 error ("Window is dedicated to buffer %s",
3152 XSTRING_DATA (XBUFFER (tem)->name));
3158 w->window_end_pos[CURRENT_DISP] = 0;
3160 w->modeline_hscroll = 0;
3161 Fset_marker (w->pointm[CURRENT_DISP],
3162 make_int (BUF_PT (XBUFFER (buffer))),
3164 set_marker_restricted (w->start[CURRENT_DISP],
3165 make_int (XBUFFER (buffer)->last_window_start),
3167 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3168 /* set start_at_line_beg correctly. GE */
3169 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3170 XBUFFER (buffer)->last_window_start);
3171 w->force_start = 0; /* Lucid fix */
3172 SET_LAST_MODIFIED (w, 1);
3173 SET_LAST_FACECHANGE (w);
3174 MARK_WINDOWS_CHANGED (w);
3175 recompute_all_cached_specifiers_in_window (w);
3176 if (EQ (window, Fselected_window (Qnil)))
3178 Fset_buffer (buffer);
3183 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3184 Select WINDOW. Most editing will apply to WINDOW's buffer.
3185 The main editor command loop selects the buffer of the selected window
3186 before each command.
3188 With non-nil optional argument `norecord', do not modify the
3189 global or per-frame buffer ordering.
3194 Lisp_Object old_selected_window = Fselected_window (Qnil);
3196 CHECK_LIVE_WINDOW (window);
3197 w = XWINDOW (window);
3199 /* we have already caught dead-window errors */
3200 if (!NILP (w->hchild) || !NILP (w->vchild))
3201 error ("Trying to select non-leaf window");
3203 w->use_time = make_int (++window_select_count);
3204 if (EQ (window, old_selected_window))
3207 /* deselect the old window, if it exists (it might not exist if
3208 the selected device has no frames, which occurs at startup) */
3209 if (!NILP (old_selected_window))
3211 struct window *ow = XWINDOW (old_selected_window);
3213 Fset_marker (ow->pointm[CURRENT_DISP],
3214 make_int (BUF_PT (XBUFFER (ow->buffer))),
3217 MARK_WINDOWS_CHANGED (ow);
3220 /* now select the window's frame */
3221 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3223 select_frame_1 (WINDOW_FRAME (w));
3225 /* also select the window's buffer */
3226 if (NILP (norecord))
3227 Frecord_buffer (w->buffer);
3228 Fset_buffer (w->buffer);
3230 /* Go to the point recorded in the window.
3231 This is important when the buffer is in more
3232 than one window. It also matters when
3233 redisplay_window has altered point after scrolling,
3234 because it makes the change only in the window. */
3236 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3237 if (new_point < BUF_BEGV (current_buffer))
3238 new_point = BUF_BEGV (current_buffer);
3239 else if (new_point > BUF_ZV (current_buffer))
3240 new_point = BUF_ZV (current_buffer);
3242 BUF_SET_PT (current_buffer, new_point);
3245 MARK_WINDOWS_CHANGED (w);
3251 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3252 Lisp_Object override_frame)
3254 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3258 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3260 /* This function can GC */
3263 struct buffer *b = XBUFFER (buf);
3265 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3266 widen_buffer (b, 0);
3267 BUF_SET_PT (b, BUF_BEG (b));
3269 if (!NILP (Vtemp_buffer_show_function))
3270 call1 (Vtemp_buffer_show_function, buf);
3273 window = display_buffer (buf, Qnil, same_frame);
3275 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3276 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3278 Vminibuffer_scroll_window = window;
3279 w = XWINDOW (window);
3281 w->modeline_hscroll = 0;
3282 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3283 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3284 set_marker_restricted (w->sb_point, make_int (1), buf);
3286 /* Run temp-buffer-show-hook, with the chosen window selected. */
3287 if (!preparing_for_armageddon)
3290 tem = Fboundp (Qtemp_buffer_show_hook);
3293 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3296 int count = specpdl_depth ();
3298 /* Select the window that was chosen, for running
3300 record_unwind_protect (save_window_excursion_unwind,
3301 Fcurrent_window_configuration (Qnil));
3303 Fselect_window (window, Qnil);
3304 run_hook (Qtemp_buffer_show_hook);
3305 unbind_to (count, Qnil);
3313 make_dummy_parent (Lisp_Object window)
3316 struct window *o = XWINDOW (window);
3317 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
3319 XSETWINDOW (new, p);
3320 copy_lcrecord (p, o);
3322 /* Don't copy the pointers to the line start cache or the face
3324 p->line_start_cache = Dynarr_new (line_start_cache);
3325 p->face_cachels = Dynarr_new (face_cachel);
3326 p->glyph_cachels = Dynarr_new (glyph_cachel);
3328 /* Put new into window structure in place of window */
3329 replace_window (window, new);
3337 p->start[CURRENT_DISP] = Qnil;
3338 p->start[DESIRED_DISP] = Qnil;
3339 p->start[CMOTION_DISP] = Qnil;
3340 p->pointm[CURRENT_DISP] = Qnil;
3341 p->pointm[DESIRED_DISP] = Qnil;
3342 p->pointm[CMOTION_DISP] = Qnil;
3347 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3348 Split WINDOW, putting SIZE lines in the first of the pair.
3349 WINDOW defaults to selected one and SIZE to half its size.
3350 If optional third arg HOR-FLAG is non-nil, split side by side
3351 and put SIZE columns in the first of the pair.
3353 (window, chsize, horflag))
3356 struct window *o, *p;
3362 window = Fselected_window (Qnil);
3364 CHECK_WINDOW (window);
3366 o = XWINDOW (window);
3367 f = XFRAME (WINDOW_FRAME (o));
3371 if (!NILP (horflag))
3372 /* In the new scheme, we are symmetric with respect to separators
3373 so there is no need to do weird things here. */
3375 psize = WINDOW_WIDTH (o) >> 1;
3376 size = window_pixel_width_to_char_width (o, psize, 0);
3380 psize = WINDOW_HEIGHT (o) >> 1;
3381 size = window_pixel_height_to_char_height (o, psize, 1);
3387 size = XINT (chsize);
3388 if (!NILP (horflag))
3389 psize = window_char_width_to_pixel_width (o, size, 0);
3391 psize = window_char_height_to_pixel_height (o, size, 1);
3394 if (MINI_WINDOW_P (o))
3395 error ("Attempt to split minibuffer window");
3396 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3397 error ("Attempt to split unsplittable frame");
3399 check_min_window_sizes ();
3403 if (size < window_min_height)
3404 error ("Window height %d too small (after splitting)", size);
3405 if (size + window_min_height > window_char_height (o, 1))
3406 error ("Window height %d too small (after splitting)",
3407 window_char_height (o, 1) - size);
3408 if (NILP (o->parent)
3409 || NILP (XWINDOW (o->parent)->vchild))
3411 make_dummy_parent (window);
3412 reset_face_cachels (XWINDOW (window));
3414 XWINDOW (new)->vchild = window;
3415 XFRAME (o->frame)->mirror_dirty = 1;
3420 if (size < window_min_width)
3421 error ("Window width %d too small (after splitting)", size);
3422 if (size + window_min_width > window_char_width (o, 0))
3423 error ("Window width %d too small (after splitting)",
3424 window_char_width (o, 0) - size);
3425 if (NILP (o->parent)
3426 || NILP (XWINDOW (o->parent)->hchild))
3428 make_dummy_parent (window);
3429 reset_face_cachels (XWINDOW (window));
3431 XWINDOW (new)->hchild = window;
3432 XFRAME (o->frame)->mirror_dirty = 1;
3436 /* Now we know that window's parent is a vertical combination
3437 if we are dividing vertically, or a horizontal combination
3438 if we are making side-by-side windows */
3440 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3441 new = allocate_window ();
3444 p->frame = o->frame;
3446 if (!NILP (p->next))
3447 XWINDOW (p->next)->prev = new;
3450 p->parent = o->parent;
3453 reset_face_cachels (p);
3454 reset_glyph_cachels (p);
3457 /* Apportion the available frame space among the two new windows */
3459 if (!NILP (horflag))
3461 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3462 WINDOW_TOP (p) = WINDOW_TOP (o);
3463 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3464 WINDOW_WIDTH (o) = psize;
3465 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3469 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3470 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3471 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3472 WINDOW_HEIGHT (o) = psize;
3473 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3476 XFRAME (p->frame)->mirror_dirty = 1;
3477 /* do this last (after the window is completely initialized and
3478 the mirror-dirty flag is set) so that specifier recomputation
3479 caused as a result of this will work properly and not abort. */
3480 Fset_window_buffer (new, o->buffer);
3485 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3486 Make the selected window ARG lines bigger.
3487 From program, optional second arg non-nil means grow sideways ARG columns,
3488 and optional third ARG specifies the window to change instead of the
3493 struct window *w = decode_window (window);
3495 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3499 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3500 Make the selected window ARG pixels bigger.
3501 From program, optional second arg non-nil means grow sideways ARG pixels,
3502 and optional third ARG specifies the window to change instead of the
3507 struct window *w = decode_window (window);
3509 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3513 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3514 Make the selected window ARG lines smaller.
3515 From program, optional second arg non-nil means shrink sideways ARG columns,
3516 and optional third ARG specifies the window to change instead of the
3522 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3527 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3528 Make the selected window ARG pixels smaller.
3529 From program, optional second arg non-nil means shrink sideways ARG pixels,
3530 and optional third ARG specifies the window to change instead of the
3536 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3542 window_pixel_height (Lisp_Object window)
3544 return WINDOW_HEIGHT (XWINDOW (window));
3548 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3549 int include_gutters_p)
3552 int defheight, defwidth;
3556 XSETWINDOW (window, w);
3558 avail_height = (pixel_height -
3559 (include_gutters_p ? 0 :
3560 window_top_gutter_height (w) +
3561 window_bottom_gutter_height (w)));
3563 default_face_height_and_width (window, &defheight, &defwidth);
3565 char_height = avail_height / defheight;
3567 /* It's the calling function's responsibility to check these values
3568 and make sure they're not out of range.
3570 #### We need to go through the calling functions and actually
3572 return max (0, char_height);
3576 window_char_height_to_pixel_height (struct window *w, int char_height,
3577 int include_gutters_p)
3580 int defheight, defwidth;
3585 XSETWINDOW (window, w);
3587 default_face_height_and_width (window, &defheight, &defwidth);
3589 avail_height = char_height * defheight;
3590 pixel_height = (avail_height +
3591 (include_gutters_p ? 0 :
3592 window_top_gutter_height (w) +
3593 window_bottom_gutter_height (w)));
3595 /* It's the calling function's responsibility to check these values
3596 and make sure they're not out of range.
3598 #### We need to go through the calling functions and actually
3600 return max (0, pixel_height);
3603 /* Return number of default lines of text can fit in the window W.
3604 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3605 horizontal scrollbar) in the space that is used for the calculation.
3608 window_char_height (struct window *w, int include_gutters_p)
3610 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3615 * Return number of lines currently displayed in window w. If
3616 * end-of-buffer is displayed then the area below end-of-buffer is assume
3617 * to be blank lines of default height.
3618 * Does not include the modeline.
3621 window_displayed_height (struct window *w)
3623 struct buffer *b = XBUFFER (w->buffer);
3624 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3626 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3628 : w->window_end_pos[CURRENT_DISP]);
3630 if (!Dynarr_length (dla))
3631 return window_char_height (w, 0);
3633 num_lines = Dynarr_length (dla);
3635 /* #### Document and assert somewhere that w->window_end_pos == -1
3636 indicates that end-of-buffer is being displayed. */
3639 struct display_line *dl = Dynarr_atp (dla, 0);
3640 int ypos1 = dl->ypos + dl->descent;
3641 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3643 int defheight, defwidth;
3645 XSETWINDOW (window, w);
3651 if (Dynarr_length (dla) == 1)
3652 ypos1 = WINDOW_TEXT_TOP (w);
3655 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3656 /* If this line is clipped then we know that there is no
3657 blank room between eob and the modeline. If we are
3658 scrolling on clipped lines just know off the clipped
3660 if (scroll_on_clipped_lines && dl->clip)
3661 return num_lines - 1;
3662 ypos1 = dl->ypos + dl->descent - dl->clip;
3666 default_face_height_and_width (window, &defheight, &defwidth);
3667 /* #### This probably needs to know about the clipping area once a
3668 final definition is decided on. */
3669 num_lines += ((ypos2 - ypos1) / defheight);
3673 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3676 if (scroll_on_clipped_lines
3677 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3685 window_pixel_width (Lisp_Object window)
3687 return WINDOW_WIDTH (XWINDOW (window));
3691 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3692 int include_margins_p)
3696 int defheight, defwidth;
3699 XSETWINDOW (window, w);
3701 avail_width = (pixel_width -
3702 window_left_gutter_width (w, 0) -
3703 window_right_gutter_width (w, 0) -
3704 (include_margins_p ? 0 : window_left_margin_width (w)) -
3705 (include_margins_p ? 0 : window_right_margin_width (w)));
3707 default_face_height_and_width (window, &defheight, &defwidth);
3709 char_width = (avail_width / defwidth);
3711 /* It's the calling function's responsibility to check these values
3712 and make sure they're not out of range.
3714 #### We need to go through the calling functions and actually
3716 return max (0, char_width);
3720 window_char_width_to_pixel_width (struct window *w, int char_width,
3721 int include_margins_p)
3725 int defheight, defwidth;
3728 XSETWINDOW (window, w);
3730 default_face_height_and_width (window, &defheight, &defwidth);
3732 avail_width = char_width * defwidth;
3733 pixel_width = (avail_width +
3734 window_left_gutter_width (w, 0) +
3735 window_right_gutter_width (w, 0) +
3736 (include_margins_p ? 0 : window_left_margin_width (w)) +
3737 (include_margins_p ? 0 : window_right_margin_width (w)));
3739 /* It's the calling function's responsibility to check these values
3740 and make sure they're not out of range.
3742 #### We need to go through the calling functions and actually
3744 return max (0, pixel_width);
3747 /* This returns the usable space which doesn't include space needed by
3748 scrollbars or divider lines. */
3750 window_char_width (struct window *w, int include_margins_p)
3752 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3756 #define MINSIZE(w) \
3758 ? window_min_width * defwidth \
3759 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3762 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3764 #define CURSIZE(w) \
3765 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3767 #define CURCHARSIZE(w) \
3768 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3770 #define MINCHARSIZE(window) \
3771 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3772 ? 1 : window_min_height)
3774 /* Unlike set_window_pixheight, this function
3775 also changes the heights of the siblings so as to
3776 keep everything consistent. */
3779 change_window_height (struct window *win, int delta, int widthflag,
3787 int (*sizefun) (Lisp_Object) = (widthflag
3788 ? window_pixel_width
3789 : window_pixel_height);
3790 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3791 ? set_window_pixwidth
3792 : set_window_pixheight);
3794 int defheight, defwidth;
3799 check_min_window_sizes ();
3801 XSETWINDOW (window, win);
3802 f = XFRAME (win->frame);
3803 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3804 error ("Won't change only window");
3806 /* #### This is very likely incorrect and instead the char_to_pixel_
3807 functions should be called. */
3808 default_face_height_and_width (window, &defheight, &defwidth);
3812 w = XWINDOW (window);
3817 error ("No other window to side of this one");
3821 ? !NILP (XWINDOW (parent)->hchild)
3822 : !NILP (XWINDOW (parent)->vchild))
3827 sizep = &CURSIZE (w);
3828 dim = CURCHARSIZE (w);
3830 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3831 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3833 if (MINI_WINDOW_P (XWINDOW (window)))
3835 else if (!NILP (parent))
3837 Fdelete_window (window, Qnil);
3843 delta *= (widthflag ? defwidth : defheight);
3848 maxdelta = ((!NILP (parent))
3849 ? (*sizefun) (parent) - *sizep
3850 : ((!NILP (w->next))
3851 ? (*sizefun) (w->next) - MINSIZE (w->next)
3852 : ((!NILP (w->prev))
3853 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3854 /* This is a frame with only one window,
3855 a minibuffer-only or a minibufferless frame. */
3858 if (delta > maxdelta)
3859 /* This case traps trying to make the minibuffer
3860 the full frame, or make the only window aside from the
3861 minibuffer the full frame. */
3868 /* #### Chuck: is this correct? */
3869 if (*sizep + delta < MINSIZE (window))
3871 Fdelete_window (window);
3877 if (!NILP (w->next) &&
3878 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3880 CURBEG (XWINDOW (w->next)) += delta;
3881 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3882 (*setsizefun) (window, *sizep + delta, 0);
3884 else if (!NILP (w->prev) &&
3885 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3887 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3888 CURBEG (w) -= delta;
3889 (*setsizefun) (window, *sizep + delta, 0);
3894 int opht = (*sizefun) (parent);
3896 /* If trying to grow this window to or beyond size of the parent,
3897 make delta1 so big that, on shrinking back down,
3898 all the siblings end up with less than one line and are deleted. */
3899 if (opht <= *sizep + delta)
3900 delta1 = opht * opht * 2;
3901 /* Otherwise, make delta1 just right so that if we add delta1
3902 lines to this window and to the parent, and then shrink
3903 the parent back to its original size, the new proportional
3904 size of this window will increase by delta. */
3906 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3908 /* Add delta1 lines or columns to this window, and to the parent,
3909 keeping things consistent while not affecting siblings. */
3910 CURSIZE (XWINDOW (parent)) = opht + delta1;
3911 (*setsizefun) (window, *sizep + delta1, 0);
3913 /* Squeeze out delta1 lines or columns from our parent,
3914 shriking this window and siblings proportionately.
3915 This brings parent back to correct size.
3916 Delta1 was calculated so this makes this window the desired size,
3917 taking it all out of the siblings. */
3918 (*setsizefun) (parent, opht, 0);
3921 SET_LAST_MODIFIED (w, 0);
3922 SET_LAST_FACECHANGE (w);
3923 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3933 /* Scroll contents of window WINDOW up N lines. */
3935 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3936 Error_behavior errb)
3938 struct window *w = XWINDOW (window);
3939 struct buffer *b = XBUFFER (w->buffer);
3940 int selected = EQ (window, Fselected_window (Qnil));
3942 Lisp_Object point, tem;
3945 point = make_int (BUF_PT (b));
3948 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3950 if (pos < BUF_BEGV (b))
3952 else if (pos > BUF_ZV (b))
3955 point = make_int (pos);
3958 /* Always set force_start so that redisplay_window will run
3959 thw window-scroll-functions. */
3962 /* #### When the fuck does this happen? I'm so glad that history has
3963 completely documented the behavior of the scrolling functions under
3964 all circumstances. */
3965 tem = Fpos_visible_in_window_p (point, window);
3968 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
3970 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
3971 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
3972 MARK_WINDOWS_CHANGED (w);
3981 n = Fprefix_numeric_value (n);
3982 value = XINT (n) * direction;
3985 return; /* someone just made a pointless call */
3989 /* If the user didn't specify how far to scroll then we have to figure it
3990 out by ourselves. */
3991 if (NILP (n) || EQ (n, Qminus))
3993 /* Going forwards is easy. If that is what we are doing then just
3994 set value and the section which handles the user specifying a
3995 positive value will work. */
3998 value = window_displayed_height (w) - next_screen_context_lines;
3999 value = (value < 1 ? 1 : value);
4002 /* Going backwards is hard. We can't use the same loop used if the
4003 user specified a negative value because we care about
4004 next_screen_context_lines. In a variable height world you don't
4005 know how many lines above you can actually be displayed and still
4006 have the context lines appear. So we leave value set to 0 and add
4007 a separate section to deal with this. */
4011 if (direction == 1 && !value)
4018 Bufpos startp, old_start;
4020 old_start = marker_position (w->start[CURRENT_DISP]);
4021 startp = vmotion (w, old_start, value, &vtarget);
4023 if (vtarget < value &&
4024 (w->window_end_pos[CURRENT_DISP] == -1
4025 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4027 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4032 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4035 w->start_at_line_beg = beginning_of_line_p (b, startp);
4036 MARK_WINDOWS_CHANGED (w);
4038 if (!point_would_be_visible (w, startp, XINT (point)))
4041 BUF_SET_PT (b, startp);
4043 set_marker_restricted (w->pointm[CURRENT_DISP],
4052 Bufpos startp, old_start;
4054 old_start = marker_position (w->start[CURRENT_DISP]);
4055 startp = vmotion (w, old_start, value, &vtarget);
4058 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4060 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4065 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4068 w->start_at_line_beg = beginning_of_line_p (b, startp);
4069 MARK_WINDOWS_CHANGED (w);
4071 if (!point_would_be_visible (w, startp, XINT (point)))
4075 if (MINI_WINDOW_P (w))
4078 new_point = start_of_last_line (w, startp);
4081 BUF_SET_PT (b, new_point);
4083 set_marker_restricted (w->pointm[CURRENT_DISP],
4084 make_int (new_point),
4089 else /* value == 0 && direction == -1 */
4091 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4093 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4099 int movement = next_screen_context_lines - 1;
4100 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4101 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4103 start_with_point_on_display_line (w, bottom,
4104 -1 - (movement - vtarget));
4106 if (startp >= old_startp)
4107 startp = vmotion (w, old_startp, -1, NULL);
4109 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4112 w->start_at_line_beg = beginning_of_line_p (b, startp);
4113 MARK_WINDOWS_CHANGED (w);
4115 if (!point_would_be_visible (w, startp, XINT (point)))
4117 Bufpos new_point = start_of_last_line (w, startp);
4120 BUF_SET_PT (b, new_point);
4122 set_marker_restricted (w->pointm[CURRENT_DISP],
4123 make_int (new_point),
4131 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4132 Scroll text of current window upward ARG lines; or near full screen if no ARG.
4133 A near full screen is `next-screen-context-lines' less than a full screen.
4134 Negative ARG means scroll downward.
4135 When calling from a program, supply a number as argument or nil.
4136 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4137 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4142 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4146 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4147 Scroll text of current window downward ARG lines; or near full screen if no ARG.
4148 A near full screen is `next-screen-context-lines' less than a full screen.
4149 Negative ARG means scroll upward.
4150 When calling from a program, supply a number as argument or nil.
4151 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4152 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4157 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4161 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4162 Return the other window for "other window scroll" commands.
4163 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4164 specifies the window.
4165 If `other-window-scroll-buffer' is non-nil, a window
4166 showing that buffer is used.
4171 Lisp_Object selected_window = Fselected_window (Qnil);
4173 if (MINI_WINDOW_P (XWINDOW (selected_window))
4174 && !NILP (Vminibuffer_scroll_window))
4175 window = Vminibuffer_scroll_window;
4176 /* If buffer is specified, scroll that buffer. */
4177 else if (!NILP (Vother_window_scroll_buffer))
4179 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4181 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4185 /* Nothing specified; look for a neighboring window on the same
4187 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4189 if (EQ (window, selected_window))
4190 /* That didn't get us anywhere; look for a window on another
4193 window = Fnext_window (window, Qnil, Qt, Qnil);
4194 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4195 && ! EQ (window, selected_window));
4198 CHECK_LIVE_WINDOW (window);
4200 if (EQ (window, selected_window))
4201 error ("There is no other window");
4206 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4207 Scroll next window upward ARG lines; or near full frame if no ARG.
4208 The next window is the one below the current one; or the one at the top
4209 if the current one is at the bottom. Negative ARG means scroll downward.
4210 When calling from a program, supply a number as argument or nil.
4212 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4213 specifies the window to scroll.
4214 If `other-window-scroll-buffer' is non-nil, scroll the window
4215 showing that buffer, popping the buffer up if necessary.
4219 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4223 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4224 Scroll selected window display ARG columns left.
4225 Default for ARG is window width minus 2.
4229 Lisp_Object window = Fselected_window (Qnil);
4230 struct window *w = XWINDOW (window);
4233 arg = make_int (window_char_width (w, 0) - 2);
4235 arg = Fprefix_numeric_value (arg);
4237 return Fset_window_hscroll (window, make_int (w->hscroll + XINT (arg)));
4240 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4241 Scroll selected window display ARG columns right.
4242 Default for ARG is window width minus 2.
4246 Lisp_Object window = Fselected_window (Qnil);
4247 struct window *w = XWINDOW (window);
4250 arg = make_int (window_char_width (w, 0) - 2);
4252 arg = Fprefix_numeric_value (arg);
4254 return Fset_window_hscroll (window, make_int (w->hscroll - XINT (arg)));
4257 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4258 Center point in WINDOW. With N, put point on line N.
4259 The desired position of point is always relative to the window.
4260 If WINDOW is nil, the selected window is used.
4264 struct window *w = decode_window (window);
4265 struct buffer *b = XBUFFER (w->buffer);
4266 Bufpos opoint = BUF_PT (b);
4270 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4273 n = Fprefix_numeric_value (n);
4275 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4278 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4280 w->start_at_line_beg = beginning_of_line_p (b, startp);
4282 MARK_WINDOWS_CHANGED (w);
4286 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4287 Position point relative to WINDOW.
4288 With no argument, position text at center of window.
4289 An argument specifies window line; zero means top of window,
4290 negative means relative to bottom of window.
4291 If WINDOW is nil, the selected window is used.
4298 Bufpos start, new_point;
4301 /* Don't use decode_window() because we need the new value of
4304 window = Fselected_window (Qnil);
4306 CHECK_WINDOW (window);
4307 w = XWINDOW (window);
4308 b = XBUFFER (w->buffer);
4310 height = window_displayed_height (w);
4311 selected = EQ (window, Fselected_window (w->frame));
4317 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4318 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4320 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4323 BUF_SET_PT (b, new_point);
4325 Fset_window_point (window, make_int (new_point));
4327 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4331 start = marker_position (w->start[CURRENT_DISP]);
4332 if (start < BUF_BEGV (b))
4333 start = BUF_BEGV (b);
4334 else if (start > BUF_ZV (b))
4338 new_point = BUF_PT (b);
4340 new_point = marker_position (w->pointm[CURRENT_DISP]);
4342 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4345 BUF_SET_PT (b, new_point);
4347 Fset_window_point (window, make_int (new_point));
4349 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4352 return make_int (retval);
4356 /* #### Is this going to work right when at eob? */
4357 arg = Fprefix_numeric_value (arg);
4359 XSETINT (arg, XINT (arg) + height);
4362 start = marker_position (w->start[CURRENT_DISP]);
4363 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4366 new_point = BUF_PT (b);
4368 new_point = marker_position (w->pointm[CURRENT_DISP]);
4370 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4373 BUF_SET_PT (b, new_point);
4375 Fset_window_point (window, make_int (new_point));
4377 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4379 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4385 BUF_SET_PT (b, start);
4387 Fset_window_point (window, make_int (start));
4391 return Fvertical_motion (arg, window, Qnil);
4395 new_point = vmotion (XWINDOW (window),
4396 marker_position (w->pointm[CURRENT_DISP]),
4398 Fset_window_point (window, make_int (new_point));
4399 return make_int (vpos);
4405 map_windows_1 (Lisp_Object window,
4406 int (*mapfun) (struct window *w, void *closure),
4409 for (; !NILP (window); window = XWINDOW (window)->next)
4412 struct window *w = XWINDOW (window);
4414 if (!NILP (w->vchild))
4415 retval = map_windows_1 (w->vchild, mapfun, closure);
4416 else if (!NILP (w->hchild))
4417 retval = map_windows_1 (w->hchild, mapfun, closure);
4419 retval = (mapfun) (w, closure);
4428 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4429 invocation of MAPFUN. If any invocation of MAPFUN returns
4430 non-zero, the mapping is halted. Otherwise, map_windows() maps
4431 over all windows in F.
4433 If MAPFUN creates or deletes windows, the behaviour is undefined. */
4436 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4440 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4443 Lisp_Object frmcons, devcons, concons;
4445 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4447 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4459 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4462 w->shadow_thickness_changed = 1;
4463 MARK_WINDOWS_CHANGED (w);
4467 vertical_divider_changed_in_window (Lisp_Object specifier,
4471 MARK_WINDOWS_CHANGED (w);
4472 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4475 /* also used in scrollbar.c */
4477 some_window_value_changed (Lisp_Object specifier, struct window *w,
4480 MARK_WINDOWS_CHANGED (w);
4483 #ifdef MEMORY_USAGE_STATS
4489 #ifdef HAVE_SCROLLBARS
4493 int other_redisplay;
4498 compute_window_mirror_usage (struct window_mirror *mir,
4499 struct window_stats *stats,
4500 struct overhead_stats *ovstats)
4504 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4506 #ifdef HAVE_SCROLLBARS
4508 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4511 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4514 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4517 #endif /* HAVE_SCROLLBARS */
4518 stats->other_redisplay +=
4519 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4520 stats->other_redisplay +=
4521 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4525 compute_window_usage (struct window *w, struct window_stats *stats,
4526 struct overhead_stats *ovstats)
4529 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4530 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4531 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4532 stats->line_start +=
4533 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4534 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4537 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4538 Return stats about the memory usage of window WINDOW.
4539 The values returned are in the form of an alist of usage types and byte
4540 counts. The byte counts attempt to encompass all the memory used
4541 by the window (separate from the memory logically associated with a
4542 buffer or frame), including internal structures and any malloc()
4543 overhead associated with them. In practice, the byte counts are
4544 underestimated because certain memory usage is very hard to determine
4545 \(e.g. the amount of memory used inside the Xt library or inside the
4546 X server) and because there is other stuff that might logically
4547 be associated with a window, buffer, or frame (e.g. window configurations,
4548 glyphs) but should not obviously be included in the usage counts.
4550 Multiple slices of the total memory usage may be returned, separated
4551 by a nil. Each slice represents a particular view of the memory, a
4552 particular way of partitioning it into groups. Within a slice, there
4553 is no overlap between the groups of memory, and each slice collectively
4554 represents all the memory concerned.
4558 struct window_stats stats;
4559 struct overhead_stats ovstats;
4560 Lisp_Object val = Qnil;
4562 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4564 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4566 val = acons (Qface_cache, make_int (stats.face), val);
4567 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4568 #ifdef HAVE_SCROLLBARS
4569 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4571 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4572 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4573 val = acons (Qother, make_int (stats.other), val);
4574 val = Fcons (Qnil, val);
4575 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4576 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4577 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4579 return Fnreverse (val);
4582 #endif /* MEMORY_USAGE_STATS */
4585 /************************************************************************/
4586 /* Window configurations */
4587 /************************************************************************/
4589 /* #### This window configuration stuff has had serious bugs lurking in it
4590 for years; it would be a -huge- win if this was reimplemented in lisp.
4593 /* If you add anything to this structure make sure saved_window_equal
4597 Lisp_Object window; /* window */
4598 Lisp_Object buffer; /* buffer */
4599 Lisp_Object start; /* copied marker */
4600 Lisp_Object pointm; /* copied marker */
4601 Lisp_Object sb_point; /* copied marker */
4602 Lisp_Object mark; /* copied marker */
4608 int modeline_hscroll;
4609 int parent_index; /* index into saved_windows */
4610 int prev_index; /* index into saved_windows */
4611 char start_at_line_beg; /* boolean */
4613 #define WINDOW_SLOT_DECLARATION
4614 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4615 #include "winslots.h"
4618 /* If you add anything to this structure make sure window_config_equal
4620 struct window_config
4622 struct lcrecord_header header;
4626 Lisp_Object selected_frame;
4628 Lisp_Object current_window;
4629 Lisp_Object current_buffer;
4630 Lisp_Object minibuffer_scroll_window;
4631 Lisp_Object root_window;
4632 /* Record the values of window-min-width and window-min-height
4633 so that window sizes remain consistent with them. */
4634 int min_width, min_height;
4635 int saved_windows_count;
4636 /* Zero-sized arrays aren't ANSI C */
4637 struct saved_window saved_windows[1];
4640 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4641 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4642 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4643 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4644 #define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
4645 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4648 mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
4650 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4652 ((markobj) (config->current_window));
4653 ((markobj) (config->current_buffer));
4654 ((markobj) (config->minibuffer_scroll_window));
4655 ((markobj) (config->root_window));
4657 for (i = 0; i < config->saved_windows_count; i++)
4659 struct saved_window *s = SAVED_WINDOW_N (config, i);
4660 ((markobj) (s->window));
4661 ((markobj) (s->buffer));
4662 ((markobj) (s->start));
4663 ((markobj) (s->pointm));
4664 ((markobj) (s->sb_point));
4665 ((markobj) (s->mark));
4667 /* #### This looked like this. I do not see why specifier cached
4668 values should not be marked, as such specifiers as toolbars
4669 might have GC-able instances. Freed configs are not marked,
4670 aren't they? -- kkm */
4671 ((markobj) (s->dedicated));
4673 #define WINDOW_SLOT(slot, compare) ((markobj) (s->slot))
4674 #include "winslots.h"
4681 sizeof_window_config_for_n_windows (int n)
4683 return (sizeof (struct window_config) +
4684 /* n - 1 because zero-sized arrays aren't ANSI C */
4685 (n - 1) *sizeof (struct saved_window));
4689 sizeof_window_config (CONST void *h)
4691 CONST struct window_config *c = (CONST struct window_config *) h;
4692 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4696 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4698 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4701 error ("printing unreadable object #<window-configuration 0x%x>",
4702 config->header.uid);
4703 write_c_string ("#<window-configuration ", printcharfun);
4704 sprintf (buf, "0x%x>", config->header.uid);
4705 write_c_string (buf, printcharfun);
4708 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4709 window_configuration,
4711 print_window_config,
4712 0, 0, 0, sizeof_window_config,
4713 struct window_config);
4716 /* Returns a boolean indicating whether the two saved windows are
4719 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4721 #define WINDOW_SLOT(slot, compare) \
4722 if (!compare (win1->slot, win2->slot)) \
4724 #include "winslots.h"
4727 EQ (win1->window, win2->window) &&
4728 EQ (win1->buffer, win2->buffer) &&
4729 internal_equal (win1->start, win2->start, 0) &&
4730 internal_equal (win1->pointm, win2->pointm, 0) &&
4731 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4732 internal_equal (win1->mark, win2->mark, 0) &&
4733 win1->pixel_left == win2->pixel_left &&
4734 win1->pixel_top == win2->pixel_top &&
4735 win1->pixel_width == win2->pixel_width &&
4736 win1->pixel_height == win2->pixel_height &&
4737 win1->hscroll == win2->hscroll &&
4738 win1->modeline_hscroll == win2->modeline_hscroll &&
4739 win1->parent_index == win2->parent_index &&
4740 win1->prev_index == win2->prev_index &&
4741 win1->start_at_line_beg == win2->start_at_line_beg;
4744 /* Returns a boolean indicating whether the two given configurations
4747 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4749 struct window_config *fig1, *fig2;
4752 /* First check if they are truly the same. */
4753 if (EQ (conf1, conf2))
4756 fig1 = XWINDOW_CONFIGURATION (conf1);
4757 fig2 = XWINDOW_CONFIGURATION (conf2);
4759 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4760 EQ (fig1->current_window, fig2->current_window) &&
4761 EQ (fig1->current_buffer, fig2->current_buffer) &&
4762 EQ (fig1->root_window, fig2->root_window) &&
4763 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window) &&
4764 fig1->frame_width == fig2->frame_width &&
4765 fig1->frame_height == fig2->frame_height))
4768 for (i = 0; i < fig1->saved_windows_count; i++)
4770 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4771 SAVED_WINDOW_N (fig2, i)))
4778 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4779 Return t if OBJECT is a window-configuration object.
4783 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4787 mark_windows_in_use_closure (struct window *w, void *closure)
4789 int mark = *(int *)closure;
4790 w->config_mark = mark;
4795 mark_windows_in_use (struct frame *f, int mark)
4797 map_windows (f, mark_windows_in_use_closure, &mark);
4800 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4802 free_window_configuration (Lisp_Object window_config)
4805 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4807 /* Free all the markers. It's not completely necessary that
4808 we do this (window configs sitting in a free list aren't
4809 marked normally so the markers wouldn't be marked anyway)
4810 but it's more efficient. */
4811 for (i = 0; i < config->saved_windows_count; i++)
4813 struct saved_window *p = SAVED_WINDOW_N (config, i);
4815 if (!NILP (p->pointm))
4817 free_marker (XMARKER (p->pointm));
4820 if (!NILP (p->start))
4822 free_marker (XMARKER (p->start));
4825 if (!NILP (p->sb_point))
4827 free_marker (XMARKER (p->sb_point));
4830 if (!NILP (p->mark))
4832 free_marker (XMARKER (p->mark));
4837 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4838 free_managed_lcrecord (Vwindow_configuration_free_list
4839 [config->saved_windows_count - 1],
4845 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4846 Set the configuration of windows and buffers as specified by CONFIGURATION.
4847 CONFIGURATION must be a value previously returned
4848 by `current-window-configuration' (which see).
4853 struct window_config *config;
4854 struct saved_window *p;
4855 Lisp_Object new_current_buffer;
4859 struct gcpro gcpro1;
4860 Lisp_Object old_window_config;
4861 int previous_frame_height;
4862 int previous_frame_width;
4863 int specpdl_count = specpdl_depth ();
4865 GCPRO1 (configuration);
4867 CHECK_WINDOW_CONFIGURATION (configuration);
4868 config = XWINDOW_CONFIGURATION (configuration);
4870 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4873 /* Do not signal an error here if the frame was deleted. There are
4874 reasonable cases where we could get here with a deleted frame and
4875 just want to do close to nothing instead. */
4877 if (FRAME_LIVE_P (f))
4879 /* restore the frame characteristics */
4881 new_current_buffer = config->current_buffer;
4882 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4883 new_current_buffer = Qnil;
4886 * Assumed precondition: w->config_mark = 0 for all w
4887 * This procedure should ensure this is true by the time it exits
4888 * to ensure the precondition for future calls.
4890 * We use w->config_mark to know whether we're modifying a
4891 * window that is currently visible on the frame (#### we
4892 * should just be able to check whether the window is dead
4893 * or not, but this way is safer?). As we process each
4894 * window, we set its config_mark to 0. At the end, we
4895 * go through all the windows that used to be on the frame,
4896 * set each one's config_mark to 0 (to maintain the
4897 * assumed precondition) and delete each one that's no
4900 * #### Using a window-configuration to keep track of
4901 * the current windows is wasteful. All we need is the
4902 * list of windows, so we could just use a dynarr.
4904 old_window_config = Fcurrent_window_configuration (frame);
4906 /* If the new configuration is already equal to the old, then stop
4907 right here. This saves the work below and it also saves
4908 triggering a full redisplay of this window. This is a huge win
4909 when using the mouse since the mode motion code uses
4910 save-window-excursion extensively but will rarely cause the
4911 configuration to actually change. */
4912 if (window_config_equal (configuration, old_window_config))
4914 free_window_configuration (old_window_config);
4919 /* We can't quit or even check for quit because that may cause
4920 investigation of the frame state, which may crash if the frame is
4921 in an inconsistent state. */
4922 begin_dont_check_for_quit ();
4923 record_unwind_protect (free_window_configuration, old_window_config);
4925 mark_windows_in_use (f, 1);
4927 previous_frame_width = FRAME_WIDTH (f);
4928 previous_frame_height = FRAME_HEIGHT (f);
4929 /* If the frame has been resized since this window configuration was
4930 made, we change the frame to the size specified in the
4931 configuration, restore the configuration, and then resize it
4932 back. We keep track of the prevailing height in these variables. */
4933 if (config->frame_height != FRAME_HEIGHT (f)
4934 || config->frame_width != FRAME_WIDTH (f))
4935 change_frame_size (f, config->frame_height, config->frame_width, 0);
4937 /* Temporarily avoid any problems with windows that are smaller
4938 than they are supposed to be. */
4939 window_min_height = 1;
4940 window_min_width = 1;
4942 /* OK, now restore all the windows in the window config.
4943 This may involve "undeleting" windows, since the
4944 windows in the window config may be deleted.
4946 for (k = 0; k < config->saved_windows_count; k++)
4948 p = SAVED_WINDOW_N (config, k);
4949 w = XWINDOW (p->window);
4952 /* The window might be dead. In this case, its redisplay
4953 structures were freed, so we need to reallocate them. */
4954 if (!w->face_cachels)
4956 w->face_cachels = Dynarr_new (face_cachel);
4957 reset_face_cachels (w);
4959 if (!w->glyph_cachels)
4960 w->glyph_cachels = Dynarr_new (glyph_cachel);
4961 if (!w->line_start_cache)
4962 w->line_start_cache = Dynarr_new (line_start_cache);
4965 if (p->parent_index >= 0)
4966 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
4970 if (p->prev_index >= 0)
4972 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
4974 /* This is true for a minibuffer-only frame. */
4975 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
4978 XWINDOW (w->prev)->next = p->window;
4983 if (!NILP (w->parent))
4985 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
4987 XWINDOW (w->parent)->vchild = p->window;
4988 XWINDOW (w->parent)->hchild = Qnil;
4992 XWINDOW (w->parent)->hchild = p->window;
4993 XWINDOW (w->parent)->vchild = Qnil;
4997 if (!w->config_mark)
4999 /* #### This should be equivalent to the window previously
5000 having been dead. If we're brave, we'll put in an
5001 assertion to this effect. */
5002 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5004 else /* if (!EQ (w->buffer, p->buffer)) */
5006 /* With the new redisplay we let it know that a change has
5007 been made and it will take care of the rest. If we don't
5008 tell it something has possibly changed it could lead to
5009 incorrect display. */
5010 MARK_WINDOWS_CHANGED (w);
5013 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5014 WINDOW_TOP (w) = WINDOW_TOP (p);
5015 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5016 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5017 w->hscroll = p->hscroll;
5018 w->modeline_hscroll = p->modeline_hscroll;
5019 w->line_cache_last_updated = Qzero;
5020 SET_LAST_MODIFIED (w, 1);
5021 SET_LAST_FACECHANGE (w);
5024 #define WINDOW_SLOT(slot, compare) w->slot = p->slot;
5025 #include "winslots.h"
5027 /* Reinstall the saved buffer and pointers into it. */
5028 if (NILP (p->buffer))
5029 w->buffer = p->buffer;
5032 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5033 /* If saved buffer is alive, install it. */
5035 w->buffer = p->buffer;
5036 w->start_at_line_beg = p->start_at_line_beg;
5037 set_marker_restricted (w->start[CURRENT_DISP],
5038 Fmarker_position (p->start),
5040 set_marker_restricted (w->pointm[CURRENT_DISP],
5041 Fmarker_position (p->pointm),
5043 set_marker_restricted (w->sb_point,
5044 Fmarker_position (p->sb_point),
5046 Fset_marker (XBUFFER (w->buffer)->mark,
5047 Fmarker_position (p->mark), w->buffer);
5049 /* As documented in Fcurrent_window_configuration, don't
5050 save the location of point in the buffer which was current
5051 when the window configuration was recorded. */
5052 if (!EQ (p->buffer, new_current_buffer) &&
5053 XBUFFER (p->buffer) == current_buffer)
5054 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5056 else if (NILP (w->buffer) ||
5057 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5058 /* Else if window's old buffer is dead too, get a live one. */
5060 /* #### The following line makes me nervous... */
5061 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5062 w->buffer = Fget_buffer_create (QSscratch);
5063 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5064 /* This will set the markers to beginning of visible
5066 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5067 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5069 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5070 w->start_at_line_beg = 1;
5073 /* Keeping window's old buffer; make sure the markers
5076 /* Set window markers at start of visible range. */
5077 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5078 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5080 if (XMARKER (w->sb_point)->buffer == 0)
5081 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5082 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5083 set_marker_restricted (w->pointm[CURRENT_DISP],
5085 (BUF_PT (XBUFFER (w->buffer))),
5087 w->start_at_line_beg = 1;
5092 FRAME_ROOT_WINDOW (f) = config->root_window;
5093 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5094 then calls do_switch_frame() below to select the frame that was
5095 recorded in the window config as being selected.
5097 Instead, we don't ever change the selected frame, and either
5098 call Fselect_window() below if the window config's frame is
5099 currently selected, or just set the selected window of the
5100 window config's frame. */
5102 /* Set the frame height to the value it had before this function. */
5103 if (previous_frame_height != FRAME_HEIGHT (f)
5104 || previous_frame_width != FRAME_WIDTH (f))
5105 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5107 /* If restoring in the current frame make the window current,
5108 otherwise just update the frame selected_window slot to be
5109 the restored current_window. */
5110 if (f == selected_frame ())
5112 /* When using `pop-window-configuration', often the minibuffer
5113 ends up as the selected window even though it's not active ...
5114 I really don't know the cause of this, but it should never
5115 happen. This kludge should fix it.
5117 #### Find out why this is really going wrong. */
5118 if (!minibuf_level &&
5119 MINI_WINDOW_P (XWINDOW (config->current_window)))
5120 Fselect_window (Fnext_window (config->current_window,
5124 Fselect_window (config->current_window, Qnil);
5125 if (!NILP (new_current_buffer))
5126 Fset_buffer (new_current_buffer);
5128 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5131 set_frame_selected_window (f, config->current_window);
5134 old_window_config = Qnil; /* Warning suppression */
5136 /* Restore the minimum heights recorded in the configuration. */
5137 window_min_height = config->min_height;
5138 window_min_width = config->min_width;
5141 /* see above comment */
5142 /* Fselect_window will have made f the selected frame, so we
5143 reselect the proper frame here. Fhandle_switch_frame will change the
5144 selected window too, but that doesn't make the call to
5145 Fselect_window above totally superfluous; it still sets f's
5147 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5148 do_switch_frame (config->selected_frame, Qnil, 0);
5151 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5153 if (FRAME_LIVE_P (f))
5155 /* Do this before calling recompute_all_cached_specifiers_in_window()
5156 so that things like redisplay_redraw_cursor() won't abort due
5157 to no window mirror present. */
5158 f->mirror_dirty = 1;
5160 config = XWINDOW_CONFIGURATION (old_window_config);
5161 for (k = 0; k < config->saved_windows_count; k++)
5163 p = SAVED_WINDOW_N (config, k);
5164 w = XWINDOW (p->window);
5165 /* Remember, we set w->config_mark on all currently visible
5166 windows, and reset it on all newly visible windows.
5167 Any windows still marked need to be deleted. */
5170 mark_window_as_deleted (w);
5175 /* We just potentially changed the window's buffer and
5176 potentially turned a dead window into a live one,
5177 so we need to recompute the cached specifier values. */
5178 recompute_all_cached_specifiers_in_window (w);
5183 /* Now restore things, when everything else if OK. */
5185 unbind_to (specpdl_count, Qnil);
5192 /* Mark all subwindows of a window as deleted. The argument
5193 W is actually the subwindow tree of the window in question. */
5196 delete_all_subwindows (struct window *w)
5198 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5199 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5200 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5202 mark_window_as_deleted (w);
5207 count_windows (struct window *window)
5210 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5211 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5212 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5216 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5219 for (j = 0; j < lim; j++)
5221 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5225 return 0; /* suppress compiler warning */
5229 save_window_save (Lisp_Object window, struct window_config *config, int i)
5233 for (; !NILP (window); window = w->next)
5235 struct saved_window *p = SAVED_WINDOW_N (config, i);
5237 w = XWINDOW (window);
5240 p->buffer = w->buffer;
5241 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5242 WINDOW_TOP (p) = WINDOW_TOP (w);
5243 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5244 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5245 p->hscroll = w->hscroll;
5246 p->modeline_hscroll = w->modeline_hscroll;
5248 #define WINDOW_SLOT(slot, compare) p->slot = w->slot;
5249 #include "winslots.h"
5251 if (!NILP (w->buffer))
5253 /* Save w's value of point in the window configuration.
5254 If w is the selected window, then get the value of point
5255 from the buffer; pointm is garbage in the selected window. */
5256 if (EQ (window, Fselected_window (Qnil)))
5258 p->pointm = noseeum_make_marker ();
5259 Fset_marker (p->pointm,
5260 make_int (BUF_PT (XBUFFER (w->buffer))),
5264 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5266 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5267 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5268 p->start_at_line_beg = w->start_at_line_beg;
5270 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5278 p->start_at_line_beg = 0;
5281 if (NILP (w->parent))
5282 p->parent_index = -1;
5284 p->parent_index = saved_window_index (w->parent, config, i);
5288 p->prev_index = saved_window_index (w->prev, config, i);
5289 if (!NILP (w->vchild))
5290 i = save_window_save (w->vchild, config, i);
5291 if (!NILP (w->hchild))
5292 i = save_window_save (w->hchild, config, i);
5299 /* Added to doc string:
5301 This also records the currently selected frame, and FRAME's focus
5302 redirection (see `redirect-frame-focus').
5307 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5308 Return an object representing the current window configuration of FRAME.
5309 If FRAME is nil or omitted, use the selected frame.
5310 This describes the number of windows, their sizes and current buffers,
5311 and for each displayed buffer, where display starts, and the positions of
5312 point and mark. An exception is made for point in the current buffer:
5313 its value is -not- saved.
5318 struct frame *f = decode_frame (frame);
5319 struct window_config *config;
5320 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5322 if (n_windows <= countof (Vwindow_configuration_free_list))
5323 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5324 (Vwindow_configuration_free_list
5327 /* More than ten windows; just allocate directly */
5328 config = (struct window_config *)
5329 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5330 lrecord_window_configuration);
5331 XSETWINDOW_CONFIGURATION (result, config);
5333 config->frame_width = FRAME_WIDTH (f);
5334 config->frame_height = FRAME_HEIGHT (f);
5335 config->current_window = FRAME_SELECTED_WINDOW (f);
5336 XSETBUFFER (config->current_buffer, current_buffer);
5337 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5338 config->root_window = FRAME_ROOT_WINDOW (f);
5339 config->min_height = window_min_height;
5340 config->min_width = window_min_width;
5341 config->saved_windows_count = n_windows;
5342 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5347 save_window_excursion_unwind (Lisp_Object window_config)
5349 Lisp_Object val = Fset_window_configuration (window_config);
5350 free_window_configuration (window_config);
5354 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5355 Execute body, preserving window sizes and contents.
5356 Restores which buffer appears in which window, where display starts,
5357 as well as the current buffer.
5358 Does not restore the value of point in current buffer.
5362 /* This function can GC */
5364 int speccount = specpdl_depth ();
5366 record_unwind_protect (save_window_excursion_unwind,
5367 Fcurrent_window_configuration (Qnil));
5368 val = Fprogn (args);
5369 return unbind_to (speccount, val);
5374 /* This is short and simple in elisp, but... it was written to debug
5375 problems purely on the C side. That is where we need to call it so
5378 debug_print_window (Lisp_Object window, int level)
5381 Lisp_Object child = Fwindow_first_vchild (window);
5384 child = Fwindow_first_hchild (window);
5386 for (i = level; i > 0; i--)
5387 putc ('\t', stderr);
5389 fputs ("#<window", stderr);
5391 Lisp_Object buffer = XWINDOW (window)->buffer;
5392 if (!NILP (buffer) && BUFFERP (buffer))
5393 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5395 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5397 while (!NILP (child))
5399 debug_print_window (child, level + 1);
5400 child = Fwindow_next_child (child);
5404 void debug_print_windows (struct frame *f);
5406 debug_print_windows (struct frame *f)
5408 debug_print_window (f->root_window, 0);
5409 putc ('\n', stderr);
5411 #endif /* DEBUG_XEMACS */
5414 /************************************************************************/
5415 /* initialization */
5416 /************************************************************************/
5419 syms_of_window (void)
5421 defsymbol (&Qwindowp, "windowp");
5422 defsymbol (&Qwindow_live_p, "window-live-p");
5423 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5424 defsymbol (&Qscroll_up, "scroll-up");
5425 defsymbol (&Qscroll_down, "scroll-down");
5426 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5427 defsymbol (&Qdisplay_buffer, "display-buffer");
5429 #ifdef MEMORY_USAGE_STATS
5430 defsymbol (&Qface_cache, "face-cache");
5431 defsymbol (&Qglyph_cache, "glyph-cache");
5432 defsymbol (&Qline_start_cache, "line-start-cache");
5433 #ifdef HAVE_SCROLLBARS
5434 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5436 defsymbol (&Qother_redisplay, "other-redisplay");
5437 /* Qother in general.c */
5440 DEFSUBR (Fselected_window);
5441 DEFSUBR (Fminibuffer_window);
5442 DEFSUBR (Fwindow_minibuffer_p);
5444 DEFSUBR (Fwindow_live_p);
5445 DEFSUBR (Fwindow_first_hchild);
5446 DEFSUBR (Fwindow_first_vchild);
5447 DEFSUBR (Fwindow_next_child);
5448 DEFSUBR (Fwindow_previous_child);
5449 DEFSUBR (Fwindow_parent);
5450 DEFSUBR (Fwindow_lowest_p);
5451 DEFSUBR (Fwindow_highest_p);
5452 DEFSUBR (Fwindow_leftmost_p);
5453 DEFSUBR (Fwindow_rightmost_p);
5454 DEFSUBR (Fpos_visible_in_window_p);
5455 DEFSUBR (Fwindow_buffer);
5456 DEFSUBR (Fwindow_frame);
5457 DEFSUBR (Fwindow_height);
5458 DEFSUBR (Fwindow_displayed_height);
5459 DEFSUBR (Fwindow_width);
5460 DEFSUBR (Fwindow_pixel_height);
5461 DEFSUBR (Fwindow_pixel_width);
5462 DEFSUBR (Fwindow_text_area_pixel_height);
5463 DEFSUBR (Fwindow_displayed_text_pixel_height);
5464 DEFSUBR (Fwindow_text_area_pixel_width);
5465 DEFSUBR (Fwindow_hscroll);
5466 #ifdef MODELINE_IS_SCROLLABLE
5467 DEFSUBR (Fmodeline_hscroll);
5468 DEFSUBR (Fset_modeline_hscroll);
5469 #endif /* MODELINE_IS_SCROLLABLE */
5470 #if 0 /* bogus FSF crock */
5471 DEFSUBR (Fwindow_redisplay_end_trigger);
5472 DEFSUBR (Fset_window_redisplay_end_trigger);
5474 DEFSUBR (Fset_window_hscroll);
5475 DEFSUBR (Fwindow_pixel_edges);
5476 DEFSUBR (Fwindow_text_area_pixel_edges);
5477 DEFSUBR (Fwindow_point);
5478 DEFSUBR (Fwindow_start);
5479 DEFSUBR (Fwindow_end);
5480 DEFSUBR (Fset_window_point);
5481 DEFSUBR (Fset_window_start);
5482 DEFSUBR (Fwindow_dedicated_p);
5483 DEFSUBR (Fset_window_dedicated_p);
5484 DEFSUBR (Fnext_window);
5485 DEFSUBR (Fprevious_window);
5486 DEFSUBR (Fnext_vertical_window);
5487 DEFSUBR (Fother_window);
5488 DEFSUBR (Fget_lru_window);
5489 DEFSUBR (Fget_largest_window);
5490 DEFSUBR (Fget_buffer_window);
5491 DEFSUBR (Fwindow_left_margin_pixel_width);
5492 DEFSUBR (Fwindow_right_margin_pixel_width);
5493 DEFSUBR (Fdelete_other_windows);
5494 DEFSUBR (Fdelete_windows_on);
5495 DEFSUBR (Freplace_buffer_in_windows);
5496 DEFSUBR (Fdelete_window);
5497 DEFSUBR (Fset_window_buffer);
5498 DEFSUBR (Fselect_window);
5499 DEFSUBR (Fsplit_window);
5500 DEFSUBR (Fenlarge_window);
5501 DEFSUBR (Fenlarge_window_pixels);
5502 DEFSUBR (Fshrink_window);
5503 DEFSUBR (Fshrink_window_pixels);
5504 DEFSUBR (Fscroll_up);
5505 DEFSUBR (Fscroll_down);
5506 DEFSUBR (Fscroll_left);
5507 DEFSUBR (Fscroll_right);
5508 DEFSUBR (Fother_window_for_scrolling);
5509 DEFSUBR (Fscroll_other_window);
5510 DEFSUBR (Fcenter_to_window_line);
5511 DEFSUBR (Fmove_to_window_line);
5512 #ifdef MEMORY_USAGE_STATS
5513 DEFSUBR (Fwindow_memory_usage);
5515 DEFSUBR (Fwindow_configuration_p);
5516 DEFSUBR (Fset_window_configuration);
5517 DEFSUBR (Fcurrent_window_configuration);
5518 DEFSUBR (Fsave_window_excursion);
5522 vars_of_window (void)
5524 /* Make sure all windows get marked */
5525 minibuf_window = Qnil;
5526 staticpro (&minibuf_window);
5528 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5529 *Non-nil means to scroll if point lands on a line which is clipped.
5531 scroll_on_clipped_lines = 1;
5533 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5534 See `temp-buffer-show-function'.
5536 Vtemp_buffer_show_hook = Qnil;
5538 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5539 Non-nil means call as function to display a help buffer.
5540 The function is called with one argument, the buffer to be displayed.
5541 Used by `with-output-to-temp-buffer'.
5542 If this function is used, then it must do the entire job of showing
5543 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5545 Vtemp_buffer_show_function = Qnil;
5547 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5548 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5550 Vminibuffer_scroll_window = Qnil;
5552 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5553 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5555 Vother_window_scroll_buffer = Qnil;
5557 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5558 *Number of lines of continuity when scrolling by screenfuls.
5560 next_screen_context_lines = 2;
5562 DEFVAR_INT ("window-min-height", &window_min_height /*
5563 *Delete any window less than this tall (including its modeline).
5565 window_min_height = 4;
5567 DEFVAR_INT ("window-min-width", &window_min_width /*
5568 *Delete any window less than this wide.
5570 window_min_width = 10;
5575 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5577 Vwindow_configuration_free_list[i] =
5578 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5579 lrecord_window_configuration);
5580 staticpro (&Vwindow_configuration_free_list[i]);
5586 specifier_vars_of_window (void)
5588 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5589 *How thick to draw 3D shadows around modelines.
5590 If this is set to 0, modelines will be the traditional 2D. Sizes above
5591 10 will be accepted but the maximum thickness that will be drawn is 10.
5592 This is a specifier; use `set-specifier' to change it.
5594 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5595 /* The initial value for modeline-shadow-thickness is 2, but if the
5596 user removes all specifications we provide a fallback value of 0,
5597 which is probably what was expected. */
5598 set_specifier_fallback (Vmodeline_shadow_thickness,
5599 list1 (Fcons (Qnil, Qzero)));
5600 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5602 set_specifier_caching (Vmodeline_shadow_thickness,
5603 slot_offset (struct window,
5604 modeline_shadow_thickness),
5605 modeline_shadow_thickness_changed,
5608 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5609 *Whether the modeline should be displayed.
5610 This is a specifier; use `set-specifier' to change it.
5612 Vhas_modeline_p = Fmake_specifier (Qboolean);
5613 set_specifier_fallback (Vhas_modeline_p,
5614 list1 (Fcons (Qnil, Qt)));
5615 set_specifier_caching (Vhas_modeline_p,
5616 slot_offset (struct window,
5618 /* #### It's strange that we need a special
5619 flag to indicate that the shadow-thickness
5620 has changed, but not one to indicate that
5621 the modeline has been turned off or on. */
5622 some_window_value_changed,
5625 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5626 &Vvertical_divider_always_visible_p /*
5627 *Should XEmacs always display vertical dividers between windows.
5629 When this is non-nil, vertical dividers are always shown, and are
5630 draggable. When it is nil, vertical dividers are shown only when
5631 there are no scrollbars in between windows, and are not draggable.
5633 This is a specifier; use `set-specifier' to change it.
5635 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5636 set_specifier_fallback (Vvertical_divider_always_visible_p,
5637 list1 (Fcons (Qnil, Qt)));
5638 set_specifier_caching (Vvertical_divider_always_visible_p,
5639 slot_offset (struct window,
5640 vertical_divider_always_visible_p),
5641 vertical_divider_changed_in_window,
5644 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5645 *How thick to draw 3D shadows around vertical dividers.
5646 This is a specifier; use `set-specifier' to change it.
5648 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5649 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5650 list1 (Fcons (Qnil, Qzero)));
5651 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5653 set_specifier_caching (Vvertical_divider_shadow_thickness,
5654 slot_offset (struct window,
5655 vertical_divider_shadow_thickness),
5656 vertical_divider_changed_in_window,
5658 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5659 *The width of the vertical dividers, not including shadows.
5661 For TTY windows, divider line is always one character wide. When
5662 instance of this specifier is zero in a TTY window, no divider is
5663 drawn at all between windows. When non-zero, a one character wide
5664 divider is displayed.
5666 This is a specifier; use `set-specifier' to change it.
5669 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5671 Lisp_Object fb = Qnil;
5673 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5675 #ifdef HAVE_X_WINDOWS
5676 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5678 #ifdef HAVE_MS_WINDOWS
5679 /* #### This should be made magic and made to obey system settings */
5680 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5682 set_specifier_fallback (Vvertical_divider_line_width, fb);
5684 set_specifier_caching (Vvertical_divider_line_width,
5685 slot_offset (struct window,
5686 vertical_divider_line_width),
5687 vertical_divider_changed_in_window,
5690 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5691 *How much space to leave around the vertical dividers.
5693 In TTY windows, spacing is always zero, and the value of this
5694 specifier is ignored.
5696 This is a specifier; use `set-specifier' to change it.
5698 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5700 Lisp_Object fb = Qnil;
5702 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5704 #ifdef HAVE_X_WINDOWS
5705 /* #### 3D dividers look great on MS Windows with spacing = 0.
5706 Should not the same value be the fallback under X? - kkm */
5707 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
5709 #ifdef HAVE_MS_WINDOWS
5710 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
5712 set_specifier_fallback (Vvertical_divider_spacing, fb);
5714 set_specifier_caching (Vvertical_divider_spacing,
5715 slot_offset (struct window,
5716 vertical_divider_spacing),
5717 vertical_divider_changed_in_window,