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;
1639 w->redo_modeline = 1;
1640 SET_LAST_MODIFIED (w, 0);
1641 SET_LAST_FACECHANGE (w);
1643 MARK_WINDOWS_CHANGED (w);
1648 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1649 Return WINDOW's dedicated object, usually t or nil.
1650 See also `set-window-dedicated-p'.
1654 return decode_window (window)->dedicated;
1657 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1658 Control whether WINDOW is dedicated to the buffer it displays.
1659 If it is dedicated, Emacs will not automatically change
1660 which buffer appears in it.
1661 The second argument is the new value for the dedication flag;
1666 struct window *w = decode_window (window);
1668 w->dedicated = NILP (arg) ? Qnil : Qt;
1670 return w->dedicated;
1673 /* FSFmacs has window-display-table here. We have display table as a
1677 /* Record info on buffer window w is displaying
1678 when it is about to cease to display that buffer. */
1680 unshow_buffer (struct window *w)
1682 Lisp_Object buf = w->buffer;
1684 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1687 /* FSF disables this check, so I'll do it too. I hope it won't
1688 break things. --ben */
1690 if (w == XWINDOW (Fselected_window (Qnil))
1691 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1692 /* Do this except when the selected window's buffer
1693 is being removed from some other window. */
1695 /* last_window_start records the start position that this buffer
1696 had in the last window to be disconnected from it.
1697 Now that this statement is unconditional,
1698 it is possible for the buffer to be displayed in the
1699 selected window, while last_window_start reflects another
1700 window which was recently showing the same buffer.
1701 Some people might say that might be a good thing. Let's see. */
1702 XBUFFER (buf)->last_window_start =
1703 marker_position (w->start[CURRENT_DISP]);
1705 /* Point in the selected window's buffer
1706 is actually stored in that buffer, and the window's pointm isn't used.
1707 So don't clobber point in that buffer. */
1708 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1710 struct buffer *b= XBUFFER (buf);
1711 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1712 marker_position (w->pointm[CURRENT_DISP]),
1717 /* Put REPLACEMENT into the window structure in place of OLD. */
1719 replace_window (Lisp_Object old, Lisp_Object replacement)
1722 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1724 /* If OLD is its frame's root_window, then replacement is the new
1725 root_window for that frame. */
1727 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1728 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1730 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1731 WINDOW_TOP (p) = WINDOW_TOP (o);
1732 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1733 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1735 p->next = tem = o->next;
1737 XWINDOW (tem)->prev = replacement;
1739 p->prev = tem = o->prev;
1741 XWINDOW (tem)->next = replacement;
1743 p->parent = tem = o->parent;
1746 if (EQ (XWINDOW (tem)->vchild, old))
1747 XWINDOW (tem)->vchild = replacement;
1748 if (EQ (XWINDOW (tem)->hchild, old))
1749 XWINDOW (tem)->hchild = replacement;
1752 /* #### Here, if replacement is a vertical combination
1753 and so is its new parent, we should make replacement's
1754 children be children of that parent instead. */
1757 /* we're deleting W; set the structure of W to indicate this. */
1760 mark_window_as_deleted (struct window *w)
1763 (while t (split-window) (delete-window))
1764 we end up with a tree of deleted windows which are all connected
1765 through the `next' slot. This might not seem so bad, as they're
1766 deleted, and will presumably be GCed - but if even *one* of those
1767 windows is still being pointed to, by the user, or by a window
1768 configuration, then *all* of those windows stick around.
1770 Since the window-configuration code doesn't need any of the
1771 pointers to other windows (they are all recreated from the
1772 window-config data), we set them all to nil so that we
1773 are able to collect more actual garbage.
1783 /* Free the extra data structures attached to windows immediately so
1784 they don't sit around consuming excess space. They will be
1785 reinitialized by the window-configuration code as necessary. */
1786 finalize_window ((void *) w, 0);
1789 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1790 Remove WINDOW from the display. Default is selected window.
1791 If window is the only one on the frame, the frame is destroyed.
1792 Normally, you cannot delete the last non-minibuffer-only frame (you must
1793 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1794 second argument FORCE is non-nil, you can delete the last frame. (This
1795 will automatically call `save-buffers-kill-emacs'.)
1799 /* This function can GC if this is the only window in the frame */
1807 /* Note: this function is called by other C code on non-leaf
1810 /* Do the equivalent of decode_window() but don't error out on
1811 deleted window; it's OK to delete an already-deleted window. */
1813 window = Fselected_window (Qnil);
1815 CHECK_WINDOW (window);
1816 w = XWINDOW (window);
1818 /* It's okay to delete an already-deleted window. */
1819 if (! WINDOW_LIVE_P (w))
1822 frame = WINDOW_FRAME (w);
1824 d = XDEVICE (FRAME_DEVICE (f));
1826 if (TOP_LEVEL_WINDOW_P (w))
1828 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1829 /* this frame isn't fully initialized yet; don't blow up. */
1832 if (MINI_WINDOW_P (XWINDOW (window)))
1833 error ("Attempt to delete the minibuffer window");
1835 /* It has been suggested that it's a good thing for C-x 0 to have this
1836 behavior, but not such a good idea for #'delete-window to have it.
1837 Maybe C-x 0 should be bound to something else, or maybe frame
1838 deletion should only happen when this is called interactively.
1840 delete_frame_internal (f, !NILP (force), 0, 0);
1844 /* At this point, we know the window has a parent. */
1846 par = XWINDOW (parent);
1848 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1850 /* Are we trying to delete any frame's selected window?
1851 Note that we could be dealing with a non-leaf window
1852 where the selected window is one of our children.
1853 So, we check by scanning all the ancestors of the
1854 frame's selected window and comparing each one with
1857 Lisp_Object pwindow;
1859 pwindow = FRAME_SELECTED_WINDOW (f);
1861 while (!NILP (pwindow))
1863 if (EQ (window, pwindow))
1865 pwindow = XWINDOW (pwindow)->parent;
1868 if (EQ (window, pwindow))
1870 /* OK, we found it. */
1871 Lisp_Object alternative;
1872 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1874 /* If we're about to delete the selected window on the
1875 selected frame, then we should use Fselect_window to select
1876 the new window. On the other hand, if we're about to
1877 delete the selected window on any other frame, we shouldn't do
1878 anything but set the frame's selected_window slot. */
1879 if (EQ (frame, Fselected_frame (Qnil)))
1880 Fselect_window (alternative, Qnil);
1882 set_frame_selected_window (f, alternative);
1886 /* w->buffer is nil in a non-leaf window; in this case,
1887 get rid of the markers we maintain that point into that buffer. */
1888 if (!NILP (w->buffer))
1891 unchain_marker (w->pointm[CURRENT_DISP]);
1892 unchain_marker (w->pointm[DESIRED_DISP]);
1893 unchain_marker (w->pointm[CMOTION_DISP]);
1894 unchain_marker (w->start[CURRENT_DISP]);
1895 unchain_marker (w->start[DESIRED_DISP]);
1896 unchain_marker (w->start[CMOTION_DISP]);
1897 unchain_marker (w->sb_point);
1898 /* This breaks set-window-configuration if windows in the saved
1899 configuration get deleted and multiple frames are in use. */
1900 /* w->buffer = Qnil; */
1903 /* close up the hole in the sibling list */
1904 if (!NILP (w->next))
1905 XWINDOW (w->next)->prev = w->prev;
1906 if (!NILP (w->prev))
1907 XWINDOW (w->prev)->next = w->next;
1908 if (EQ (window, par->hchild))
1909 par->hchild = w->next;
1910 if (EQ (window, par->vchild))
1911 par->vchild = w->next;
1913 /* Find one of our siblings to give our space to. */
1915 Lisp_Object sib = w->prev;
1918 /* If w gives its space to its next sibling, that sibling needs
1919 to have its top/left side pulled back to where w's is.
1920 set_window_{height,width} will re-position the sibling's
1923 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1924 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1927 /* Stretch that sibling. */
1928 if (!NILP (par->vchild))
1929 set_window_pixheight
1930 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1931 if (!NILP (par->hchild))
1933 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1936 /* If parent now has only one child,
1937 put the child into the parent's place. */
1939 Lisp_Object parchild = par->hchild;
1940 if (NILP (parchild))
1941 parchild = par->vchild;
1942 if (NILP (XWINDOW (parchild)->next))
1944 replace_window (parent, parchild);
1945 mark_window_as_deleted (XWINDOW (parent));
1949 /* Since we may be deleting combination windows, we must make sure that
1950 not only W but all its children have been marked as deleted. */
1951 if (!NILP (w->hchild))
1952 delete_all_subwindows (XWINDOW (w->hchild));
1953 else if (!NILP (w->vchild))
1954 delete_all_subwindows (XWINDOW (w->vchild));
1956 mark_window_as_deleted (w);
1958 f->mirror_dirty = 1;
1963 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1964 Return next window after WINDOW in canonical ordering of windows.
1965 If omitted, WINDOW defaults to the selected window.
1967 Optional second arg MINIBUF t means count the minibuffer window even
1968 if not active. MINIBUF nil or omitted means count the minibuffer iff
1969 it is active. MINIBUF neither t nor nil means not to count the
1970 minibuffer even if it is active.
1972 Several frames may share a single minibuffer; if the minibuffer
1973 counts, all windows on all frames that share that minibuffer count
1974 too. Therefore, `next-window' can be used to iterate through the
1975 set of windows even when the minibuffer is on another frame. If the
1976 minibuffer does not count, only windows from WINDOW's frame count.
1978 Optional third arg ALL-FRAMES t means include windows on all frames.
1979 ALL-FRAMES nil or omitted means cycle within the frames as specified
1980 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1981 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1982 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1983 Anything else means restrict to WINDOW's frame.
1985 Optional fourth argument CONSOLE controls which consoles or devices the
1986 returned window may be on. If CONSOLE is a console, return windows only
1987 on that console. If CONSOLE is a device, return windows only on that
1988 device. If CONSOLE is a console type, return windows only on consoles
1989 of that type. If CONSOLE is 'window-system, return any windows on any
1990 window-system consoles. If CONSOLE is nil or omitted, return windows only
1991 on WINDOW's console. Otherwise, all windows are considered.
1993 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
1994 can use `next-window' to iterate through the entire cycle of acceptable
1995 windows, eventually ending up back at the window you started with.
1996 `previous-window' traverses the same cycle, in the reverse order.
1998 (window, minibuf, all_frames, console))
2001 Lisp_Object start_window;
2004 window = Fselected_window (Qnil);
2006 CHECK_LIVE_WINDOW (window);
2008 start_window = window;
2010 /* minibuf == nil may or may not include minibuffers.
2011 Decide if it does. */
2013 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2014 else if (! EQ (minibuf, Qt))
2016 /* Now minibuf can be t => count all minibuffer windows,
2017 lambda => count none of them,
2018 or a specific minibuffer window (the active one) to count. */
2020 /* all_frames == nil doesn't specify which frames to include. */
2021 if (NILP (all_frames))
2022 all_frames = (! EQ (minibuf, Qlambda)
2023 ? (FRAME_MINIBUF_WINDOW
2026 (XWINDOW (window)))))
2028 else if (EQ (all_frames, Qvisible))
2030 else if (ZEROP (all_frames))
2032 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2033 /* If all_frames is a frame and window arg isn't on that frame, just
2034 return the first window on the frame. */
2035 return frame_first_window (XFRAME (all_frames));
2036 else if (! EQ (all_frames, Qt))
2038 /* Now all_frames is t meaning search all frames,
2039 nil meaning search just current frame,
2040 visible meaning search just visible frames,
2041 0 meaning search visible and iconified frames,
2042 or a window, meaning search the frame that window belongs to. */
2044 /* Do this loop at least once, to get the next window, and perhaps
2045 again, if we hit the minibuffer and that is not acceptable. */
2048 /* Find a window that actually has a next one. This loop
2049 climbs up the tree. */
2050 while (tem = XWINDOW (window)->next, NILP (tem))
2051 if (tem = XWINDOW (window)->parent, !NILP (tem))
2053 else /* window must be minibuffer window now */
2055 /* We've reached the end of this frame.
2056 Which other frames are acceptable? */
2057 tem = WINDOW_FRAME (XWINDOW (window));
2059 if (! NILP (all_frames))
2064 tem = next_frame (tem, all_frames, console);
2065 /* In the case where the minibuffer is active,
2066 and we include its frame as well as the selected one,
2067 next_frame may get stuck in that frame.
2068 If that happens, go back to the selected frame
2069 so we can complete the cycle. */
2071 XSETFRAME (tem, selected_frame ());
2074 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2080 /* If we're in a combination window, find its first child and
2081 recurse on that. Otherwise, we've found the window we want. */
2084 if (!NILP (XWINDOW (window)->hchild))
2085 window = XWINDOW (window)->hchild;
2086 else if (!NILP (XWINDOW (window)->vchild))
2087 window = XWINDOW (window)->vchild;
2091 /* "acceptable" is the correct spelling. */
2092 /* Which windows are acceptable?
2093 Exit the loop and accept this window if
2094 this isn't a minibuffer window,
2095 or we're accepting all minibuffer windows,
2096 or this is the active minibuffer and we are accepting that one, or
2097 we've come all the way around and we're back at the original window. */
2098 while (MINI_WINDOW_P (XWINDOW (window))
2099 && ! EQ (minibuf, Qt)
2100 && ! EQ (minibuf, window)
2101 && ! EQ (window, start_window));
2106 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2107 Return the window preceding WINDOW in canonical ordering of windows.
2108 If omitted, WINDOW defaults to the selected window.
2110 Optional second arg MINIBUF t means count the minibuffer window even
2111 if not active. MINIBUF nil or omitted means count the minibuffer iff
2112 it is active. MINIBUF neither t nor nil means not to count the
2113 minibuffer even if it is active.
2115 Several frames may share a single minibuffer; if the minibuffer
2116 counts, all windows on all frames that share that minibuffer count
2117 too. Therefore, `previous-window' can be used to iterate through
2118 the set of windows even when the minibuffer is on another frame. If
2119 the minibuffer does not count, only windows from WINDOW's frame count
2121 If optional third arg ALL-FRAMES t means include windows on all frames.
2122 ALL-FRAMES nil or omitted means cycle within the frames as specified
2123 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2124 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2125 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2126 Anything else means restrict to WINDOW's frame.
2128 Optional fourth argument CONSOLE controls which consoles or devices the
2129 returned window may be on. If CONSOLE is a console, return windows only
2130 on that console. If CONSOLE is a device, return windows only on that
2131 device. If CONSOLE is a console type, return windows only on consoles
2132 of that type. If CONSOLE is 'window-system, return any windows on any
2133 window-system consoles. If CONSOLE is nil or omitted, return windows only
2134 on WINDOW's console. Otherwise, all windows are considered.
2136 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2137 can use `previous-window' to iterate through the entire cycle of acceptable
2138 windows, eventually ending up back at the window you started with.
2139 `next-window' traverses the same cycle, in the reverse order.
2141 (window, minibuf, all_frames, console))
2144 Lisp_Object start_window;
2147 window = Fselected_window (Qnil);
2149 CHECK_LIVE_WINDOW (window);
2151 start_window = window;
2153 /* minibuf == nil may or may not include minibuffers.
2154 Decide if it does. */
2156 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2157 else if (! EQ (minibuf, Qt))
2159 /* Now minibuf can be t => count all minibuffer windows,
2160 lambda => count none of them,
2161 or a specific minibuffer window (the active one) to count. */
2163 /* all_frames == nil doesn't specify which frames to include.
2164 Decide which frames it includes. */
2165 if (NILP (all_frames))
2166 all_frames = (! EQ (minibuf, Qlambda)
2167 ? (FRAME_MINIBUF_WINDOW
2170 (XWINDOW (window)))))
2172 else if (EQ (all_frames, Qvisible))
2174 else if (ZEROP (all_frames))
2176 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2177 /* If all_frames is a frame and window arg isn't on that frame, just
2178 return the first window on the frame. */
2179 return frame_first_window (XFRAME (all_frames));
2180 else if (! EQ (all_frames, Qt))
2182 /* Now all_frames is t meaning search all frames,
2183 nil meaning search just current frame,
2184 visible meaning search just visible frames,
2185 0 meaning search visible and iconified frames,
2186 or a window, meaning search the frame that window belongs to. */
2188 /* Do this loop at least once, to get the next window, and perhaps
2189 again, if we hit the minibuffer and that is not acceptable. */
2192 /* Find a window that actually has a next one. This loop
2193 climbs up the tree. */
2194 while (tem = XWINDOW (window)->prev, NILP (tem))
2195 if (tem = XWINDOW (window)->parent, !NILP (tem))
2197 else /* window must be minibuffer window now */
2199 /* We have found the top window on the frame.
2200 Which frames are acceptable? */
2201 tem = WINDOW_FRAME (XWINDOW (window));
2203 if (! NILP (all_frames))
2204 /* It's actually important that we use prev_frame here,
2205 rather than next_frame. All the windows acceptable
2206 according to the given parameters should form a ring;
2207 Fnext_window and Fprevious_window should go back and
2208 forth around the ring. If we use next_frame here,
2209 then Fnext_window and Fprevious_window take different
2210 paths through the set of acceptable windows.
2211 window_loop assumes that these `ring' requirement are
2217 tem = prev_frame (tem, all_frames, console);
2218 /* In the case where the minibuffer is active,
2219 and we include its frame as well as the selected one,
2220 next_frame may get stuck in that frame.
2221 If that happens, go back to the selected frame
2222 so we can complete the cycle. */
2224 XSETFRAME (tem, selected_frame ());
2227 /* If this frame has a minibuffer, find that window first,
2228 because it is conceptually the last window in that frame. */
2229 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2230 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2232 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2239 /* If we're in a combination window, find its first child and
2240 recurse on that. Otherwise, we've found the window we want. */
2243 if (!NILP (XWINDOW (window)->hchild))
2244 window = XWINDOW (window)->hchild;
2245 else if (!NILP (XWINDOW (window)->vchild))
2246 window = XWINDOW (window)->vchild;
2248 while (tem = XWINDOW (window)->next, !NILP (tem))
2252 /* Which windows are acceptable?
2253 Exit the loop and accept this window if
2254 this isn't a minibuffer window,
2255 or we're accepting all minibuffer windows,
2256 or this is the active minibuffer and we are accepting that one, or
2257 we've come all the way around and we're back at the original window. */
2258 while (MINI_WINDOW_P (XWINDOW (window))
2259 && ! EQ (minibuf, Qt)
2260 && ! EQ (minibuf, window)
2261 && ! EQ (window, start_window));
2266 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2267 Return the next window which is vertically after WINDOW.
2272 struct window *w = decode_window (window);
2273 XSETWINDOW (window, w);
2275 if (MINI_WINDOW_P (XWINDOW (window)))
2278 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2280 if (EQ (window, root))
2283 if (!NILP (XWINDOW (window)->hchild))
2284 window = XWINDOW (window)->hchild;
2285 else if (!NILP (XWINDOW (window)->vchild))
2286 window = XWINDOW (window)->vchild;
2293 if (!NILP (XWINDOW (window)->parent) &&
2294 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2296 if (!NILP (XWINDOW (window)->next))
2297 return XWINDOW (window)->next;
2299 window = XWINDOW (window)->parent;
2302 window = XWINDOW (window)->parent;
2304 while (!EQ (window, root));
2307 if (!NILP (XWINDOW (window)->hchild))
2308 window = XWINDOW (window)->hchild;
2309 else if (!NILP (XWINDOW (window)->vchild))
2310 window = XWINDOW (window)->vchild;
2315 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2316 Select the N'th different window on this frame.
2317 All windows on current frame are arranged in a cyclic order.
2318 This command selects the window N steps away in that order.
2319 A negative N moves in the opposite order.
2321 If optional argument FRAME is `visible', search all visible frames.
2322 If FRAME is 0, search all visible and iconified frames.
2323 If FRAME is t, search all frames.
2324 If FRAME is nil, search only the selected frame.
2325 If FRAME is a frame, search only that frame.
2327 Optional third argument CONSOLE controls which consoles or devices the
2328 returned window may be on. If CONSOLE is a console, return windows only
2329 on that console. If CONSOLE is a device, return windows only on that
2330 device. If CONSOLE is a console type, return windows only on consoles
2331 of that type. If CONSOLE is 'window-system, return any windows on any
2332 window-system consoles. If CONSOLE is nil or omitted, return windows only
2333 on FRAME'S console, or on the selected console if FRAME is not a frame.
2334 Otherwise, all windows are considered.
2336 (n, frame, console))
2342 w = Fselected_window (Qnil);
2347 w = Fnext_window (w, Qnil, frame, console);
2352 w = Fprevious_window (w, Qnil, frame, console);
2355 Fselect_window (w, Qnil);
2360 /* Look at all windows, performing an operation specified by TYPE
2363 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2364 frame. If FRAMES is a frame, just look at windows on that frame.
2365 If MINI is non-zero, perform the operation on minibuffer windows too.
2371 GET_BUFFER_WINDOW, /* Arg is buffer */
2372 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2373 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2374 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2376 UNSHOW_BUFFER, /* Arg is buffer */
2377 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2378 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2382 window_loop (enum window_loop type,
2387 Lisp_Object console)
2389 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2391 Lisp_Object best_window = Qnil;
2392 Lisp_Object next_window;
2393 Lisp_Object last_window;
2394 struct frame *frame;
2395 Lisp_Object frame_arg = Qt;
2396 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2397 /* #### I think the change of "precomputing" last_window and next_window
2398 * #### catch the lossage this is meant(?) to punt on...
2401 Lisp_Object devcons, concons;
2403 /* FRAME_ARG is Qlambda to stick to one frame,
2404 Qvisible to consider all visible frames,
2407 /* If we're only looping through windows on a particular frame,
2408 FRAME points to that frame. If we're looping through windows
2409 on all frames, FRAME is 0. */
2411 if (FRAMEP (frames))
2412 frame = XFRAME (frames);
2413 else if (NILP (frames))
2414 frame = selected_frame ();
2418 frame_arg = Qlambda;
2419 else if (ZEROP (frames))
2421 else if (EQ (frames, Qvisible))
2424 DEVICE_LOOP_NO_BREAK (devcons, concons)
2426 Lisp_Object device = XCAR (devcons);
2427 Lisp_Object the_frame;
2430 XSETFRAME (the_frame, frame);
2432 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2434 if (NILP (the_frame))
2437 if (!device_matches_console_spec (the_frame, device, console))
2440 /* Pick a window to start with. */
2444 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2446 /* Figure out the last window we're going to mess with. Since
2447 Fnext_window, given the same options, is guaranteed to go in a
2448 ring, we can just use Fprevious_window to find the last one.
2450 We can't just wait until we hit the first window again,
2451 because it might be deleted. */
2453 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2458 struct window *p = XWINDOW (w);
2459 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2461 /* Pick the next window now, since some operations will delete
2462 the current window. */
2463 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2465 /* #### Still needed ?? */
2466 /* Given the outstanding quality of the rest of this code,
2467 I feel no shame about putting this piece of shit in. */
2468 if (++lose_lose >= 500)
2471 /* Note that we do not pay attention here to whether
2472 the frame is visible, since Fnext_window skips non-visible frames
2473 if that is desired, under the control of frame_arg. */
2474 if (! MINI_WINDOW_P (p)
2475 || (mini && minibuf_level > 0))
2478 case GET_BUFFER_WINDOW:
2480 if (XBUFFER (p->buffer) == XBUFFER (obj))
2485 case GET_BUFFER_WINDOW_COUNT:
2487 if (XBUFFER (p->buffer) == XBUFFER (obj))
2492 case GET_LRU_WINDOW:
2494 /* t as arg means consider only full-width windows */
2496 && !window_full_width_p (p))
2498 /* Ignore dedicated windows and minibuffers. */
2499 if (MINI_WINDOW_P (p)
2500 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2502 if (NILP (best_window)
2503 || (XINT (XWINDOW (best_window)->use_time)
2504 > XINT (p->use_time)))
2509 case GET_BUFFER_MRU_WINDOW:
2511 /* #### what about the first check in GET_LRU_WINDOW? */
2512 /* Ignore dedicated windows and minibuffers. */
2513 if (MINI_WINDOW_P (p)
2514 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2517 if (XBUFFER (p->buffer) == XBUFFER (obj))
2519 if (NILP (best_window)
2520 || (XINT (XWINDOW (best_window)->use_time)
2521 < XINT (p->use_time)))
2527 case DELETE_OTHER_WINDOWS:
2529 /* Don't delete the last window on a frame; this can
2530 happen when the minibuffer is selected, and would
2531 cause the frame to be deleted. */
2532 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2533 Fdelete_window (w, Qnil);
2537 case DELETE_BUFFER_WINDOWS:
2539 if (EQ (p->buffer, obj))
2541 struct frame *f = XFRAME (WINDOW_FRAME (p));
2543 /* If this window is dedicated, and in a frame
2544 of its own, kill the frame. */
2545 if (EQ (w, FRAME_ROOT_WINDOW (f))
2546 && !NILP (p->dedicated)
2547 && other_visible_frames (f))
2549 /* Skip the other windows on this frame.
2550 There might be one, the minibuffer! */
2551 if (! EQ (w, last_window))
2552 while (f == XFRAME (WINDOW_FRAME
2553 (XWINDOW (next_window))))
2555 /* As we go, check for the end of the
2556 loop. We mustn't start going
2557 around a second time. */
2558 if (EQ (next_window, last_window))
2563 next_window = Fnext_window (next_window,
2567 /* Now we can safely delete the frame. */
2568 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2571 /* If we're deleting the buffer displayed in
2572 the only window on the frame, find a new
2573 buffer to display there. */
2574 if (NILP (p->parent))
2576 Lisp_Object new_buffer;
2577 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2578 if (NILP (new_buffer))
2579 new_buffer = Fget_buffer_create (QSscratch);
2580 Fset_window_buffer (w, new_buffer);
2581 if (EQ (w, Fselected_window (Qnil)))
2582 Fset_buffer (p->buffer);
2585 Fdelete_window (w, Qnil);
2590 case GET_LARGEST_WINDOW:
2592 /* Ignore dedicated windows and minibuffers. */
2593 if (MINI_WINDOW_P (p)
2594 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2597 /* write the check as follows to avoid tripping
2598 error_check_window() --ben */
2599 struct window *b = NILP (best_window) ? 0 :
2600 XWINDOW (best_window);
2601 if (NILP (best_window)
2602 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2603 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2611 if (EQ (p->buffer, obj))
2613 /* Find another buffer to show in this window. */
2614 Lisp_Object another_buffer =
2615 Fother_buffer (obj, Qnil, Qnil);
2616 if (NILP (another_buffer))
2618 = Fget_buffer_create (QSscratch);
2619 /* If this window is dedicated, and in a frame
2620 of its own, kill the frame. */
2621 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2622 && !NILP (p->dedicated)
2623 && other_visible_frames (w_frame))
2625 /* Skip the other windows on this frame.
2626 There might be one, the minibuffer! */
2627 if (! EQ (w, last_window))
2628 while (w_frame == XFRAME (WINDOW_FRAME
2629 (XWINDOW (next_window))))
2631 /* As we go, check for the end of the
2632 loop. We mustn't start going
2633 around a second time. */
2634 if (EQ (next_window, last_window))
2639 next_window = Fnext_window (next_window,
2643 /* Now we can safely delete the frame. */
2644 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2649 /* Otherwise show a different buffer in the
2651 p->dedicated = Qnil;
2652 Fset_window_buffer (w, another_buffer);
2653 if (EQ (w, Fselected_window (Qnil)))
2654 Fset_buffer (p->buffer);
2664 if (EQ (w, last_window))
2671 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2674 #if 0 /* not currently used */
2677 buffer_window_count (struct buffer *b, struct frame *f)
2679 Lisp_Object buffer, frame;
2681 XSETFRAME (frame, f);
2682 XSETBUFFER (buffer, b);
2684 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2689 buffer_window_mru (struct window *w)
2691 Lisp_Object window =
2692 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2696 else if (XWINDOW (window) == w)
2705 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2706 Return the window least recently selected or used for display.
2707 If optional argument FRAME is `visible', search all visible frames.
2708 If FRAME is 0, search all visible and iconified frames.
2709 If FRAME is t, search all frames.
2710 If FRAME is nil, search only the selected frame.
2711 If FRAME is a frame, search only that frame.
2713 Optional second argument CONSOLE controls which consoles or devices the
2714 returned window may be on. If CONSOLE is a console, return windows only
2715 on that console. If CONSOLE is a device, return windows only on that
2716 device. If CONSOLE is a console type, return windows only on consoles
2717 of that type. If CONSOLE is 'window-system, return any windows on any
2718 window-system consoles. If CONSOLE is nil or omitted, return windows only
2719 on FRAME'S console, or on the selected console if FRAME is not a frame.
2720 Otherwise, all windows are considered.
2725 /* First try for a non-dedicated window that is full-width */
2726 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2727 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2730 /* Then try for any non-dedicated window */
2731 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2732 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2736 /* FSFmacs never returns a dedicated window here. If we do,
2737 it makes `display-buffer' not work right. #### All of this
2738 shit is so disgusting and awful that it needs to be rethought
2740 /* then try for a dedicated window that is full-width */
2741 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2742 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2745 /* If none of them, then all windows, dedicated or not. */
2746 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2748 /* At this point we damn well better have found something. */
2749 if (NILP (w)) abort ();
2755 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2756 Return the window largest in area.
2757 If optional argument FRAME is `visible', search all visible frames.
2758 If FRAME is 0, search all visible and iconified frames.
2759 If FRAME is t, search all frames.
2760 If FRAME is nil, search only the selected frame.
2761 If FRAME is a frame, search only that frame.
2763 Optional second argument CONSOLE controls which consoles or devices the
2764 returned window may be on. If CONSOLE is a console, return windows only
2765 on that console. If CONSOLE is a device, return windows only on that
2766 device. If CONSOLE is a console type, return windows only on consoles
2767 of that type. If CONSOLE is 'window-system, return any windows on any
2768 window-system consoles. If CONSOLE is nil or omitted, return windows only
2769 on FRAME'S console, or on the selected console if FRAME is not a frame.
2770 Otherwise, all windows are considered.
2774 /* Don't search dedicated windows because FSFmacs doesn't.
2775 This stuff is all black magic so don't try to apply common
2777 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2780 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2781 Return a window currently displaying BUFFER, or nil if none.
2782 If optional argument FRAME is `visible', search all visible frames.
2783 If optional argument FRAME is 0, search all visible and iconified frames.
2784 If FRAME is t, search all frames.
2785 If FRAME is nil, search only the selected frame.
2786 If FRAME is a frame, search only that frame.
2788 Optional third argument CONSOLE controls which consoles or devices the
2789 returned window may be on. If CONSOLE is a console, return windows only
2790 on that console. If CONSOLE is a device, return windows only on that
2791 device. If CONSOLE is a console type, return windows only on consoles
2792 of that type. If CONSOLE is 'window-system, return any windows on any
2793 window-system consoles. If CONSOLE is nil or omitted, return windows only
2794 on FRAME'S console, or on the selected console if FRAME is not a frame.
2795 Otherwise, all windows are considered.
2797 (buffer, frame, console))
2799 buffer = Fget_buffer (buffer);
2800 if (BUFFERP (buffer))
2801 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2802 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2807 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2808 but there is no sensible way to implement those functions, since
2809 you can't in general derive a window from a buffer. */
2811 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2813 Return the width in pixels of the left outside margin of window WINDOW.
2814 If WINDOW is nil, the selected window is assumed.
2818 return make_int (window_left_margin_width (decode_window (window)));
2821 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2823 Return the width in pixels of the right outside margin of window WINDOW.
2824 If WINDOW is nil, the selected window is assumed.
2828 return make_int (window_right_margin_width (decode_window (window)));
2831 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2832 Make WINDOW (or the selected window) fill its frame.
2833 Only the frame WINDOW is on is affected.
2834 This function tries to reduce display jumps
2835 by keeping the text previously visible in WINDOW
2836 in the same place on the frame. Doing this depends on
2837 the value of (window-start WINDOW), so if calling this function
2838 in a program gives strange scrolling, make sure the window-start
2839 value is reasonable when this function is called.
2843 struct window *w = decode_window (window);
2844 struct buffer *b = XBUFFER (w->buffer);
2846 int old_top = WINDOW_TOP (w);
2848 XSETWINDOW (window, w);
2850 if (MINI_WINDOW_P (w) && old_top > 0)
2851 error ("Can't expand minibuffer to full frame");
2853 /* Ignore dedicated windows. */
2854 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2856 start_pos = marker_position (w->start[CURRENT_DISP]);
2858 /* Try to minimize scrolling, by setting the window start to the
2859 point which will cause the text at the old window start to be at
2860 the same place on the frame. But don't try to do this if the
2861 window start is outside the visible portion (as might happen when
2862 the display is not current, due to typeahead). */
2863 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2864 && !MINI_WINDOW_P (w))
2866 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2868 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2870 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2872 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2874 /* We need to do this, so that the window-scroll-functions
2882 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2883 "bDelete windows on (buffer): ", /*
2884 Delete all windows showing BUFFER.
2885 Optional second argument FRAME controls which frames are affected.
2886 If nil or omitted, delete all windows showing BUFFER in any frame.
2887 If t, delete only windows showing BUFFER in the selected frame.
2888 If `visible', delete all windows showing BUFFER in any visible frame.
2889 If a frame, delete only windows showing BUFFER in that frame.
2891 Optional third argument CONSOLE controls which consoles or devices the
2892 returned window may be on. If CONSOLE is a console, return windows only
2893 on that console. If CONSOLE is a device, return windows only on that
2894 device. If CONSOLE is a console type, return windows only on consoles
2895 of that type. If CONSOLE is 'window-system, return any windows on any
2896 window-system consoles. If CONSOLE is nil or omitted, return windows only
2897 on FRAME'S console, or on the selected console if FRAME is not a frame.
2898 Otherwise, all windows are considered.
2900 (buffer, frame, console))
2902 /* This function can GC */
2903 /* FRAME uses t and nil to mean the opposite of what window_loop
2905 if (!FRAMEP (frame))
2906 frame = NILP (frame) ? Qt : Qnil;
2910 buffer = Fget_buffer (buffer);
2911 CHECK_BUFFER (buffer);
2912 /* Ignore dedicated windows. */
2913 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2918 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2919 "bReplace buffer in windows: ", /*
2920 Replace BUFFER with some other buffer in all windows showing it.
2924 /* This function can GC */
2927 buffer = Fget_buffer (buffer);
2928 CHECK_BUFFER (buffer);
2929 /* Ignore dedicated windows. */
2930 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2935 /* The smallest acceptable dimensions for a window. Anything smaller
2936 might crash Emacs. */
2937 #define MIN_SAFE_WINDOW_WIDTH (2)
2938 #define MIN_SAFE_WINDOW_HEIGHT (2)
2940 /* Make sure that window_min_height and window_min_width are
2941 not too small; if they are, set them to safe minima. */
2944 check_min_window_sizes (void)
2946 /* Smaller values might permit a crash. */
2947 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2948 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2949 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2950 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2953 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2954 minimum allowable size. */
2956 check_frame_size (struct frame *frame, int *rows, int *cols)
2958 /* For height, we have to see whether the frame has a minibuffer, and
2959 whether it wants a modeline. */
2961 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2962 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2963 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2965 if (*rows < min_height)
2967 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2968 *cols = MIN_SAFE_WINDOW_WIDTH;
2971 /* Normally the window is deleted if it gets too small.
2972 nodelete nonzero means do not do this.
2973 (The caller should check later and do so if appropriate) */
2975 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
2978 struct window *w = XWINDOW (window);
2979 struct frame *f = XFRAME (w->frame);
2981 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
2982 Lisp_Object child, minor_kid, major_kid;
2985 int defheight, defwidth;
2987 /* #### This is very likely incorrect and instead the char_to_pixel_
2988 functions should be called. */
2989 default_face_height_and_width (window, &defheight, &defwidth);
2990 line_size = (set_height ? defheight : defwidth);
2992 check_min_window_sizes ();
2994 minsize = (set_height ? window_min_height : window_min_width);
2995 minsize *= line_size;
2998 && !TOP_LEVEL_WINDOW_P (w)
2999 && new_pixsize < minsize)
3001 Fdelete_window (window, Qnil);
3005 SET_LAST_MODIFIED (w, 0);
3006 SET_LAST_FACECHANGE (w);
3007 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3010 WINDOW_HEIGHT (w) = new_pixsize;
3011 major_kid = w->vchild;
3012 minor_kid = w->hchild;
3016 WINDOW_WIDTH (w) = new_pixsize;
3017 major_kid = w->hchild;
3018 minor_kid = w->vchild;
3021 if (!NILP (minor_kid))
3023 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3026 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3028 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3030 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3033 else if (!NILP (major_kid))
3035 int last_pos, last_old_pos, pos, old_pos, first;
3036 int pixel_adj_left = new_pixsize - old_pixsize;
3037 int div_val = old_pixsize << 1;
3040 * Previously we bailed out here if there was no size change.
3041 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3042 * toolbar appears or disappears, windows may not change size,
3043 * but their top and left coordinates need to be updated.
3045 * So we don't bail until after the loop below.
3048 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3051 for (child = major_kid; !NILP (child); child = c->next)
3053 c = XWINDOW (child);
3057 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3058 WINDOW_TOP (c) = last_pos;
3062 old_pos = last_old_pos + WINDOW_WIDTH (c);
3063 WINDOW_LEFT (c) = last_pos;
3066 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3067 /* All but the last window should have a height which is
3068 a multiple of the default line height. */
3069 if (!NILP (c->next))
3070 pos = (pos / line_size) * line_size;
3072 /* Avoid confusion: don't delete child if it becomes too small */
3073 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3075 last_pos = pos + first;
3076 last_old_pos = old_pos;
3079 /* Sometimes we may get called with our old size. In that case
3080 we don't need to do anything else. */
3081 if (!pixel_adj_left)
3084 /* Now delete any children that became too small. */
3086 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3089 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3091 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3096 /* Set the height of WINDOW and all its inferiors. */
3098 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3100 set_window_pixsize (window, new_pixheight, nodelete, 1);
3103 /* Recursively set width of WINDOW and its inferiors. */
3105 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3107 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3111 static int window_select_count;
3113 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3114 Make WINDOW display BUFFER as its contents.
3115 BUFFER can be a buffer or buffer name.
3120 struct window *w = decode_window (window);
3122 buffer = Fget_buffer (buffer);
3123 CHECK_BUFFER (buffer);
3125 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3126 error ("Attempt to display deleted buffer");
3130 error ("Window is deleted");
3132 /* While this seems like a logical thing to do, it causes problems
3133 because of saved window configurations. It is possible for a
3134 buffer to get restored into a window in which it is already being
3135 displayed, but start and point are actually at completely
3136 different locations. So we let this function complete fully and
3137 it will then make sure redisplay correctly updates things.
3139 #### This is a kludge. The correct approach is not to do this
3140 but to fix set-window-configuration. */
3142 else if (EQ (tem, buffer))
3145 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3146 is first being set up. */
3148 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3149 error ("Window is dedicated to buffer %s",
3150 XSTRING_DATA (XBUFFER (tem)->name));
3156 w->window_end_pos[CURRENT_DISP] = 0;
3158 w->modeline_hscroll = 0;
3159 Fset_marker (w->pointm[CURRENT_DISP],
3160 make_int (BUF_PT (XBUFFER (buffer))),
3162 set_marker_restricted (w->start[CURRENT_DISP],
3163 make_int (XBUFFER (buffer)->last_window_start),
3165 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3166 w->start_at_line_beg = 0;
3167 w->force_start = 0; /* Lucid fix */
3168 SET_LAST_MODIFIED (w, 1);
3169 SET_LAST_FACECHANGE (w);
3170 MARK_WINDOWS_CHANGED (w);
3171 recompute_all_cached_specifiers_in_window (w);
3172 if (EQ (window, Fselected_window (Qnil)))
3174 Fset_buffer (buffer);
3179 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3180 Select WINDOW. Most editing will apply to WINDOW's buffer.
3181 The main editor command loop selects the buffer of the selected window
3182 before each command.
3184 With non-nil optional argument `norecord', do not modify the
3185 global or per-frame buffer ordering.
3190 Lisp_Object old_selected_window = Fselected_window (Qnil);
3192 CHECK_LIVE_WINDOW (window);
3193 w = XWINDOW (window);
3195 /* we have already caught dead-window errors */
3196 if (!NILP (w->hchild) || !NILP (w->vchild))
3197 error ("Trying to select non-leaf window");
3199 w->use_time = make_int (++window_select_count);
3200 if (EQ (window, old_selected_window))
3203 /* deselect the old window, if it exists (it might not exist if
3204 the selected device has no frames, which occurs at startup) */
3205 if (!NILP (old_selected_window))
3207 struct window *ow = XWINDOW (old_selected_window);
3209 Fset_marker (ow->pointm[CURRENT_DISP],
3210 make_int (BUF_PT (XBUFFER (ow->buffer))),
3213 MARK_WINDOWS_CHANGED (ow);
3216 /* now select the window's frame */
3217 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3219 select_frame_1 (WINDOW_FRAME (w));
3221 /* also select the window's buffer */
3222 if (NILP (norecord))
3223 Frecord_buffer (w->buffer);
3224 Fset_buffer (w->buffer);
3226 /* Go to the point recorded in the window.
3227 This is important when the buffer is in more
3228 than one window. It also matters when
3229 redisplay_window has altered point after scrolling,
3230 because it makes the change only in the window. */
3232 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3233 if (new_point < BUF_BEGV (current_buffer))
3234 new_point = BUF_BEGV (current_buffer);
3235 else if (new_point > BUF_ZV (current_buffer))
3236 new_point = BUF_ZV (current_buffer);
3238 BUF_SET_PT (current_buffer, new_point);
3241 MARK_WINDOWS_CHANGED (w);
3247 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3248 Lisp_Object override_frame)
3250 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3254 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3256 /* This function can GC */
3259 struct buffer *b = XBUFFER (buf);
3261 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3262 widen_buffer (b, 0);
3263 BUF_SET_PT (b, BUF_BEG (b));
3265 if (!NILP (Vtemp_buffer_show_function))
3266 call1 (Vtemp_buffer_show_function, buf);
3269 window = display_buffer (buf, Qnil, same_frame);
3271 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3272 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3274 Vminibuffer_scroll_window = window;
3275 w = XWINDOW (window);
3277 w->modeline_hscroll = 0;
3278 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3279 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3280 set_marker_restricted (w->sb_point, make_int (1), buf);
3282 /* Run temp-buffer-show-hook, with the chosen window selected. */
3283 if (!preparing_for_armageddon)
3286 tem = Fboundp (Qtemp_buffer_show_hook);
3289 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3292 int count = specpdl_depth ();
3294 /* Select the window that was chosen, for running
3296 record_unwind_protect (save_window_excursion_unwind,
3297 Fcurrent_window_configuration (Qnil));
3299 Fselect_window (window, Qnil);
3300 run_hook (Qtemp_buffer_show_hook);
3301 unbind_to (count, Qnil);
3309 make_dummy_parent (Lisp_Object window)
3312 struct window *o = XWINDOW (window);
3313 struct window *p = alloc_lcrecord_type (struct window, lrecord_window);
3315 XSETWINDOW (new, p);
3316 copy_lcrecord (p, o);
3318 /* Don't copy the pointers to the line start cache or the face
3320 p->line_start_cache = Dynarr_new (line_start_cache);
3321 p->face_cachels = Dynarr_new (face_cachel);
3322 p->glyph_cachels = Dynarr_new (glyph_cachel);
3324 /* Put new into window structure in place of window */
3325 replace_window (window, new);
3333 p->start[CURRENT_DISP] = Qnil;
3334 p->start[DESIRED_DISP] = Qnil;
3335 p->start[CMOTION_DISP] = Qnil;
3336 p->pointm[CURRENT_DISP] = Qnil;
3337 p->pointm[DESIRED_DISP] = Qnil;
3338 p->pointm[CMOTION_DISP] = Qnil;
3343 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3344 Split WINDOW, putting SIZE lines in the first of the pair.
3345 WINDOW defaults to selected one and SIZE to half its size.
3346 If optional third arg HOR-FLAG is non-nil, split side by side
3347 and put SIZE columns in the first of the pair.
3349 (window, chsize, horflag))
3352 struct window *o, *p;
3358 window = Fselected_window (Qnil);
3360 CHECK_WINDOW (window);
3362 o = XWINDOW (window);
3363 f = XFRAME (WINDOW_FRAME (o));
3367 if (!NILP (horflag))
3368 /* In the new scheme, we are symmetric with respect to separators
3369 so there is no need to do weird things here. */
3371 psize = WINDOW_WIDTH (o) >> 1;
3372 size = window_pixel_width_to_char_width (o, psize, 0);
3376 psize = WINDOW_HEIGHT (o) >> 1;
3377 size = window_pixel_height_to_char_height (o, psize, 1);
3383 size = XINT (chsize);
3384 if (!NILP (horflag))
3385 psize = window_char_width_to_pixel_width (o, size, 0);
3387 psize = window_char_height_to_pixel_height (o, size, 1);
3390 if (MINI_WINDOW_P (o))
3391 error ("Attempt to split minibuffer window");
3392 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3393 error ("Attempt to split unsplittable frame");
3395 check_min_window_sizes ();
3399 if (size < window_min_height)
3400 error ("Window height %d too small (after splitting)", size);
3401 if (size + window_min_height > window_char_height (o, 1))
3402 error ("Window height %d too small (after splitting)",
3403 window_char_height (o, 1) - size);
3404 if (NILP (o->parent)
3405 || NILP (XWINDOW (o->parent)->vchild))
3407 make_dummy_parent (window);
3408 reset_face_cachels (XWINDOW (window));
3410 XWINDOW (new)->vchild = window;
3411 XFRAME (o->frame)->mirror_dirty = 1;
3416 if (size < window_min_width)
3417 error ("Window width %d too small (after splitting)", size);
3418 if (size + window_min_width > window_char_width (o, 0))
3419 error ("Window width %d too small (after splitting)",
3420 window_char_width (o, 0) - size);
3421 if (NILP (o->parent)
3422 || NILP (XWINDOW (o->parent)->hchild))
3424 make_dummy_parent (window);
3425 reset_face_cachels (XWINDOW (window));
3427 XWINDOW (new)->hchild = window;
3428 XFRAME (o->frame)->mirror_dirty = 1;
3432 /* Now we know that window's parent is a vertical combination
3433 if we are dividing vertically, or a horizontal combination
3434 if we are making side-by-side windows */
3436 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3437 new = allocate_window ();
3440 p->frame = o->frame;
3442 if (!NILP (p->next))
3443 XWINDOW (p->next)->prev = new;
3446 p->parent = o->parent;
3449 reset_face_cachels (p);
3450 reset_glyph_cachels (p);
3453 /* Apportion the available frame space among the two new windows */
3455 if (!NILP (horflag))
3457 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3458 WINDOW_TOP (p) = WINDOW_TOP (o);
3459 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3460 WINDOW_WIDTH (o) = psize;
3461 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3465 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3466 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3467 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3468 WINDOW_HEIGHT (o) = psize;
3469 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3472 XFRAME (p->frame)->mirror_dirty = 1;
3473 /* do this last (after the window is completely initialized and
3474 the mirror-dirty flag is set) so that specifier recomputation
3475 caused as a result of this will work properly and not abort. */
3476 Fset_window_buffer (new, o->buffer);
3481 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3482 Make the selected window ARG lines bigger.
3483 From program, optional second arg non-nil means grow sideways ARG columns,
3484 and optional third ARG specifies the window to change instead of the
3489 struct window *w = decode_window (window);
3491 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3495 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3496 Make the selected window ARG pixels bigger.
3497 From program, optional second arg non-nil means grow sideways ARG pixels,
3498 and optional third ARG specifies the window to change instead of the
3503 struct window *w = decode_window (window);
3505 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3509 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3510 Make the selected window ARG lines smaller.
3511 From program, optional second arg non-nil means shrink sideways ARG columns,
3512 and optional third ARG specifies the window to change instead of the
3518 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3523 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3524 Make the selected window ARG pixels smaller.
3525 From program, optional second arg non-nil means shrink sideways ARG pixels,
3526 and optional third ARG specifies the window to change instead of the
3532 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3538 window_pixel_height (Lisp_Object window)
3540 return WINDOW_HEIGHT (XWINDOW (window));
3544 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3545 int include_gutters_p)
3548 int defheight, defwidth;
3552 XSETWINDOW (window, w);
3554 avail_height = (pixel_height -
3555 (include_gutters_p ? 0 :
3556 window_top_gutter_height (w) +
3557 window_bottom_gutter_height (w)));
3559 default_face_height_and_width (window, &defheight, &defwidth);
3561 char_height = avail_height / defheight;
3563 /* It's the calling function's responsibility to check these values
3564 and make sure they're not out of range.
3566 #### We need to go through the calling functions and actually
3568 return max (0, char_height);
3572 window_char_height_to_pixel_height (struct window *w, int char_height,
3573 int include_gutters_p)
3576 int defheight, defwidth;
3581 XSETWINDOW (window, w);
3583 default_face_height_and_width (window, &defheight, &defwidth);
3585 avail_height = char_height * defheight;
3586 pixel_height = (avail_height +
3587 (include_gutters_p ? 0 :
3588 window_top_gutter_height (w) +
3589 window_bottom_gutter_height (w)));
3591 /* It's the calling function's responsibility to check these values
3592 and make sure they're not out of range.
3594 #### We need to go through the calling functions and actually
3596 return max (0, pixel_height);
3599 /* Return number of default lines of text can fit in the window W.
3600 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3601 horizontal scrollbar) in the space that is used for the calculation.
3604 window_char_height (struct window *w, int include_gutters_p)
3606 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3611 * Return number of lines currently displayed in window w. If
3612 * end-of-buffer is displayed then the area below end-of-buffer is assume
3613 * to be blank lines of default height.
3614 * Does not include the modeline.
3617 window_displayed_height (struct window *w)
3619 struct buffer *b = XBUFFER (w->buffer);
3620 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3622 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3624 : w->window_end_pos[CURRENT_DISP]);
3626 if (!Dynarr_length (dla))
3627 return window_char_height (w, 0);
3629 num_lines = Dynarr_length (dla);
3631 /* #### Document and assert somewhere that w->window_end_pos == -1
3632 indicates that end-of-buffer is being displayed. */
3635 struct display_line *dl = Dynarr_atp (dla, 0);
3636 int ypos1 = dl->ypos + dl->descent;
3637 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3639 int defheight, defwidth;
3641 XSETWINDOW (window, w);
3647 if (Dynarr_length (dla) == 1)
3648 ypos1 = WINDOW_TEXT_TOP (w);
3651 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3652 /* If this line is clipped then we know that there is no
3653 blank room between eob and the modeline. If we are
3654 scrolling on clipped lines just know off the clipped
3656 if (scroll_on_clipped_lines && dl->clip)
3657 return num_lines - 1;
3658 ypos1 = dl->ypos + dl->descent - dl->clip;
3662 default_face_height_and_width (window, &defheight, &defwidth);
3663 /* #### This probably needs to know about the clipping area once a
3664 final definition is decided on. */
3665 num_lines += ((ypos2 - ypos1) / defheight);
3669 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3672 if (scroll_on_clipped_lines
3673 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3681 window_pixel_width (Lisp_Object window)
3683 return WINDOW_WIDTH (XWINDOW (window));
3687 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3688 int include_margins_p)
3692 int defheight, defwidth;
3695 XSETWINDOW (window, w);
3697 avail_width = (pixel_width -
3698 window_left_gutter_width (w, 0) -
3699 window_right_gutter_width (w, 0) -
3700 (include_margins_p ? 0 : window_left_margin_width (w)) -
3701 (include_margins_p ? 0 : window_right_margin_width (w)));
3703 default_face_height_and_width (window, &defheight, &defwidth);
3705 char_width = (avail_width / defwidth);
3707 /* It's the calling function's responsibility to check these values
3708 and make sure they're not out of range.
3710 #### We need to go through the calling functions and actually
3712 return max (0, char_width);
3716 window_char_width_to_pixel_width (struct window *w, int char_width,
3717 int include_margins_p)
3721 int defheight, defwidth;
3724 XSETWINDOW (window, w);
3726 default_face_height_and_width (window, &defheight, &defwidth);
3728 avail_width = char_width * defwidth;
3729 pixel_width = (avail_width +
3730 window_left_gutter_width (w, 0) +
3731 window_right_gutter_width (w, 0) +
3732 (include_margins_p ? 0 : window_left_margin_width (w)) +
3733 (include_margins_p ? 0 : window_right_margin_width (w)));
3735 /* It's the calling function's responsibility to check these values
3736 and make sure they're not out of range.
3738 #### We need to go through the calling functions and actually
3740 return max (0, pixel_width);
3743 /* This returns the usable space which doesn't include space needed by
3744 scrollbars or divider lines. */
3746 window_char_width (struct window *w, int include_margins_p)
3748 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3752 #define MINSIZE(w) \
3754 ? window_min_width * defwidth \
3755 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3758 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3760 #define CURSIZE(w) \
3761 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3763 #define CURCHARSIZE(w) \
3764 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3766 #define MINCHARSIZE(window) \
3767 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3768 ? 1 : window_min_height)
3770 /* Unlike set_window_pixheight, this function
3771 also changes the heights of the siblings so as to
3772 keep everything consistent. */
3775 change_window_height (struct window *win, int delta, int widthflag,
3783 int (*sizefun) (Lisp_Object) = (widthflag
3784 ? window_pixel_width
3785 : window_pixel_height);
3786 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3787 ? set_window_pixwidth
3788 : set_window_pixheight);
3790 int defheight, defwidth;
3795 check_min_window_sizes ();
3797 XSETWINDOW (window, win);
3798 f = XFRAME (win->frame);
3799 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3800 error ("Won't change only window");
3802 /* #### This is very likely incorrect and instead the char_to_pixel_
3803 functions should be called. */
3804 default_face_height_and_width (window, &defheight, &defwidth);
3808 w = XWINDOW (window);
3813 error ("No other window to side of this one");
3817 ? !NILP (XWINDOW (parent)->hchild)
3818 : !NILP (XWINDOW (parent)->vchild))
3823 sizep = &CURSIZE (w);
3824 dim = CURCHARSIZE (w);
3826 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3827 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3829 if (MINI_WINDOW_P (XWINDOW (window)))
3831 else if (!NILP (parent))
3833 Fdelete_window (window, Qnil);
3839 delta *= (widthflag ? defwidth : defheight);
3844 maxdelta = ((!NILP (parent))
3845 ? (*sizefun) (parent) - *sizep
3846 : ((!NILP (w->next))
3847 ? (*sizefun) (w->next) - MINSIZE (w->next)
3848 : ((!NILP (w->prev))
3849 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3850 /* This is a frame with only one window,
3851 a minibuffer-only or a minibufferless frame. */
3854 if (delta > maxdelta)
3855 /* This case traps trying to make the minibuffer
3856 the full frame, or make the only window aside from the
3857 minibuffer the full frame. */
3864 /* #### Chuck: is this correct? */
3865 if (*sizep + delta < MINSIZE (window))
3867 Fdelete_window (window);
3873 if (!NILP (w->next) &&
3874 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3876 CURBEG (XWINDOW (w->next)) += delta;
3877 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3878 (*setsizefun) (window, *sizep + delta, 0);
3880 else if (!NILP (w->prev) &&
3881 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3883 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3884 CURBEG (w) -= delta;
3885 (*setsizefun) (window, *sizep + delta, 0);
3890 int opht = (*sizefun) (parent);
3892 /* If trying to grow this window to or beyond size of the parent,
3893 make delta1 so big that, on shrinking back down,
3894 all the siblings end up with less than one line and are deleted. */
3895 if (opht <= *sizep + delta)
3896 delta1 = opht * opht * 2;
3897 /* Otherwise, make delta1 just right so that if we add delta1
3898 lines to this window and to the parent, and then shrink
3899 the parent back to its original size, the new proportional
3900 size of this window will increase by delta. */
3902 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3904 /* Add delta1 lines or columns to this window, and to the parent,
3905 keeping things consistent while not affecting siblings. */
3906 CURSIZE (XWINDOW (parent)) = opht + delta1;
3907 (*setsizefun) (window, *sizep + delta1, 0);
3909 /* Squeeze out delta1 lines or columns from our parent,
3910 shriking this window and siblings proportionately.
3911 This brings parent back to correct size.
3912 Delta1 was calculated so this makes this window the desired size,
3913 taking it all out of the siblings. */
3914 (*setsizefun) (parent, opht, 0);
3917 SET_LAST_MODIFIED (w, 0);
3918 SET_LAST_FACECHANGE (w);
3919 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3929 /* Scroll contents of window WINDOW up N lines. */
3931 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3932 Error_behavior errb)
3934 struct window *w = XWINDOW (window);
3935 struct buffer *b = XBUFFER (w->buffer);
3936 int selected = EQ (window, Fselected_window (Qnil));
3938 Lisp_Object point, tem;
3941 point = make_int (BUF_PT (b));
3944 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3946 if (pos < BUF_BEGV (b))
3948 else if (pos > BUF_ZV (b))
3951 point = make_int (pos);
3954 /* Always set force_start so that redisplay_window will run
3955 thw window-scroll-functions. */
3958 /* #### When the fuck does this happen? I'm so glad that history has
3959 completely documented the behavior of the scrolling functions under
3960 all circumstances. */
3961 tem = Fpos_visible_in_window_p (point, window);
3964 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
3966 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
3967 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
3968 MARK_WINDOWS_CHANGED (w);
3977 n = Fprefix_numeric_value (n);
3978 value = XINT (n) * direction;
3981 return; /* someone just made a pointless call */
3985 /* If the user didn't specify how far to scroll then we have to figure it
3986 out by ourselves. */
3987 if (NILP (n) || EQ (n, Qminus))
3989 /* Going forwards is easy. If that is what we are doing then just
3990 set value and the section which handles the user specifying a
3991 positive value will work. */
3994 value = window_displayed_height (w) - next_screen_context_lines;
3995 value = (value < 1 ? 1 : value);
3998 /* Going backwards is hard. We can't use the same loop used if the
3999 user specified a negative value because we care about
4000 next_screen_context_lines. In a variable height world you don't
4001 know how many lines above you can actually be displayed and still
4002 have the context lines appear. So we leave value set to 0 and add
4003 a separate section to deal with this. */
4007 if (direction == 1 && !value)
4014 Bufpos startp, old_start;
4016 old_start = marker_position (w->start[CURRENT_DISP]);
4017 startp = vmotion (w, old_start, value, &vtarget);
4019 if (vtarget < value &&
4020 (w->window_end_pos[CURRENT_DISP] == -1
4021 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4023 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4028 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4031 w->start_at_line_beg = beginning_of_line_p (b, startp);
4032 MARK_WINDOWS_CHANGED (w);
4034 if (!point_would_be_visible (w, startp, XINT (point)))
4037 BUF_SET_PT (b, startp);
4039 set_marker_restricted (w->pointm[CURRENT_DISP],
4048 Bufpos startp, old_start;
4050 old_start = marker_position (w->start[CURRENT_DISP]);
4051 startp = vmotion (w, old_start, value, &vtarget);
4054 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4056 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4061 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4064 w->start_at_line_beg = beginning_of_line_p (b, startp);
4065 MARK_WINDOWS_CHANGED (w);
4067 if (!point_would_be_visible (w, startp, XINT (point)))
4071 if (MINI_WINDOW_P (w))
4074 new_point = start_of_last_line (w, startp);
4077 BUF_SET_PT (b, new_point);
4079 set_marker_restricted (w->pointm[CURRENT_DISP],
4080 make_int (new_point),
4085 else /* value == 0 && direction == -1 */
4087 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4089 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4095 int movement = next_screen_context_lines - 1;
4096 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4097 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4099 start_with_point_on_display_line (w, bottom,
4100 -1 - (movement - vtarget));
4102 if (startp >= old_startp)
4103 startp = vmotion (w, old_startp, -1, NULL);
4105 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4108 w->start_at_line_beg = beginning_of_line_p (b, startp);
4109 MARK_WINDOWS_CHANGED (w);
4111 if (!point_would_be_visible (w, startp, XINT (point)))
4113 Bufpos new_point = start_of_last_line (w, startp);
4116 BUF_SET_PT (b, new_point);
4118 set_marker_restricted (w->pointm[CURRENT_DISP],
4119 make_int (new_point),
4127 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4128 Scroll text of current window upward ARG lines; or near full screen if no ARG.
4129 A near full screen is `next-screen-context-lines' less than a full screen.
4130 Negative ARG means scroll downward.
4131 When calling from a program, supply a number as argument or nil.
4132 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4133 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4138 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4142 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4143 Scroll text of current window downward ARG lines; or near full screen if no ARG.
4144 A near full screen is `next-screen-context-lines' less than a full screen.
4145 Negative ARG means scroll upward.
4146 When calling from a program, supply a number as argument or nil.
4147 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4148 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4153 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4157 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4158 Return the other window for "other window scroll" commands.
4159 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4160 specifies the window.
4161 If `other-window-scroll-buffer' is non-nil, a window
4162 showing that buffer is used.
4167 Lisp_Object selected_window = Fselected_window (Qnil);
4169 if (MINI_WINDOW_P (XWINDOW (selected_window))
4170 && !NILP (Vminibuffer_scroll_window))
4171 window = Vminibuffer_scroll_window;
4172 /* If buffer is specified, scroll that buffer. */
4173 else if (!NILP (Vother_window_scroll_buffer))
4175 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4177 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4181 /* Nothing specified; look for a neighboring window on the same
4183 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4185 if (EQ (window, selected_window))
4186 /* That didn't get us anywhere; look for a window on another
4189 window = Fnext_window (window, Qnil, Qt, Qnil);
4190 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4191 && ! EQ (window, selected_window));
4194 CHECK_LIVE_WINDOW (window);
4196 if (EQ (window, selected_window))
4197 error ("There is no other window");
4202 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4203 Scroll next window upward ARG lines; or near full frame if no ARG.
4204 The next window is the one below the current one; or the one at the top
4205 if the current one is at the bottom. Negative ARG means scroll downward.
4206 When calling from a program, supply a number as argument or nil.
4208 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4209 specifies the window to scroll.
4210 If `other-window-scroll-buffer' is non-nil, scroll the window
4211 showing that buffer, popping the buffer up if necessary.
4215 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4219 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4220 Scroll selected window display ARG columns left.
4221 Default for ARG is window width minus 2.
4225 Lisp_Object window = Fselected_window (Qnil);
4226 struct window *w = XWINDOW (window);
4229 arg = make_int (window_char_width (w, 0) - 2);
4231 arg = Fprefix_numeric_value (arg);
4233 return Fset_window_hscroll (window, make_int (w->hscroll + XINT (arg)));
4236 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4237 Scroll selected window display ARG columns right.
4238 Default for ARG is window width minus 2.
4242 Lisp_Object window = Fselected_window (Qnil);
4243 struct window *w = XWINDOW (window);
4246 arg = make_int (window_char_width (w, 0) - 2);
4248 arg = Fprefix_numeric_value (arg);
4250 return Fset_window_hscroll (window, make_int (w->hscroll - XINT (arg)));
4253 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4254 Center point in WINDOW. With N, put point on line N.
4255 The desired position of point is always relative to the window.
4256 If WINDOW is nil, the selected window is used.
4260 struct window *w = decode_window (window);
4261 struct buffer *b = XBUFFER (w->buffer);
4262 Bufpos opoint = BUF_PT (b);
4266 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4269 n = Fprefix_numeric_value (n);
4271 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4274 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4276 w->start_at_line_beg = beginning_of_line_p (b, startp);
4278 MARK_WINDOWS_CHANGED (w);
4282 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4283 Position point relative to WINDOW.
4284 With no argument, position text at center of window.
4285 An argument specifies window line; zero means top of window,
4286 negative means relative to bottom of window.
4287 If WINDOW is nil, the selected window is used.
4294 Bufpos start, new_point;
4297 /* Don't use decode_window() because we need the new value of
4300 window = Fselected_window (Qnil);
4302 CHECK_WINDOW (window);
4303 w = XWINDOW (window);
4304 b = XBUFFER (w->buffer);
4306 height = window_displayed_height (w);
4307 selected = EQ (window, Fselected_window (w->frame));
4313 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4314 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4316 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4319 BUF_SET_PT (b, new_point);
4321 Fset_window_point (window, make_int (new_point));
4323 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4327 start = marker_position (w->start[CURRENT_DISP]);
4328 if (start < BUF_BEGV (b))
4329 start = BUF_BEGV (b);
4330 else if (start > BUF_ZV (b))
4334 new_point = BUF_PT (b);
4336 new_point = marker_position (w->pointm[CURRENT_DISP]);
4338 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4341 BUF_SET_PT (b, new_point);
4343 Fset_window_point (window, make_int (new_point));
4345 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4348 return make_int (retval);
4352 /* #### Is this going to work right when at eob? */
4353 arg = Fprefix_numeric_value (arg);
4355 XSETINT (arg, XINT (arg) + height);
4358 start = marker_position (w->start[CURRENT_DISP]);
4359 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4362 new_point = BUF_PT (b);
4364 new_point = marker_position (w->pointm[CURRENT_DISP]);
4366 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4369 BUF_SET_PT (b, new_point);
4371 Fset_window_point (window, make_int (new_point));
4373 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4375 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4381 BUF_SET_PT (b, start);
4383 Fset_window_point (window, make_int (start));
4387 return Fvertical_motion (arg, window, Qnil);
4391 new_point = vmotion (XWINDOW (window),
4392 marker_position (w->pointm[CURRENT_DISP]),
4394 Fset_window_point (window, make_int (new_point));
4395 return make_int (vpos);
4401 map_windows_1 (Lisp_Object window,
4402 int (*mapfun) (struct window *w, void *closure),
4405 for (; !NILP (window); window = XWINDOW (window)->next)
4408 struct window *w = XWINDOW (window);
4410 if (!NILP (w->vchild))
4411 retval = map_windows_1 (w->vchild, mapfun, closure);
4412 else if (!NILP (w->hchild))
4413 retval = map_windows_1 (w->hchild, mapfun, closure);
4415 retval = (mapfun) (w, closure);
4424 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4425 invocation of MAPFUN. If any invocation of MAPFUN returns
4426 non-zero, the mapping is halted. Otherwise, map_windows() maps
4427 over all windows in F.
4429 If MAPFUN creates or deletes windows, the behaviour is undefined. */
4432 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4436 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4439 Lisp_Object frmcons, devcons, concons;
4441 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4443 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4455 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4458 w->shadow_thickness_changed = 1;
4459 MARK_WINDOWS_CHANGED (w);
4463 vertical_divider_changed_in_window (Lisp_Object specifier,
4467 MARK_WINDOWS_CHANGED (w);
4468 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4471 /* also used in scrollbar.c */
4473 some_window_value_changed (Lisp_Object specifier, struct window *w,
4476 MARK_WINDOWS_CHANGED (w);
4479 #ifdef MEMORY_USAGE_STATS
4485 #ifdef HAVE_SCROLLBARS
4489 int other_redisplay;
4494 compute_window_mirror_usage (struct window_mirror *mir,
4495 struct window_stats *stats,
4496 struct overhead_stats *ovstats)
4500 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4502 #ifdef HAVE_SCROLLBARS
4504 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4507 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4510 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4513 #endif /* HAVE_SCROLLBARS */
4514 stats->other_redisplay +=
4515 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4516 stats->other_redisplay +=
4517 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4521 compute_window_usage (struct window *w, struct window_stats *stats,
4522 struct overhead_stats *ovstats)
4525 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4526 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4527 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4528 stats->line_start +=
4529 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4530 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4533 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4534 Return stats about the memory usage of window WINDOW.
4535 The values returned are in the form of an alist of usage types and byte
4536 counts. The byte counts attempt to encompass all the memory used
4537 by the window (separate from the memory logically associated with a
4538 buffer or frame), including internal structures and any malloc()
4539 overhead associated with them. In practice, the byte counts are
4540 underestimated because certain memory usage is very hard to determine
4541 \(e.g. the amount of memory used inside the Xt library or inside the
4542 X server) and because there is other stuff that might logically
4543 be associated with a window, buffer, or frame (e.g. window configurations,
4544 glyphs) but should not obviously be included in the usage counts.
4546 Multiple slices of the total memory usage may be returned, separated
4547 by a nil. Each slice represents a particular view of the memory, a
4548 particular way of partitioning it into groups. Within a slice, there
4549 is no overlap between the groups of memory, and each slice collectively
4550 represents all the memory concerned.
4554 struct window_stats stats;
4555 struct overhead_stats ovstats;
4556 Lisp_Object val = Qnil;
4558 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4560 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4562 val = acons (Qface_cache, make_int (stats.face), val);
4563 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4564 #ifdef HAVE_SCROLLBARS
4565 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4567 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4568 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4569 val = acons (Qother, make_int (stats.other), val);
4570 val = Fcons (Qnil, val);
4571 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4572 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4573 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4575 return Fnreverse (val);
4578 #endif /* MEMORY_USAGE_STATS */
4581 /************************************************************************/
4582 /* Window configurations */
4583 /************************************************************************/
4585 /* #### This window configuration stuff has had serious bugs lurking in it
4586 for years; it would be a -huge- win if this was reimplemented in lisp.
4589 /* If you add anything to this structure make sure saved_window_equal
4593 Lisp_Object window; /* window */
4594 Lisp_Object buffer; /* buffer */
4595 Lisp_Object start; /* copied marker */
4596 Lisp_Object pointm; /* copied marker */
4597 Lisp_Object sb_point; /* copied marker */
4598 Lisp_Object mark; /* copied marker */
4604 int modeline_hscroll;
4605 int parent_index; /* index into saved_windows */
4606 int prev_index; /* index into saved_windows */
4607 char start_at_line_beg; /* boolean */
4609 #define WINDOW_SLOT_DECLARATION
4610 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4611 #include "winslots.h"
4614 /* If you add anything to this structure make sure window_config_equal
4616 struct window_config
4618 struct lcrecord_header header;
4622 Lisp_Object selected_frame;
4624 Lisp_Object current_window;
4625 Lisp_Object current_buffer;
4626 Lisp_Object minibuffer_scroll_window;
4627 Lisp_Object root_window;
4628 /* Record the values of window-min-width and window-min-height
4629 so that window sizes remain consistent with them. */
4630 int min_width, min_height;
4631 int saved_windows_count;
4632 /* Zero-sized arrays aren't ANSI C */
4633 struct saved_window saved_windows[1];
4636 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4637 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4638 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4639 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4640 #define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
4641 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4644 mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
4646 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4648 ((markobj) (config->current_window));
4649 ((markobj) (config->current_buffer));
4650 ((markobj) (config->minibuffer_scroll_window));
4651 ((markobj) (config->root_window));
4653 for (i = 0; i < config->saved_windows_count; i++)
4655 struct saved_window *s = SAVED_WINDOW_N (config, i);
4656 ((markobj) (s->window));
4657 ((markobj) (s->buffer));
4658 ((markobj) (s->start));
4659 ((markobj) (s->pointm));
4660 ((markobj) (s->sb_point));
4661 ((markobj) (s->mark));
4663 /* #### This looked like this. I do not see why specifier cached
4664 values should not be marked, as such specifiers as toolbars
4665 might have GC-able instances. Freed configs are not marked,
4666 aren't they? -- kkm */
4667 ((markobj) (s->dedicated));
4669 #define WINDOW_SLOT(slot, compare) ((markobj) (s->slot))
4670 #include "winslots.h"
4677 sizeof_window_config_for_n_windows (int n)
4679 return (sizeof (struct window_config) +
4680 /* n - 1 because zero-sized arrays aren't ANSI C */
4681 (n - 1) *sizeof (struct saved_window));
4685 sizeof_window_config (CONST void *h)
4687 CONST struct window_config *c = (CONST struct window_config *) h;
4688 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4692 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4694 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4697 error ("printing unreadable object #<window-configuration 0x%x>",
4698 config->header.uid);
4699 write_c_string ("#<window-configuration ", printcharfun);
4700 sprintf (buf, "0x%x>", config->header.uid);
4701 write_c_string (buf, printcharfun);
4704 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4705 window_configuration,
4707 print_window_config,
4708 0, 0, 0, sizeof_window_config,
4709 struct window_config);
4712 /* Returns a boolean indicating whether the two saved windows are
4715 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4717 #define WINDOW_SLOT(slot, compare) \
4718 if (!compare (win1->slot, win2->slot)) \
4720 #include "winslots.h"
4723 EQ (win1->window, win2->window) &&
4724 EQ (win1->buffer, win2->buffer) &&
4725 internal_equal (win1->start, win2->start, 0) &&
4726 internal_equal (win1->pointm, win2->pointm, 0) &&
4727 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4728 internal_equal (win1->mark, win2->mark, 0) &&
4729 win1->pixel_left == win2->pixel_left &&
4730 win1->pixel_top == win2->pixel_top &&
4731 win1->pixel_width == win2->pixel_width &&
4732 win1->pixel_height == win2->pixel_height &&
4733 win1->hscroll == win2->hscroll &&
4734 win1->modeline_hscroll == win2->modeline_hscroll &&
4735 win1->parent_index == win2->parent_index &&
4736 win1->prev_index == win2->prev_index &&
4737 win1->start_at_line_beg == win2->start_at_line_beg;
4740 /* Returns a boolean indicating whether the two given configurations
4743 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4745 struct window_config *fig1, *fig2;
4748 /* First check if they are truly the same. */
4749 if (EQ (conf1, conf2))
4752 fig1 = XWINDOW_CONFIGURATION (conf1);
4753 fig2 = XWINDOW_CONFIGURATION (conf2);
4755 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4756 EQ (fig1->current_window, fig2->current_window) &&
4757 EQ (fig1->current_buffer, fig2->current_buffer) &&
4758 EQ (fig1->root_window, fig2->root_window) &&
4759 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window) &&
4760 fig1->frame_width == fig2->frame_width &&
4761 fig1->frame_height == fig2->frame_height))
4764 for (i = 0; i < fig1->saved_windows_count; i++)
4766 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4767 SAVED_WINDOW_N (fig2, i)))
4774 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4775 Return t if OBJECT is a window-configuration object.
4779 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4783 mark_windows_in_use_closure (struct window *w, void *closure)
4785 int mark = *(int *)closure;
4786 w->config_mark = mark;
4791 mark_windows_in_use (struct frame *f, int mark)
4793 map_windows (f, mark_windows_in_use_closure, &mark);
4796 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4798 free_window_configuration (Lisp_Object window_config)
4801 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4803 /* Free all the markers. It's not completely necessary that
4804 we do this (window configs sitting in a free list aren't
4805 marked normally so the markers wouldn't be marked anyway)
4806 but it's more efficient. */
4807 for (i = 0; i < config->saved_windows_count; i++)
4809 struct saved_window *p = SAVED_WINDOW_N (config, i);
4811 if (!NILP (p->pointm))
4813 free_marker (XMARKER (p->pointm));
4816 if (!NILP (p->start))
4818 free_marker (XMARKER (p->start));
4821 if (!NILP (p->sb_point))
4823 free_marker (XMARKER (p->sb_point));
4826 if (!NILP (p->mark))
4828 free_marker (XMARKER (p->mark));
4833 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4834 free_managed_lcrecord (Vwindow_configuration_free_list
4835 [config->saved_windows_count - 1],
4841 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4842 Set the configuration of windows and buffers as specified by CONFIGURATION.
4843 CONFIGURATION must be a value previously returned
4844 by `current-window-configuration' (which see).
4849 struct window_config *config;
4850 struct saved_window *p;
4851 Lisp_Object new_current_buffer;
4855 struct gcpro gcpro1;
4856 Lisp_Object old_window_config;
4857 int previous_frame_height;
4858 int previous_frame_width;
4859 int specpdl_count = specpdl_depth ();
4861 GCPRO1 (configuration);
4863 CHECK_WINDOW_CONFIGURATION (configuration);
4864 config = XWINDOW_CONFIGURATION (configuration);
4866 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4869 /* Do not signal an error here if the frame was deleted. There are
4870 reasonable cases where we could get here with a deleted frame and
4871 just want to do close to nothing instead. */
4873 if (FRAME_LIVE_P (f))
4875 /* restore the frame characteristics */
4877 new_current_buffer = config->current_buffer;
4878 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4879 new_current_buffer = Qnil;
4882 * Assumed precondition: w->config_mark = 0 for all w
4883 * This procedure should ensure this is true by the time it exits
4884 * to ensure the precondition for future calls.
4886 * We use w->config_mark to know whether we're modifying a
4887 * window that is currently visible on the frame (#### we
4888 * should just be able to check whether the window is dead
4889 * or not, but this way is safer?). As we process each
4890 * window, we set its config_mark to 0. At the end, we
4891 * go through all the windows that used to be on the frame,
4892 * set each one's config_mark to 0 (to maintain the
4893 * assumed precondition) and delete each one that's no
4896 * #### Using a window-configuration to keep track of
4897 * the current windows is wasteful. All we need is the
4898 * list of windows, so we could just use a dynarr.
4900 old_window_config = Fcurrent_window_configuration (frame);
4902 /* If the new configuration is already equal to the old, then stop
4903 right here. This saves the work below and it also saves
4904 triggering a full redisplay of this window. This is a huge win
4905 when using the mouse since the mode motion code uses
4906 save-window-excursion extensively but will rarely cause the
4907 configuration to actually change. */
4908 if (window_config_equal (configuration, old_window_config))
4910 free_window_configuration (old_window_config);
4915 /* We can't quit or even check for quit because that may cause
4916 investigation of the frame state, which may crash if the frame is
4917 in an inconsistent state. */
4918 begin_dont_check_for_quit ();
4919 record_unwind_protect (free_window_configuration, old_window_config);
4921 mark_windows_in_use (f, 1);
4923 previous_frame_width = FRAME_WIDTH (f);
4924 previous_frame_height = FRAME_HEIGHT (f);
4925 /* If the frame has been resized since this window configuration was
4926 made, we change the frame to the size specified in the
4927 configuration, restore the configuration, and then resize it
4928 back. We keep track of the prevailing height in these variables. */
4929 if (config->frame_height != FRAME_HEIGHT (f)
4930 || config->frame_width != FRAME_WIDTH (f))
4931 change_frame_size (f, config->frame_height, config->frame_width, 0);
4933 /* Temporarily avoid any problems with windows that are smaller
4934 than they are supposed to be. */
4935 window_min_height = 1;
4936 window_min_width = 1;
4938 /* OK, now restore all the windows in the window config.
4939 This may involve "undeleting" windows, since the
4940 windows in the window config may be deleted.
4942 for (k = 0; k < config->saved_windows_count; k++)
4944 p = SAVED_WINDOW_N (config, k);
4945 w = XWINDOW (p->window);
4948 /* The window might be dead. In this case, its redisplay
4949 structures were freed, so we need to reallocate them. */
4950 if (!w->face_cachels)
4952 w->face_cachels = Dynarr_new (face_cachel);
4953 reset_face_cachels (w);
4955 if (!w->glyph_cachels)
4956 w->glyph_cachels = Dynarr_new (glyph_cachel);
4957 if (!w->line_start_cache)
4958 w->line_start_cache = Dynarr_new (line_start_cache);
4961 if (p->parent_index >= 0)
4962 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
4966 if (p->prev_index >= 0)
4968 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
4970 /* This is true for a minibuffer-only frame. */
4971 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
4974 XWINDOW (w->prev)->next = p->window;
4979 if (!NILP (w->parent))
4981 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
4983 XWINDOW (w->parent)->vchild = p->window;
4984 XWINDOW (w->parent)->hchild = Qnil;
4988 XWINDOW (w->parent)->hchild = p->window;
4989 XWINDOW (w->parent)->vchild = Qnil;
4993 if (!w->config_mark)
4995 /* #### This should be equivalent to the window previously
4996 having been dead. If we're brave, we'll put in an
4997 assertion to this effect. */
4998 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5000 else /* if (!EQ (w->buffer, p->buffer)) */
5002 /* With the new redisplay we let it know that a change has
5003 been made and it will take care of the rest. If we don't
5004 tell it something has possibly changed it could lead to
5005 incorrect display. */
5006 MARK_WINDOWS_CHANGED (w);
5009 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5010 WINDOW_TOP (w) = WINDOW_TOP (p);
5011 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5012 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5013 w->hscroll = p->hscroll;
5014 w->modeline_hscroll = p->modeline_hscroll;
5015 w->line_cache_last_updated = Qzero;
5016 SET_LAST_MODIFIED (w, 1);
5017 SET_LAST_FACECHANGE (w);
5020 #define WINDOW_SLOT(slot, compare) w->slot = p->slot;
5021 #include "winslots.h"
5023 /* Reinstall the saved buffer and pointers into it. */
5024 if (NILP (p->buffer))
5025 w->buffer = p->buffer;
5028 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5029 /* If saved buffer is alive, install it. */
5031 w->buffer = p->buffer;
5032 w->start_at_line_beg = p->start_at_line_beg;
5033 set_marker_restricted (w->start[CURRENT_DISP],
5034 Fmarker_position (p->start),
5036 set_marker_restricted (w->pointm[CURRENT_DISP],
5037 Fmarker_position (p->pointm),
5039 set_marker_restricted (w->sb_point,
5040 Fmarker_position (p->sb_point),
5042 Fset_marker (XBUFFER (w->buffer)->mark,
5043 Fmarker_position (p->mark), w->buffer);
5045 /* As documented in Fcurrent_window_configuration, don't
5046 save the location of point in the buffer which was current
5047 when the window configuration was recorded. */
5048 if (!EQ (p->buffer, new_current_buffer) &&
5049 XBUFFER (p->buffer) == current_buffer)
5050 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5052 else if (NILP (w->buffer) ||
5053 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5054 /* Else if window's old buffer is dead too, get a live one. */
5056 /* #### The following line makes me nervous... */
5057 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5058 w->buffer = Fget_buffer_create (QSscratch);
5059 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5060 /* This will set the markers to beginning of visible
5062 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5063 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5065 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5066 w->start_at_line_beg = 1;
5069 /* Keeping window's old buffer; make sure the markers
5072 /* Set window markers at start of visible range. */
5073 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5074 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5076 if (XMARKER (w->sb_point)->buffer == 0)
5077 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5078 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5079 set_marker_restricted (w->pointm[CURRENT_DISP],
5081 (BUF_PT (XBUFFER (w->buffer))),
5083 w->start_at_line_beg = 1;
5088 FRAME_ROOT_WINDOW (f) = config->root_window;
5089 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5090 then calls do_switch_frame() below to select the frame that was
5091 recorded in the window config as being selected.
5093 Instead, we don't ever change the selected frame, and either
5094 call Fselect_window() below if the window config's frame is
5095 currently selected, or just set the selected window of the
5096 window config's frame. */
5098 /* Set the frame height to the value it had before this function. */
5099 if (previous_frame_height != FRAME_HEIGHT (f)
5100 || previous_frame_width != FRAME_WIDTH (f))
5101 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5103 /* If restoring in the current frame make the window current,
5104 otherwise just update the frame selected_window slot to be
5105 the restored current_window. */
5106 if (f == selected_frame ())
5108 /* When using `pop-window-configuration', often the minibuffer
5109 ends up as the selected window even though it's not active ...
5110 I really don't know the cause of this, but it should never
5111 happen. This kludge should fix it.
5113 #### Find out why this is really going wrong. */
5114 if (!minibuf_level &&
5115 MINI_WINDOW_P (XWINDOW (config->current_window)))
5116 Fselect_window (Fnext_window (config->current_window,
5120 Fselect_window (config->current_window, Qnil);
5121 if (!NILP (new_current_buffer))
5122 Fset_buffer (new_current_buffer);
5124 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5127 set_frame_selected_window (f, config->current_window);
5130 old_window_config = Qnil; /* Warning suppression */
5132 /* Restore the minimum heights recorded in the configuration. */
5133 window_min_height = config->min_height;
5134 window_min_width = config->min_width;
5137 /* see above comment */
5138 /* Fselect_window will have made f the selected frame, so we
5139 reselect the proper frame here. Fhandle_switch_frame will change the
5140 selected window too, but that doesn't make the call to
5141 Fselect_window above totally superfluous; it still sets f's
5143 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5144 do_switch_frame (config->selected_frame, Qnil, 0);
5147 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5149 if (FRAME_LIVE_P (f))
5151 /* Do this before calling recompute_all_cached_specifiers_in_window()
5152 so that things like redisplay_redraw_cursor() won't abort due
5153 to no window mirror present. */
5154 f->mirror_dirty = 1;
5156 config = XWINDOW_CONFIGURATION (old_window_config);
5157 for (k = 0; k < config->saved_windows_count; k++)
5159 p = SAVED_WINDOW_N (config, k);
5160 w = XWINDOW (p->window);
5161 /* Remember, we set w->config_mark on all currently visible
5162 windows, and reset it on all newly visible windows.
5163 Any windows still marked need to be deleted. */
5166 mark_window_as_deleted (w);
5171 /* We just potentially changed the window's buffer and
5172 potentially turned a dead window into a live one,
5173 so we need to recompute the cached specifier values. */
5174 recompute_all_cached_specifiers_in_window (w);
5179 /* Now restore things, when everything else if OK. */
5181 unbind_to (specpdl_count, Qnil);
5188 /* Mark all subwindows of a window as deleted. The argument
5189 W is actually the subwindow tree of the window in question. */
5192 delete_all_subwindows (struct window *w)
5194 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5195 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5196 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5198 mark_window_as_deleted (w);
5203 count_windows (struct window *window)
5206 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5207 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5208 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5212 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5215 for (j = 0; j < lim; j++)
5217 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5221 return 0; /* suppress compiler warning */
5225 save_window_save (Lisp_Object window, struct window_config *config, int i)
5229 for (; !NILP (window); window = w->next)
5231 struct saved_window *p = SAVED_WINDOW_N (config, i);
5233 w = XWINDOW (window);
5236 p->buffer = w->buffer;
5237 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5238 WINDOW_TOP (p) = WINDOW_TOP (w);
5239 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5240 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5241 p->hscroll = w->hscroll;
5242 p->modeline_hscroll = w->modeline_hscroll;
5244 #define WINDOW_SLOT(slot, compare) p->slot = w->slot;
5245 #include "winslots.h"
5247 if (!NILP (w->buffer))
5249 /* Save w's value of point in the window configuration.
5250 If w is the selected window, then get the value of point
5251 from the buffer; pointm is garbage in the selected window. */
5252 if (EQ (window, Fselected_window (Qnil)))
5254 p->pointm = noseeum_make_marker ();
5255 Fset_marker (p->pointm,
5256 make_int (BUF_PT (XBUFFER (w->buffer))),
5260 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5262 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5263 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5264 p->start_at_line_beg = w->start_at_line_beg;
5266 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5274 p->start_at_line_beg = 0;
5277 if (NILP (w->parent))
5278 p->parent_index = -1;
5280 p->parent_index = saved_window_index (w->parent, config, i);
5284 p->prev_index = saved_window_index (w->prev, config, i);
5285 if (!NILP (w->vchild))
5286 i = save_window_save (w->vchild, config, i);
5287 if (!NILP (w->hchild))
5288 i = save_window_save (w->hchild, config, i);
5295 /* Added to doc string:
5297 This also records the currently selected frame, and FRAME's focus
5298 redirection (see `redirect-frame-focus').
5303 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5304 Return an object representing the current window configuration of FRAME.
5305 If FRAME is nil or omitted, use the selected frame.
5306 This describes the number of windows, their sizes and current buffers,
5307 and for each displayed buffer, where display starts, and the positions of
5308 point and mark. An exception is made for point in the current buffer:
5309 its value is -not- saved.
5314 struct frame *f = decode_frame (frame);
5315 struct window_config *config;
5316 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5318 if (n_windows <= countof (Vwindow_configuration_free_list))
5319 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5320 (Vwindow_configuration_free_list
5323 /* More than ten windows; just allocate directly */
5324 config = (struct window_config *)
5325 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5326 lrecord_window_configuration);
5327 XSETWINDOW_CONFIGURATION (result, config);
5329 config->frame_width = FRAME_WIDTH (f);
5330 config->frame_height = FRAME_HEIGHT (f);
5331 config->current_window = FRAME_SELECTED_WINDOW (f);
5332 XSETBUFFER (config->current_buffer, current_buffer);
5333 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5334 config->root_window = FRAME_ROOT_WINDOW (f);
5335 config->min_height = window_min_height;
5336 config->min_width = window_min_width;
5337 config->saved_windows_count = n_windows;
5338 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5343 save_window_excursion_unwind (Lisp_Object window_config)
5345 Lisp_Object val = Fset_window_configuration (window_config);
5346 free_window_configuration (window_config);
5350 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5351 Execute body, preserving window sizes and contents.
5352 Restores which buffer appears in which window, where display starts,
5353 as well as the current buffer.
5354 Does not restore the value of point in current buffer.
5358 /* This function can GC */
5360 int speccount = specpdl_depth ();
5362 record_unwind_protect (save_window_excursion_unwind,
5363 Fcurrent_window_configuration (Qnil));
5364 val = Fprogn (args);
5365 return unbind_to (speccount, val);
5370 /* This is short and simple in elisp, but... it was written to debug
5371 problems purely on the C side. That is where we need to call it so
5374 debug_print_window (Lisp_Object window, int level)
5377 Lisp_Object child = Fwindow_first_vchild (window);
5380 child = Fwindow_first_hchild (window);
5382 for (i = level; i > 0; i--)
5383 putc ('\t', stderr);
5385 fputs ("#<window", stderr);
5387 Lisp_Object buffer = XWINDOW (window)->buffer;
5388 if (!NILP (buffer) && BUFFERP (buffer))
5389 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5391 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5393 while (!NILP (child))
5395 debug_print_window (child, level + 1);
5396 child = Fwindow_next_child (child);
5400 void debug_print_windows (struct frame *f);
5402 debug_print_windows (struct frame *f)
5404 debug_print_window (f->root_window, 0);
5405 putc ('\n', stderr);
5407 #endif /* DEBUG_XEMACS */
5410 /************************************************************************/
5411 /* initialization */
5412 /************************************************************************/
5415 syms_of_window (void)
5417 defsymbol (&Qwindowp, "windowp");
5418 defsymbol (&Qwindow_live_p, "window-live-p");
5419 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5420 defsymbol (&Qscroll_up, "scroll-up");
5421 defsymbol (&Qscroll_down, "scroll-down");
5422 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5423 defsymbol (&Qdisplay_buffer, "display-buffer");
5425 #ifdef MEMORY_USAGE_STATS
5426 defsymbol (&Qface_cache, "face-cache");
5427 defsymbol (&Qglyph_cache, "glyph-cache");
5428 defsymbol (&Qline_start_cache, "line-start-cache");
5429 #ifdef HAVE_SCROLLBARS
5430 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5432 defsymbol (&Qother_redisplay, "other-redisplay");
5433 /* Qother in general.c */
5436 DEFSUBR (Fselected_window);
5437 DEFSUBR (Fminibuffer_window);
5438 DEFSUBR (Fwindow_minibuffer_p);
5440 DEFSUBR (Fwindow_live_p);
5441 DEFSUBR (Fwindow_first_hchild);
5442 DEFSUBR (Fwindow_first_vchild);
5443 DEFSUBR (Fwindow_next_child);
5444 DEFSUBR (Fwindow_previous_child);
5445 DEFSUBR (Fwindow_parent);
5446 DEFSUBR (Fwindow_lowest_p);
5447 DEFSUBR (Fwindow_highest_p);
5448 DEFSUBR (Fwindow_leftmost_p);
5449 DEFSUBR (Fwindow_rightmost_p);
5450 DEFSUBR (Fpos_visible_in_window_p);
5451 DEFSUBR (Fwindow_buffer);
5452 DEFSUBR (Fwindow_frame);
5453 DEFSUBR (Fwindow_height);
5454 DEFSUBR (Fwindow_displayed_height);
5455 DEFSUBR (Fwindow_width);
5456 DEFSUBR (Fwindow_pixel_height);
5457 DEFSUBR (Fwindow_pixel_width);
5458 DEFSUBR (Fwindow_text_area_pixel_height);
5459 DEFSUBR (Fwindow_displayed_text_pixel_height);
5460 DEFSUBR (Fwindow_text_area_pixel_width);
5461 DEFSUBR (Fwindow_hscroll);
5462 #ifdef MODELINE_IS_SCROLLABLE
5463 DEFSUBR (Fmodeline_hscroll);
5464 DEFSUBR (Fset_modeline_hscroll);
5465 #endif /* MODELINE_IS_SCROLLABLE */
5466 #if 0 /* bogus FSF crock */
5467 DEFSUBR (Fwindow_redisplay_end_trigger);
5468 DEFSUBR (Fset_window_redisplay_end_trigger);
5470 DEFSUBR (Fset_window_hscroll);
5471 DEFSUBR (Fwindow_pixel_edges);
5472 DEFSUBR (Fwindow_text_area_pixel_edges);
5473 DEFSUBR (Fwindow_point);
5474 DEFSUBR (Fwindow_start);
5475 DEFSUBR (Fwindow_end);
5476 DEFSUBR (Fset_window_point);
5477 DEFSUBR (Fset_window_start);
5478 DEFSUBR (Fwindow_dedicated_p);
5479 DEFSUBR (Fset_window_dedicated_p);
5480 DEFSUBR (Fnext_window);
5481 DEFSUBR (Fprevious_window);
5482 DEFSUBR (Fnext_vertical_window);
5483 DEFSUBR (Fother_window);
5484 DEFSUBR (Fget_lru_window);
5485 DEFSUBR (Fget_largest_window);
5486 DEFSUBR (Fget_buffer_window);
5487 DEFSUBR (Fwindow_left_margin_pixel_width);
5488 DEFSUBR (Fwindow_right_margin_pixel_width);
5489 DEFSUBR (Fdelete_other_windows);
5490 DEFSUBR (Fdelete_windows_on);
5491 DEFSUBR (Freplace_buffer_in_windows);
5492 DEFSUBR (Fdelete_window);
5493 DEFSUBR (Fset_window_buffer);
5494 DEFSUBR (Fselect_window);
5495 DEFSUBR (Fsplit_window);
5496 DEFSUBR (Fenlarge_window);
5497 DEFSUBR (Fenlarge_window_pixels);
5498 DEFSUBR (Fshrink_window);
5499 DEFSUBR (Fshrink_window_pixels);
5500 DEFSUBR (Fscroll_up);
5501 DEFSUBR (Fscroll_down);
5502 DEFSUBR (Fscroll_left);
5503 DEFSUBR (Fscroll_right);
5504 DEFSUBR (Fother_window_for_scrolling);
5505 DEFSUBR (Fscroll_other_window);
5506 DEFSUBR (Fcenter_to_window_line);
5507 DEFSUBR (Fmove_to_window_line);
5508 #ifdef MEMORY_USAGE_STATS
5509 DEFSUBR (Fwindow_memory_usage);
5511 DEFSUBR (Fwindow_configuration_p);
5512 DEFSUBR (Fset_window_configuration);
5513 DEFSUBR (Fcurrent_window_configuration);
5514 DEFSUBR (Fsave_window_excursion);
5518 vars_of_window (void)
5520 /* Make sure all windows get marked */
5521 minibuf_window = Qnil;
5522 staticpro (&minibuf_window);
5524 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5525 *Non-nil means to scroll if point lands on a line which is clipped.
5527 scroll_on_clipped_lines = 1;
5529 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5530 See `temp-buffer-show-function'.
5532 Vtemp_buffer_show_hook = Qnil;
5534 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5535 Non-nil means call as function to display a help buffer.
5536 The function is called with one argument, the buffer to be displayed.
5537 Used by `with-output-to-temp-buffer'.
5538 If this function is used, then it must do the entire job of showing
5539 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5541 Vtemp_buffer_show_function = Qnil;
5543 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5544 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5546 Vminibuffer_scroll_window = Qnil;
5548 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5549 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5551 Vother_window_scroll_buffer = Qnil;
5553 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5554 *Number of lines of continuity when scrolling by screenfuls.
5556 next_screen_context_lines = 2;
5558 DEFVAR_INT ("window-min-height", &window_min_height /*
5559 *Delete any window less than this tall (including its modeline).
5561 window_min_height = 4;
5563 DEFVAR_INT ("window-min-width", &window_min_width /*
5564 *Delete any window less than this wide.
5566 window_min_width = 10;
5571 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5573 Vwindow_configuration_free_list[i] =
5574 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5575 lrecord_window_configuration);
5576 staticpro (&Vwindow_configuration_free_list[i]);
5582 specifier_vars_of_window (void)
5584 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5585 *How thick to draw 3D shadows around modelines.
5586 If this is set to 0, modelines will be the traditional 2D. Sizes above
5587 10 will be accepted but the maximum thickness that will be drawn is 10.
5588 This is a specifier; use `set-specifier' to change it.
5590 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5591 /* The initial value for modeline-shadow-thickness is 2, but if the
5592 user removes all specifications we provide a fallback value of 0,
5593 which is probably what was expected. */
5594 set_specifier_fallback (Vmodeline_shadow_thickness,
5595 list1 (Fcons (Qnil, Qzero)));
5596 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5598 set_specifier_caching (Vmodeline_shadow_thickness,
5599 slot_offset (struct window,
5600 modeline_shadow_thickness),
5601 modeline_shadow_thickness_changed,
5604 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5605 *Whether the modeline should be displayed.
5606 This is a specifier; use `set-specifier' to change it.
5608 Vhas_modeline_p = Fmake_specifier (Qboolean);
5609 set_specifier_fallback (Vhas_modeline_p,
5610 list1 (Fcons (Qnil, Qt)));
5611 set_specifier_caching (Vhas_modeline_p,
5612 slot_offset (struct window,
5614 /* #### It's strange that we need a special
5615 flag to indicate that the shadow-thickness
5616 has changed, but not one to indicate that
5617 the modeline has been turned off or on. */
5618 some_window_value_changed,
5621 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5622 &Vvertical_divider_always_visible_p /*
5623 *Should XEmacs always display vertical dividers between windows.
5625 When this is non-nil, vertical dividers are always shown, and are
5626 draggable. When it is nil, vertical dividers are shown only when
5627 there are no scrollbars in between windows, and are not draggable.
5629 This is a specifier; use `set-specifier' to change it.
5631 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5632 set_specifier_fallback (Vvertical_divider_always_visible_p,
5633 list1 (Fcons (Qnil, Qt)));
5634 set_specifier_caching (Vvertical_divider_always_visible_p,
5635 slot_offset (struct window,
5636 vertical_divider_always_visible_p),
5637 vertical_divider_changed_in_window,
5640 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5641 *How thick to draw 3D shadows around vertical dividers.
5642 This is a specifier; use `set-specifier' to change it.
5644 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5645 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5646 list1 (Fcons (Qnil, Qzero)));
5647 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5649 set_specifier_caching (Vvertical_divider_shadow_thickness,
5650 slot_offset (struct window,
5651 vertical_divider_shadow_thickness),
5652 vertical_divider_changed_in_window,
5654 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5655 *The width of the vertical dividers, not including shadows.
5657 For TTY windows, divider line is always one character wide. When
5658 instance of this specifier is zero in a TTY window, no divider is
5659 drawn at all between windows. When non-zero, a one character wide
5660 divider is displayed.
5662 This is a specifier; use `set-specifier' to change it.
5665 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5667 Lisp_Object fb = Qnil;
5669 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5671 #ifdef HAVE_X_WINDOWS
5672 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5674 #ifdef HAVE_MS_WINDOWS
5675 /* #### This should be made magic and made to obey system settings */
5676 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5678 set_specifier_fallback (Vvertical_divider_line_width, fb);
5680 set_specifier_caching (Vvertical_divider_line_width,
5681 slot_offset (struct window,
5682 vertical_divider_line_width),
5683 vertical_divider_changed_in_window,
5686 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5687 *How much space to leave around the vertical dividers.
5689 In TTY windows, spacing is always zero, and the value of this
5690 specifier is ignored.
5692 This is a specifier; use `set-specifier' to change it.
5694 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5696 Lisp_Object fb = Qnil;
5698 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5700 #ifdef HAVE_X_WINDOWS
5701 /* #### 3D dividers look great on MS Windows with spacing = 0.
5702 Should not the same value be the fallback under X? - kkm */
5703 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
5705 #ifdef HAVE_MS_WINDOWS
5706 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
5708 set_specifier_fallback (Vvertical_divider_spacing, fb);
5710 set_specifier_caching (Vvertical_divider_spacing,
5711 slot_offset (struct window,
5712 vertical_divider_spacing),
5713 vertical_divider_changed_in_window,