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"
43 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
44 Lisp_Object Qdisplay_buffer;
46 #ifdef MEMORY_USAGE_STATS
47 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
48 #ifdef HAVE_SCROLLBARS
49 Lisp_Object Qscrollbar_instances;
53 EXFUN (Fnext_window, 4);
55 static int window_pixel_width_to_char_width (struct window *w,
57 int include_margins_p);
58 static int window_char_width_to_pixel_width (struct window *w,
60 int include_margins_p);
61 static int window_pixel_height_to_char_height (struct window *w,
63 int include_gutters_p);
64 static int window_char_height_to_pixel_height (struct window *w,
66 int include_gutters_p);
67 static void change_window_height (struct window *w, int delta, int widthflag,
70 /* Thickness of shadow border around 3d modelines. */
71 Lisp_Object Vmodeline_shadow_thickness;
73 /* Whether vertical dividers are draggable and displayed */
74 Lisp_Object Vvertical_divider_always_visible_p;
76 /* Whether a modeline should be displayed. */
77 Lisp_Object Vhas_modeline_p;
79 /* Thickness of shadow border around vertical dividers. */
80 Lisp_Object Vvertical_divider_shadow_thickness;
82 /* Divider surface width (not counting 3-d borders) */
83 Lisp_Object Vvertical_divider_line_width;
85 /* Spacing between outer egde of divider border and window edge */
86 Lisp_Object Vvertical_divider_spacing;
88 /* How much to scroll by per-line. */
89 Lisp_Object Vwindow_pixel_scroll_increment;
91 /* Scroll if point lands on the bottom line and that line is partially
93 int scroll_on_clipped_lines;
95 /* The minibuffer window of the selected frame.
96 Note that you cannot test for minibufferness of an arbitrary window
97 by comparing against this; but you can test for minibufferness of
98 the selected window. */
99 Lisp_Object minibuf_window;
101 /* Non-nil means it is the window for C-M-v to scroll
102 when the minibuffer is selected. */
103 Lisp_Object Vminibuffer_scroll_window;
105 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
106 Lisp_Object Vother_window_scroll_buffer;
108 /* Non-nil means it's the function to call to display temp buffers. */
109 Lisp_Object Vtemp_buffer_show_function;
111 Lisp_Object Vtemp_buffer_show_hook;
113 /* If a window gets smaller than either of these, it is removed. */
114 int window_min_height;
115 int window_min_width;
117 /* Hook run at end of temp_output_buffer_show. */
118 Lisp_Object Qtemp_buffer_show_hook;
120 /* Number of lines of continuity in scrolling by screenfuls. */
121 int next_screen_context_lines;
123 /* List of freed window configurations with 1 - 10 windows. */
124 static Lisp_Object Vwindow_configuration_free_list[10];
126 #define SET_LAST_MODIFIED(w, cache_too) \
128 (w)->last_modified[CURRENT_DISP] = Qzero; \
129 (w)->last_modified[DESIRED_DISP] = Qzero; \
130 (w)->last_modified[CMOTION_DISP] = Qzero; \
132 (w)->line_cache_last_updated = Qzero; \
135 #define SET_LAST_FACECHANGE(w) \
137 (w)->last_facechange[CURRENT_DISP] = Qzero; \
138 (w)->last_facechange[DESIRED_DISP] = Qzero; \
139 (w)->last_facechange[CMOTION_DISP] = Qzero; \
143 #define MARK_DISP_VARIABLE(field) \
144 mark_object (window->field[CURRENT_DISP]); \
145 mark_object (window->field[DESIRED_DISP]); \
146 mark_object (window->field[CMOTION_DISP]);
149 mark_window (Lisp_Object obj)
151 struct window *window = XWINDOW (obj);
152 mark_object (window->frame);
153 mark_object (window->mini_p);
154 mark_object (window->next);
155 mark_object (window->prev);
156 mark_object (window->hchild);
157 mark_object (window->vchild);
158 mark_object (window->parent);
159 mark_object (window->buffer);
160 MARK_DISP_VARIABLE (start);
161 MARK_DISP_VARIABLE (pointm);
162 mark_object (window->sb_point); /* #### move to scrollbar.c? */
163 mark_object (window->use_time);
164 MARK_DISP_VARIABLE (last_modified);
165 MARK_DISP_VARIABLE (last_point);
166 MARK_DISP_VARIABLE (last_start);
167 MARK_DISP_VARIABLE (last_facechange);
168 mark_object (window->line_cache_last_updated);
169 mark_object (window->redisplay_end_trigger);
170 mark_object (window->subwindow_instance_cache);
172 mark_face_cachels (window->face_cachels);
173 mark_glyph_cachels (window->glyph_cachels);
175 #define WINDOW_SLOT(slot, compare) mark_object (window->slot)
176 #include "winslots.h"
182 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
187 error ("printing unreadable object #<window 0x%x>",
188 XWINDOW (obj)->header.uid);
190 write_c_string ("#<window", printcharfun);
191 if (!NILP (XWINDOW (obj)->buffer))
193 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
194 write_c_string (" on ", printcharfun);
195 print_internal (name, printcharfun, 1);
197 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
198 write_c_string (buf, printcharfun);
202 finalize_window (void *header, int for_disksave)
204 struct window *w = (struct window *) header;
206 if (w->line_start_cache)
208 Dynarr_free (w->line_start_cache);
209 w->line_start_cache = 0;
216 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
218 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
219 if (cachel->merged_faces)
221 Dynarr_free (cachel->merged_faces);
222 cachel->merged_faces = 0;
225 Dynarr_free (w->face_cachels);
229 if (w->glyph_cachels)
231 Dynarr_free (w->glyph_cachels);
232 w->glyph_cachels = 0;
236 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
237 mark_window, print_window, finalize_window,
238 0, 0, 0, struct window);
241 #define INIT_DISP_VARIABLE(field, initialization) \
242 p->field[CURRENT_DISP] = initialization; \
243 p->field[DESIRED_DISP] = initialization; \
244 p->field[CMOTION_DISP] = initialization;
246 /* We have an implicit assertion that the first two elements (default
247 and modeline faces) are always present in the face_element_cache.
248 Normally redisplay ensures this. However, it is possible for a
249 window to get created and functions which reference these values
250 called before redisplay works with the window for the first time.
251 All callers of allocate_window should therefore call
252 reset_face_cachels on the created window. We can't do it
253 here because the window must have its frame pointer set or
254 reset_face_cachels will fail. */
256 allocate_window (void)
259 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
273 INIT_DISP_VARIABLE (start, Fmake_marker ());
274 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
275 p->sb_point = Fmake_marker ();
277 INIT_DISP_VARIABLE (last_modified, Qzero);
278 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
279 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
280 INIT_DISP_VARIABLE (last_facechange, Qzero);
281 p->face_cachels = Dynarr_new (face_cachel);
282 p->glyph_cachels = Dynarr_new (glyph_cachel);
283 p->line_start_cache = Dynarr_new (line_start_cache);
284 p->subwindow_instance_cache = make_lisp_hash_table (30,
287 p->line_cache_last_updated = Qzero;
288 INIT_DISP_VARIABLE (last_point_x, 0);
289 INIT_DISP_VARIABLE (last_point_y, 0);
290 INIT_DISP_VARIABLE (window_end_pos, 0);
291 p->redisplay_end_trigger = Qnil;
293 p->gutter_extent_modiff[0] = 0;
294 p->gutter_extent_modiff[1] = 0;
295 p->gutter_extent_modiff[2] = 0;
296 p->gutter_extent_modiff[3] = 0;
298 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
299 #include "winslots.h"
301 p->windows_changed = 1;
302 p->shadow_thickness_changed = 1;
306 #undef INIT_DISP_VARIABLE
309 * The redisplay structures used to be stored with each window. While
310 * they are logically something associated with frames they can't be
311 * stored there with a redisplay which handles variable height lines.
312 * Lines in horizontally split windows might not line up. So they get
313 * stored with the windows.
315 * The problem with this is window configurations. When restoring a
316 * window configuration it now becomes problematic to do an
317 * incremental redisplay. The solution is to store the redisplay
318 * structures with the frame as they should be but laid out in the
319 * same manner as the window structure. Thus is born the window
322 * It also becomes a convenient place to stick scrollbar instances
323 * since they extrapolate out to having the same problem described for
324 * the display structures.
327 /* Create a new window mirror structure and associated redisplay
329 static struct window_mirror *
330 new_window_mirror (struct frame *f)
332 struct window_mirror *t = xnew_and_zero (struct window_mirror);
336 t->current_display_lines = Dynarr_new (display_line);
337 t->desired_display_lines = Dynarr_new (display_line);
340 #ifdef HAVE_SCROLLBARS
341 t->scrollbar_vertical_instance = NULL;
342 t->scrollbar_horizontal_instance = NULL;
348 /* Synchronize the mirror structure with a given window structure.
349 This is normally called from update_frame_window_mirror with a
350 starting window of f->root_window. */
351 static struct window_mirror *
352 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
358 free_window_mirror (mir);
365 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
367 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
368 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
369 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
372 * If the redisplay structs are not empty and the mirror has
373 * children, then this mirror structure was formerly being used for
374 * display but is no longer. Reset its current display structs so
375 * that redisplay doesn't accidentally think they are accurate if it
376 * is later used for display purposes once again. Also, mark the
377 * scrollbar instance as not active.
379 if (mir->vchild || mir->hchild)
381 /* The redisplay structures are big. Leaving them around in
382 non-leaf windows can add up to a lot of wasted space. So
384 free_display_structs (mir);
385 mir->current_display_lines = Dynarr_new (display_line);
386 mir->desired_display_lines = Dynarr_new (display_line);
388 #ifdef HAVE_SCROLLBARS
389 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
397 /* Given a window mirror, determine which real window it contains the
398 redisplay structures for. */
400 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
401 struct window_mirror *mir)
403 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
407 if (!NILP (XWINDOW (win)->vchild))
410 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
414 if (!NILP (XWINDOW (win)->hchild))
417 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
426 /* Given a real window, find the mirror structure which contains its
427 redisplay structures. */
428 static struct window_mirror *
429 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
432 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
434 if (w == XWINDOW (win))
437 if (!NILP (XWINDOW (win)->vchild))
439 struct window_mirror *retval =
440 find_window_mirror_internal (XWINDOW (win)->vchild,
442 if (retval) return retval;
445 if (!NILP (XWINDOW (win)->hchild))
447 struct window_mirror *retval =
448 find_window_mirror_internal (XWINDOW (win)->hchild,
450 if (retval) return retval;
457 /* Update the mirror structure for the given frame. */
459 update_frame_window_mirror (struct frame *f)
461 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
465 /* Free a given mirror structure along with all of its children as
466 well as their associated display structures. */
468 free_window_mirror (struct window_mirror *mir)
472 struct window_mirror *prev = mir;
473 if (mir->hchild) free_window_mirror (mir->hchild);
474 if (mir->vchild) free_window_mirror (mir->vchild);
475 #ifdef HAVE_SCROLLBARS
476 release_window_mirror_scrollbars (mir);
478 free_display_structs (mir);
484 /* Given a mirror structure, return the window it mirrors. Calls
485 real_window_internal to do most of the work. */
487 real_window (struct window_mirror *mir, int no_abort)
489 Lisp_Object retval = real_window_internal (mir->frame->root_window,
490 mir->frame->root_mirror, mir);
491 if (NILP (retval) && !no_abort)
497 /* Given a real window, return its mirror structure. Calls
498 find_window_mirror_internal to do all of the work. */
499 struct window_mirror *
500 find_window_mirror (struct window *w)
502 struct frame *f = XFRAME (w->frame);
504 update_frame_window_mirror (f);
505 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
508 /*****************************************************************************
509 find_window_by_pixel_pos
511 Given a pixel position relative to a frame, find the window at that
513 ****************************************************************************/
515 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
520 for (; !NILP (win); win = XWINDOW (win)->next)
524 if (!NILP (XWINDOW (win)->vchild))
526 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
529 if (!NILP (XWINDOW (win)->hchild))
531 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
535 if (pix_x >= WINDOW_LEFT (w)
536 && pix_x <= WINDOW_RIGHT (w)
537 && pix_y >= WINDOW_TOP (w)
538 && pix_y <= WINDOW_BOTTOM (w))
544 /* Return a pointer to the display structures for the given window. */
545 display_line_dynarr *
546 window_display_lines (struct window *w, int which)
548 struct window_mirror *t;
550 if (XFRAME (w->frame)->mirror_dirty)
551 update_frame_window_mirror (XFRAME (w->frame));
552 t = find_window_mirror (w);
556 if (which == CURRENT_DISP)
557 return t->current_display_lines;
558 else if (which == DESIRED_DISP)
559 return t->desired_display_lines;
560 else if (which == CMOTION_DISP)
561 /* The CMOTION_DISP display lines are global. */
562 return cmotion_display_lines;
566 return 0; /* shut up compiler */
570 window_display_buffer (struct window *w)
572 struct window_mirror *t;
574 if (XFRAME (w->frame)->mirror_dirty)
575 update_frame_window_mirror (XFRAME (w->frame));
576 t = find_window_mirror (w);
584 set_window_display_buffer (struct window *w, struct buffer *b)
586 struct window_mirror *t;
588 if (XFRAME (w->frame)->mirror_dirty)
589 update_frame_window_mirror (XFRAME (w->frame));
590 t = find_window_mirror (w);
598 /* Determining a window's position based solely on its pixel
599 positioning doesn't work. Instead, we do it the intelligent way,
600 by checking its positioning in the window hierarchy. */
602 window_is_leftmost (struct window *w)
604 Lisp_Object parent, current_ancestor, window;
606 XSETWINDOW (window, w);
608 parent = XWINDOW (window)->parent;
609 current_ancestor = window;
611 while (!NILP (parent))
613 if (!NILP (XWINDOW (parent)->hchild) &&
614 !EQ (XWINDOW (parent)->hchild, current_ancestor))
617 current_ancestor = parent;
618 parent = XWINDOW (parent)->parent;
625 window_is_rightmost (struct window *w)
627 Lisp_Object parent, current_ancestor, window;
629 XSETWINDOW (window, w);
631 parent = XWINDOW (window)->parent;
632 current_ancestor = window;
634 while (!NILP (parent))
636 if (!NILP (XWINDOW (parent)->hchild)
637 && !NILP (XWINDOW (current_ancestor)->next))
640 current_ancestor = parent;
641 parent = XWINDOW (parent)->parent;
648 window_full_width_p (struct window *w)
650 return window_is_leftmost (w) && window_is_rightmost (w);
654 window_is_highest (struct window *w)
656 Lisp_Object parent, current_ancestor, window;
658 XSETWINDOW (window, w);
660 parent = XWINDOW (window)->parent;
661 current_ancestor = window;
663 while (!NILP (parent))
665 if (!NILP (XWINDOW (parent)->vchild) &&
666 !EQ (XWINDOW (parent)->vchild, current_ancestor))
669 current_ancestor = parent;
670 parent = XWINDOW (parent)->parent;
673 /* This is really to catch the minibuffer but we make it generic in
674 case we ever change things around to let the minibuffer be on top. */
675 if (NILP (XWINDOW (current_ancestor)->prev))
682 window_is_lowest (struct window *w)
684 Lisp_Object parent, current_ancestor, window;
686 XSETWINDOW (window, w);
688 parent = XWINDOW (window)->parent;
689 current_ancestor = window;
691 while (!NILP (parent))
693 if (!NILP (XWINDOW (parent)->vchild)
694 && !NILP (XWINDOW (current_ancestor)->next))
697 current_ancestor = parent;
698 parent = XWINDOW (parent)->parent;
704 #if 0 /* not currently used */
707 window_full_height_p (struct window *w)
709 return window_is_highest (w) && window_is_lowest (w);
715 window_truncation_on (struct window *w)
717 /* Minibuffer windows are never truncated.
718 #### is this the right way ? */
719 if (MINI_WINDOW_P (w))
722 /* Horizontally scrolled windows are truncated. */
726 /* If truncate_partial_width_windows is true and the window is not
727 the full width of the frame it is truncated. */
728 if (truncate_partial_width_windows
729 && !(window_is_leftmost (w) && window_is_rightmost (w)))
732 /* If the window's buffer's value of truncate_lines is non-nil, then
733 the window is truncated. */
734 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
740 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
741 Returns non-nil if text in the window is truncated.
745 struct window *w = decode_window (window);
747 return window_truncation_on (w) ? Qt : Qnil;
752 have_undivided_common_edge (struct window *w_right, void *closure)
754 struct window *w_left = (struct window *) closure;
755 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
756 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
757 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
758 #ifdef HAVE_SCROLLBARS
759 && (NILP (w_right->scrollbar_on_left_p)
760 || NILP (w_right->vertical_scrollbar_visible_p)
761 || ZEROP (w_right->scrollbar_width))
767 window_needs_vertical_divider_1 (struct window *w)
769 /* Never if we're on the right */
770 if (window_is_rightmost (w))
773 /* Always if draggable */
774 if (!NILP (w->vertical_divider_always_visible_p))
777 #ifdef HAVE_SCROLLBARS
778 /* Our right scrollbar is enough to separate us at the right */
779 if (NILP (w->scrollbar_on_left_p)
780 && !NILP (w->vertical_scrollbar_visible_p)
781 && !ZEROP (w->scrollbar_width))
785 /* Ok. to determine whether we need a divider on the left, we must
786 check that our right neighbor windows have scrollbars on their
787 left sides. We must check all such windows which have common
788 left edge with our window's right edge. */
789 return map_windows (XFRAME (WINDOW_FRAME (w)),
790 have_undivided_common_edge, (void*)w);
794 window_needs_vertical_divider (struct window *w)
796 if (!w->need_vertical_divider_valid_p)
798 w->need_vertical_divider_p =
799 window_needs_vertical_divider_1 (w);
800 w->need_vertical_divider_valid_p = 1;
802 return w->need_vertical_divider_p;
805 /* Called from invalidate_vertical_divider_cache_in_frame */
807 invalidate_vertical_divider_cache_in_window (struct window *w,
810 w->need_vertical_divider_valid_p = 0;
814 /* Calculate width of vertical divider, including its shadows
815 and spacing. The returned value is effectively the distance
816 between adjacent window edges. This function does not check
817 whether a window needs a vertical divider, so the returned
818 value is a "theoretical" one */
820 window_divider_width (struct window *w)
822 /* the shadow thickness can be negative. This means that the divider
823 will have a depressed look */
825 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
827 XINT (w->vertical_divider_line_width)
828 + 2 * XINT (w->vertical_divider_spacing)
829 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
831 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
835 window_scrollbar_width (struct window *w)
837 #ifdef HAVE_SCROLLBARS
838 if (!WINDOW_WIN_P (w)
841 || NILP (w->vertical_scrollbar_visible_p))
842 /* #### when does NILP (w->buffer) happen? */
845 return XINT (w->scrollbar_width);
848 #endif /* HAVE_SCROLLBARS */
851 /* Horizontal scrollbars are only active on windows with truncation
854 window_scrollbar_height (struct window *w)
856 #ifdef HAVE_SCROLLBARS
857 if (!WINDOW_WIN_P (w)
860 || NILP (w->horizontal_scrollbar_visible_p)
861 || !window_truncation_on (w))
864 return XINT (w->scrollbar_height);
867 #endif /* HAVE_SCROLLBARS */
871 window_modeline_height (struct window *w)
873 struct frame *f = XFRAME (w->frame);
876 if (MINI_WINDOW_P (w) || NILP (w->buffer))
880 else if (!WINDOW_HAS_MODELINE_P (w))
882 if (window_scrollbar_height (w))
886 modeline_height = FRAMEMETH (f, divider_height, ());
888 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
889 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
898 display_line_dynarr *dla;
900 /* We don't force a regeneration of the modeline here.
901 Instead it is now a precondition that any function calling
902 this should make sure that one of these structures is
903 up-to-date. In practice this only affects two internal
904 redisplay functions, regenerate_window and
905 regenerate_window_point_center. */
906 /* We check DESIRED_DISP because if it is valid it is more
907 up-to-date than CURRENT_DISP. For calls to this outside
908 of redisplay it doesn't matter which structure we check
909 since there is a redisplay condition that these
910 structures be identical outside of redisplay. */
911 dla = window_display_lines (w, DESIRED_DISP);
912 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
913 modeline_height = (Dynarr_atp (dla, 0)->ascent +
914 Dynarr_atp (dla, 0)->descent);
917 dla = window_display_lines (w, CURRENT_DISP);
918 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
919 modeline_height = (Dynarr_atp (dla, 0)->ascent +
920 Dynarr_atp (dla, 0)->descent);
922 /* This should be an abort except I'm not yet 100%
923 confident that it won't ever get hit (though I
924 haven't been able to trigger it). It is extremely
925 unlikely to cause any noticeable problem and even if
926 it does it will be a minor display glitch. */
927 /* #### Bullshit alert. It does get hit and it causes
928 noticeable glitches. real_current_modeline_height
929 is a kludge to fix this for 19.14. */
930 modeline_height = real_current_modeline_height (w);
933 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
934 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
938 return modeline_height;
941 /*****************************************************************************
942 margin_width_internal
944 For a given window, return the width in pixels of the specified margin.
945 ****************************************************************************/
947 margin_width_internal (struct window *w, int left_margin)
950 int window_cwidth = window_char_width (w, 1);
955 /* We might be getting called on a non-leaf. */
956 if (NILP (w->buffer))
959 /* The minibuffer never has margins. */
960 if (MINI_WINDOW_P (w))
963 XSETWINDOW (window, w);
964 b = XBUFFER (w->buffer);
965 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
966 XINT (w->right_margin_width));
968 default_face_height_and_width (window, 0, &font_width);
970 /* The left margin takes precedence over the right margin so we
971 subtract its width from the space available for the right
974 window_cwidth -= XINT (w->left_margin_width);
976 /* The margin cannot be wider than the window is. We allow the
977 value to be bigger since it is possible for the user to enlarge
978 the window such that the left margin value would no longer be too
979 big, but we won't return a value that is larger. */
980 if (margin_cwidth > window_cwidth)
981 margin_cwidth = window_cwidth;
983 /* At the user level the margin is always specified in characters.
984 Internally however it is manipulated in terms of pixels. */
985 return margin_cwidth * font_width;
989 window_left_margin_width (struct window *w)
991 return margin_width_internal (w, 1);
995 window_right_margin_width (struct window *w)
997 return margin_width_internal (w, 0);
1000 /*****************************************************************************
1003 The gutters of a window are those areas in the boundary defined by
1004 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1005 do not contain text. Items which may be in the gutters include
1006 scrollbars, toolbars and modelines. The margin areas are not
1007 included. This is an exception made because redisplay special cases
1008 the handling of those areas in many places in such a way that
1009 including them in the gutter area would make life difficult.
1011 The size functions refer to height for the bottom and top gutters and
1012 width for the left and right gutters. The starting position
1013 functions refer to the Y coord for bottom and top gutters and the X
1014 coord for left and right gutters. All starting positions are
1015 relative to the frame, not the window.
1016 ****************************************************************************/
1019 window_top_window_gutter_height (struct window *w)
1021 if (!NILP (w->hchild) || !NILP (w->vchild))
1024 #ifdef HAVE_SCROLLBARS
1025 if (!NILP (w->scrollbar_on_top_p))
1026 return window_scrollbar_height (w);
1033 window_top_gutter_height (struct window *w)
1035 return window_top_window_gutter_height (w);
1039 window_bottom_window_gutter_height (struct window *w)
1043 if (!NILP (w->hchild) || !NILP (w->vchild))
1046 gutter = window_modeline_height (w);
1048 #ifdef HAVE_SCROLLBARS
1049 if (NILP (w->scrollbar_on_top_p))
1050 return window_scrollbar_height (w) + gutter;
1057 window_bottom_gutter_height (struct window *w)
1059 return window_bottom_window_gutter_height (w);
1063 window_left_window_gutter_width (struct window *w, int modeline)
1065 if (!NILP (w->hchild) || !NILP (w->vchild))
1068 #ifdef HAVE_SCROLLBARS
1069 if (!modeline && !NILP (w->scrollbar_on_left_p))
1070 return window_scrollbar_width (w);
1077 window_left_gutter_width (struct window *w, int modeline)
1079 return window_left_window_gutter_width (w, modeline);
1083 window_right_window_gutter_width (struct window *w, int modeline)
1087 if (!NILP (w->hchild) || !NILP (w->vchild))
1090 #ifdef HAVE_SCROLLBARS
1091 if (!modeline && NILP (w->scrollbar_on_left_p))
1092 gutter += window_scrollbar_width (w);
1095 if (window_needs_vertical_divider (w))
1096 gutter += window_divider_width (w);
1102 window_right_gutter_width (struct window *w, int modeline)
1104 return window_right_window_gutter_width (w, modeline);
1108 window_pixel_height (struct window* w)
1110 return WINDOW_HEIGHT (w);
1114 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1115 Return t if OBJ is a window.
1119 return WINDOWP (obj) ? Qt : Qnil;
1122 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1123 Return t if OBJ is a window which is currently visible.
1127 return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
1130 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1131 Return the window that the cursor now appears in and commands apply to.
1132 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1133 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1134 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1135 is a console, the selected frame on that console's selected device will
1136 be used. Otherwise, the selected frame is used.
1140 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1141 return Qnil; /* happens at startup */
1144 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1145 return FRAME_SELECTED_WINDOW (f);
1149 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1150 Return the last selected window that is not a minibuffer window.
1151 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1152 return the last non-minibuffer window used by that frame. If
1153 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1154 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1155 that console's selected device will be used. Otherwise, the selected
1160 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1161 return Qnil; /* happens at startup */
1164 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1165 return FRAME_LAST_NONMINIBUF_WINDOW (f);
1169 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1170 Return the window used now for minibuffers.
1171 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1172 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1173 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1174 is a console, the selected frame on that console's selected device will
1175 be used. Otherwise, the selected frame is used.
1179 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1182 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1183 Return non-nil if WINDOW is a minibuffer window.
1187 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1190 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1191 Return the first horizontal child of WINDOW, or nil.
1195 return decode_window (window)->hchild;
1198 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1199 Return the first vertical child of WINDOW, or nil.
1203 return decode_window (window)->vchild;
1206 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1207 Return the next window on the same level as WINDOW, or nil.
1211 return decode_window (window)->next;
1214 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1215 Return the previous window on the same level as WINDOW, or nil.
1219 return decode_window (window)->prev;
1222 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1223 Return the parent of WINDOW, or nil.
1227 return decode_window (window)->parent;
1230 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1231 Return non-nil if WINDOW is along the bottom of its frame.
1235 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1238 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1239 Return non-nil if WINDOW is along the top of its frame.
1243 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1246 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1247 Return non-nil if WINDOW is along the left edge of its frame.
1251 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1254 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1255 Return non-nil if WINDOW is along the right edge of its frame.
1259 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1262 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1263 Return t if position POS is currently on the frame in WINDOW.
1264 Returns nil if that position is scrolled vertically out of view.
1265 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1269 struct window *w = decode_window (window);
1270 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1272 struct buffer *buf = XBUFFER (w->buffer);
1275 posint = BUF_PT (buf);
1278 CHECK_INT_COERCE_MARKER (pos);
1279 posint = XINT (pos);
1282 if (posint < top || posint > BUF_ZV (buf))
1285 /* w->start can be out of range. If it is, do something reasonable. */
1286 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1289 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1294 decode_window (Lisp_Object window)
1297 return XWINDOW (Fselected_window (Qnil));
1299 CHECK_LIVE_WINDOW (window);
1300 return XWINDOW (window);
1303 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1304 Return the buffer that WINDOW is displaying.
1308 return decode_window (window)->buffer;
1311 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1312 Return the frame that window WINDOW is on.
1316 return decode_window (window)->frame;
1319 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1320 Return the number of default lines in WINDOW.
1321 This actually works by dividing the window's pixel height (including
1322 the modeline and horizontal scrollbar, if any) by the height of the
1323 default font; therefore, the number of displayed lines will probably
1325 Use `window-height' to get consistent results in geometry calculations.
1326 Use `window-displayed-height' to get the actual number of lines
1327 currently displayed in a window.
1329 The names are somewhat confusing; here's a table to help out:
1332 -------------------------------------------------------------------------
1334 (rows/columns) window-width window-text-area-height
1335 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1338 (rows/columns) window-full-width window-height
1339 (pixels) window-pixel-width window-pixel-height
1342 (rows/columns) ---- window-displayed-height
1343 (pixels) ---- window-displayed-text-pixel-height
1347 return make_int (window_char_height (decode_window (window), 1));
1350 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1351 Return the number of lines currently displayed in WINDOW.
1352 This counts the actual number of lines displayed in WINDOW
1353 \(as opposed to `window-height'). The modeline and horizontal
1354 scrollbar do not count as lines. If there is some blank space
1355 between the end of the buffer and the end of the window, this
1356 function pretends that there are lines of text in the default
1361 return make_int (window_displayed_height (decode_window (window)));
1364 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1365 Return the height of WINDOW in pixels. Defaults to current window.
1366 This includes the window's modeline and horizontal scrollbar (if any).
1370 return make_int (window_pixel_height (decode_window (window)));
1373 DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1374 Return the number of default lines in the text area of WINDOW.
1375 This actually works by dividing the window's text area pixel height (i.e.
1376 excluding the modeline and horizontal scrollbar, if any) by the height of the
1377 default font; therefore, the number of displayed lines will probably
1379 See also `window-height' and `window-displayed-height'.
1383 return make_int (window_char_height (decode_window (window), 0));
1386 DEFUN ("window-text-area-pixel-height",
1387 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1388 Return the height in pixels of the text-displaying portion of WINDOW.
1389 Unlike `window-pixel-height', the space occupied by the modeline and
1390 horizontal scrollbar, if any, is not counted.
1394 struct window *w = decode_window (window);
1396 return make_int (WINDOW_TEXT_HEIGHT (w));
1399 DEFUN ("window-displayed-text-pixel-height",
1400 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1401 Return the height in pixels of the text displayed in WINDOW.
1402 Unlike `window-text-area-pixel-height', any blank space below the
1403 end of the buffer is not included. If optional argument NOCLIPPED
1404 is non-nil, do not include space occupied by clipped lines.
1406 (window, noclipped))
1409 Bufpos start, eobuf;
1411 int hlimit, height, prev_height = -1;
1415 line_start_cache_dynarr *cache;
1418 window = Fselected_window (Qnil);
1420 CHECK_LIVE_WINDOW (window);
1421 w = XWINDOW (window);
1423 start = marker_position (w->start[CURRENT_DISP]);
1424 hlimit = WINDOW_TEXT_HEIGHT (w);
1425 eobuf = BUF_ZV (XBUFFER (w->buffer));
1427 default_face_height_and_width (window, &defheight, NULL);
1429 /* guess lines needed in line start cache + a few extra */
1430 needed = (hlimit + defheight-1) / defheight + 3;
1433 elt = point_in_line_start_cache (w, start, needed);
1434 assert (elt >= 0); /* in the cache */
1436 cache = w->line_start_cache;
1437 nelt = Dynarr_length (cache);
1440 for (i = elt; i < nelt; i++) {
1441 line = Dynarr_atp (cache, i)->height;
1443 if (height + line > hlimit)
1444 return make_int (!NILP (noclipped) ? height : hlimit);
1448 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1449 return make_int (height);
1452 /* get here => need more cache lines. try again. */
1453 assert(height > prev_height); /* progress? */
1454 prev_height = height;
1456 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1459 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1462 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1463 Return the number of display columns in WINDOW.
1464 This is the width that is usable columns available for text in WINDOW,
1465 and does not include vertical scrollbars, dividers, or the like. See also
1466 `window-full-width' and `window-height'.
1470 return make_int (window_char_width (decode_window (window), 0));
1473 DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1474 Return the total number of columns in WINDOW.
1475 This is like `window-width' but includes vertical scrollbars, dividers,
1480 return make_int (window_char_width (decode_window (window), 1));
1483 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1484 Return the width of WINDOW in pixels. Defaults to current window.
1488 return make_int (decode_window (window)->pixel_width);
1491 DEFUN ("window-text-area-pixel-width",
1492 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1493 Return the width in pixels of the text-displaying portion of WINDOW.
1494 Unlike `window-pixel-width', the space occupied by the vertical
1495 scrollbar or divider, if any, is not counted.
1499 struct window *w = decode_window (window);
1501 return make_int (WINDOW_TEXT_WIDTH (w));
1504 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1505 Return the number of columns by which WINDOW is scrolled from left margin.
1509 return make_int (decode_window (window)->hscroll);
1512 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1513 Return the horizontal scrolling ammount of WINDOW's modeline.
1514 If the window has no modeline, return nil.
1518 struct window *w = decode_window (window);
1520 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
1524 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1525 Set the horizontal scrolling ammount of WINDOW's modeline to NCOL.
1526 If NCOL is negative, it will silently be forced to 0.
1527 If the window has no modeline, return nil. Otherwise, return the actual
1532 struct window *w = decode_window (window);
1534 if (WINDOW_HAS_MODELINE_P (w))
1539 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
1540 if (ncols != w->modeline_hscroll)
1542 MARK_MODELINE_CHANGED;
1543 w->modeline_hscroll = ncols;
1545 return make_int ((int) ncols);
1551 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1552 Set number of columns WINDOW is scrolled from left margin to NCOL.
1553 NCOL should be zero or positive.
1561 ncols = XINT (ncol);
1562 if (ncols < 0) ncols = 0;
1563 w = decode_window (window);
1564 if (w->hscroll != ncols)
1565 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1570 #if 0 /* bogus FSF crock */
1572 xxDEFUN ("window-redisplay-end-trigger",
1573 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1574 Return WINDOW's redisplay end trigger value.
1575 See `set-window-redisplay-end-trigger' for more information.
1579 return decode_window (window)->redisplay_end_trigger;
1582 xxDEFUN ("set-window-redisplay-end-trigger",
1583 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1584 Set WINDOW's redisplay end trigger value to VALUE.
1585 VALUE should be a buffer position (typically a marker) or nil.
1586 If it is a buffer position, then if redisplay in WINDOW reaches a position
1587 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1588 with two arguments: WINDOW, and the end trigger value.
1589 Afterwards the end-trigger value is reset to nil.
1593 return (decode_window (window)->redisplay_end_trigger = value);
1598 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1599 Return a list of the pixel edge coordinates of WINDOW.
1600 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1601 The frame toolbars, menubars and gutters are considered to be outside of this area.
1605 struct window *w = decode_window (window);
1607 int left = w->pixel_left;
1608 int top = w->pixel_top;
1610 return list4 (make_int (left),
1612 make_int (left + w->pixel_width),
1613 make_int (top + w->pixel_height));
1616 DEFUN ("window-text-area-pixel-edges",
1617 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1618 Return a list of the pixel edge coordinates of the text area of WINDOW.
1619 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1620 top left corner of the window.
1624 struct window *w = decode_window (window);
1626 int left = window_left_gutter_width (w, /* modeline = */ 0);
1627 int top = window_top_gutter_height (w);
1628 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1629 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1631 return list4 (make_int (left),
1637 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1638 Return current value of point in WINDOW.
1639 For a nonselected window, this is the value point would have
1640 if that window were selected.
1642 Note that, when WINDOW is the selected window and its buffer
1643 is also currently selected, the value returned is the same as (point).
1644 It would be more strictly correct to return the `top-level' value
1645 of point, outside of any save-excursion forms.
1646 But that is hard to define.
1650 struct window *w = decode_window (window);
1652 /* The special check for current buffer is necessary for this
1653 function to work as defined when called within an excursion. */
1654 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1655 && current_buffer == XBUFFER (w->buffer))
1656 return Fpoint (Qnil);
1657 return Fmarker_position (w->pointm[CURRENT_DISP]);
1660 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1661 Return position at which display currently starts in WINDOW.
1662 This is updated by redisplay or by calling `set-window-start'.
1666 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1669 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1670 Return position at which display currently ends in WINDOW.
1671 This is updated by redisplay, when it runs to completion.
1672 Simply changing the buffer text or setting `window-start'
1673 does not update this value.
1674 If GUARANTEE is non-nil, then the return value is guaranteed to be
1675 the value of window-end at the end of the next full redisplay assuming
1676 nothing else changes in the meantime. This function is potentially much
1677 slower with this flag set.
1679 (window, guarantee))
1681 struct window *w = decode_window (window);
1683 if (NILP (guarantee))
1688 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1692 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1693 return make_int (end_of_last_line (w, startp));
1697 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1698 Return pixel height of visible part of last window line if it is clipped.
1699 If the last line is not clipped, return nil.
1703 struct window *w = decode_window (window);
1704 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1705 int num_lines = Dynarr_length (dla);
1706 struct display_line *dl;
1708 /* No lines - no clipped lines */
1709 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
1712 dl = Dynarr_atp (dla, num_lines - 1);
1716 return make_int (dl->ascent + dl->descent - dl->clip);
1719 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1720 Make point value in WINDOW be at position POS in WINDOW's buffer.
1724 struct window *w = decode_window (window);
1726 CHECK_INT_COERCE_MARKER (pos);
1727 if (w == XWINDOW (Fselected_window (Qnil)))
1728 Fgoto_char (pos, Qnil);
1730 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1736 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1737 Make display in WINDOW start at position POS in WINDOW's buffer.
1738 Optional third arg NOFORCE non-nil inhibits next redisplay
1739 from overriding motion of point in order to display at this exact start.
1741 (window, pos, noforce))
1743 struct window *w = decode_window (window);
1745 CHECK_INT_COERCE_MARKER (pos);
1746 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1747 /* this is not right, but much easier than doing what is right. */
1748 /* w->start_at_line_beg = 0; */
1749 /* WTF is the above supposed to mean? GE */
1750 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1751 marker_position (w->start[CURRENT_DISP]));
1754 w->redo_modeline = 1;
1755 SET_LAST_MODIFIED (w, 0);
1756 SET_LAST_FACECHANGE (w);
1758 MARK_WINDOWS_CHANGED (w);
1763 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1764 Return WINDOW's dedicated object, usually t or nil.
1765 See also `set-window-dedicated-p'.
1769 return decode_window (window)->dedicated;
1772 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1773 Control whether WINDOW is dedicated to the buffer it displays.
1774 If it is dedicated, Emacs will not automatically change
1775 which buffer appears in it.
1776 The second argument is the new value for the dedication flag;
1781 struct window *w = decode_window (window);
1783 w->dedicated = NILP (arg) ? Qnil : Qt;
1785 return w->dedicated;
1788 /* FSFmacs has window-display-table here. We have display table as a
1792 /* Record info on buffer window w is displaying
1793 when it is about to cease to display that buffer. */
1795 unshow_buffer (struct window *w)
1797 Lisp_Object buf = w->buffer;
1799 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1802 /* FSF disables this check, so I'll do it too. I hope it won't
1803 break things. --ben */
1805 if (w == XWINDOW (Fselected_window (Qnil))
1806 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1807 /* Do this except when the selected window's buffer
1808 is being removed from some other window. */
1810 /* last_window_start records the start position that this buffer
1811 had in the last window to be disconnected from it.
1812 Now that this statement is unconditional,
1813 it is possible for the buffer to be displayed in the
1814 selected window, while last_window_start reflects another
1815 window which was recently showing the same buffer.
1816 Some people might say that might be a good thing. Let's see. */
1817 XBUFFER (buf)->last_window_start =
1818 marker_position (w->start[CURRENT_DISP]);
1820 /* Point in the selected window's buffer
1821 is actually stored in that buffer, and the window's pointm isn't used.
1822 So don't clobber point in that buffer. */
1823 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1825 struct buffer *b= XBUFFER (buf);
1826 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1827 marker_position (w->pointm[CURRENT_DISP]),
1832 /* Put REPLACEMENT into the window structure in place of OLD. */
1834 replace_window (Lisp_Object old, Lisp_Object replacement)
1837 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1839 /* If OLD is its frame's root_window, then replacement is the new
1840 root_window for that frame. */
1842 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1843 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1845 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1846 WINDOW_TOP (p) = WINDOW_TOP (o);
1847 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1848 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1850 p->next = tem = o->next;
1852 XWINDOW (tem)->prev = replacement;
1854 p->prev = tem = o->prev;
1856 XWINDOW (tem)->next = replacement;
1858 p->parent = tem = o->parent;
1861 if (EQ (XWINDOW (tem)->vchild, old))
1862 XWINDOW (tem)->vchild = replacement;
1863 if (EQ (XWINDOW (tem)->hchild, old))
1864 XWINDOW (tem)->hchild = replacement;
1867 /* #### Here, if replacement is a vertical combination
1868 and so is its new parent, we should make replacement's
1869 children be children of that parent instead. */
1871 ERROR_CHECK_SUBWINDOW_CACHE (p);
1875 window_unmap_subwindows_cache_mapper (Lisp_Object key, Lisp_Object value,
1878 /* value can be nil; we cache failures as well as successes */
1881 struct frame* f = XFRAME (XIMAGE_INSTANCE_FRAME (value));
1882 unmap_subwindow (value);
1883 /* In case GC doesn't catch up fast enough, remove from the frame
1884 cache also. Otherwise code that checks the sanity of the instance
1886 XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
1887 = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
1893 window_unmap_subwindows (struct window* w)
1895 assert (!NILP (w->subwindow_instance_cache));
1896 elisp_maphash (window_unmap_subwindows_cache_mapper,
1897 w->subwindow_instance_cache, 0);
1900 /* we're deleting W; set the structure of W to indicate this. */
1903 mark_window_as_deleted (struct window *w)
1905 /* The window instance cache is going away now, so need to get the
1906 cachels reset by redisplay. */
1907 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
1909 /* The cache is going away. If we leave unmapping to
1910 reset_subwindow_cachels then we get in a situation where the
1911 domain (the window) has been deleted but we still need access to
1912 its attributes in order to unmap windows properly. Since the
1913 subwindows are going to get GC'd anyway as a result of the domain
1914 going away, it is safer to just unmap them all while we know the
1915 domain is still valid. */
1916 ERROR_CHECK_SUBWINDOW_CACHE (w);
1917 window_unmap_subwindows (w);
1920 (while t (split-window) (delete-window))
1921 we end up with a tree of deleted windows which are all connected
1922 through the `next' slot. This might not seem so bad, as they're
1923 deleted, and will presumably be GCed - but if even *one* of those
1924 windows is still being pointed to, by the user, or by a window
1925 configuration, then *all* of those windows stick around.
1927 Since the window-configuration code doesn't need any of the
1928 pointers to other windows (they are all recreated from the
1929 window-config data), we set them all to nil so that we
1930 are able to collect more actual garbage. */
1936 w->subwindow_instance_cache = Qnil;
1940 /* Free the extra data structures attached to windows immediately so
1941 they don't sit around consuming excess space. They will be
1942 reinitialized by the window-configuration code as necessary. */
1943 finalize_window ((void *) w, 0);
1946 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1947 Remove WINDOW from the display. Default is selected window.
1948 If window is the only one on the frame, the frame is destroyed.
1949 Normally, you cannot delete the last non-minibuffer-only frame (you must
1950 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1951 second argument FORCE is non-nil, you can delete the last frame. (This
1952 will automatically call `save-buffers-kill-emacs'.)
1956 /* This function can GC if this is the only window in the frame */
1964 /* Note: this function is called by other C code on non-leaf
1967 /* Do the equivalent of decode_window() but don't error out on
1968 deleted window; it's OK to delete an already-deleted window. */
1970 window = Fselected_window (Qnil);
1972 CHECK_WINDOW (window);
1974 w = XWINDOW (window);
1976 /* It's okay to delete an already-deleted window. */
1977 if (! WINDOW_LIVE_P (w))
1980 frame = WINDOW_FRAME (w);
1982 d = XDEVICE (FRAME_DEVICE (f));
1984 if (TOP_LEVEL_WINDOW_P (w))
1986 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1987 /* this frame isn't fully initialized yet; don't blow up. */
1990 if (MINI_WINDOW_P (XWINDOW (window)))
1991 error ("Attempt to delete the minibuffer window");
1993 /* It has been suggested that it's a good thing for C-x 0 to have this
1994 behavior, but not such a good idea for #'delete-window to have it.
1995 Maybe C-x 0 should be bound to something else, or maybe frame
1996 deletion should only happen when this is called interactively.
1998 delete_frame_internal (f, !NILP (force), 0, 0);
2002 /* At this point, we know the window has a parent. */
2004 par = XWINDOW (parent);
2006 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
2007 /* It's quite likely that deleting a window will result in
2008 subwindows needing to be deleted also (since they are cached
2009 per-window). So we mark them as changed, so that the cachels will
2010 get reset by redisplay and thus deleted subwindows can get
2012 MARK_FRAME_SUBWINDOWS_CHANGED (f);
2014 /* Are we trying to delete any frame's selected window?
2015 Note that we could be dealing with a non-leaf window
2016 where the selected window is one of our children.
2017 So, we check by scanning all the ancestors of the
2018 frame's selected window and comparing each one with
2021 Lisp_Object pwindow;
2023 pwindow = FRAME_SELECTED_WINDOW (f);
2025 while (!NILP (pwindow))
2027 if (EQ (window, pwindow))
2029 pwindow = XWINDOW (pwindow)->parent;
2032 if (EQ (window, pwindow))
2034 /* OK, we found it. */
2035 Lisp_Object alternative;
2036 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
2038 /* If we're about to delete the selected window on the
2039 selected frame, then we should use Fselect_window to select
2040 the new window. On the other hand, if we're about to
2041 delete the selected window on any other frame, we shouldn't do
2042 anything but set the frame's selected_window slot. */
2043 if (EQ (frame, Fselected_frame (Qnil)))
2044 Fselect_window (alternative, Qnil);
2046 set_frame_selected_window (f, alternative);
2050 /* w->buffer is nil in a non-leaf window; in this case,
2051 get rid of the markers we maintain that point into that buffer. */
2052 if (!NILP (w->buffer))
2055 unchain_marker (w->pointm[CURRENT_DISP]);
2056 unchain_marker (w->pointm[DESIRED_DISP]);
2057 unchain_marker (w->pointm[CMOTION_DISP]);
2058 unchain_marker (w->start[CURRENT_DISP]);
2059 unchain_marker (w->start[DESIRED_DISP]);
2060 unchain_marker (w->start[CMOTION_DISP]);
2061 unchain_marker (w->sb_point);
2062 /* This breaks set-window-configuration if windows in the saved
2063 configuration get deleted and multiple frames are in use. */
2064 /* w->buffer = Qnil; */
2067 /* close up the hole in the sibling list */
2068 if (!NILP (w->next))
2069 XWINDOW (w->next)->prev = w->prev;
2070 if (!NILP (w->prev))
2071 XWINDOW (w->prev)->next = w->next;
2072 if (EQ (window, par->hchild))
2073 par->hchild = w->next;
2074 if (EQ (window, par->vchild))
2075 par->vchild = w->next;
2077 /* Find one of our siblings to give our space to. */
2079 Lisp_Object sib = w->prev;
2082 /* If w gives its space to its next sibling, that sibling needs
2083 to have its top/left side pulled back to where w's is.
2084 set_window_{height,width} will re-position the sibling's
2087 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
2088 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
2091 /* Stretch that sibling. */
2092 if (!NILP (par->vchild))
2093 set_window_pixheight
2094 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
2095 if (!NILP (par->hchild))
2097 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
2100 /* If parent now has only one child,
2101 put the child into the parent's place. */
2103 Lisp_Object parchild = par->hchild;
2104 if (NILP (parchild))
2105 parchild = par->vchild;
2106 if (NILP (XWINDOW (parchild)->next))
2108 replace_window (parent, parchild);
2109 mark_window_as_deleted (XWINDOW (parent));
2113 /* Since we may be deleting combination windows, we must make sure that
2114 not only W but all its children have been marked as deleted. */
2115 if (!NILP (w->hchild))
2116 delete_all_subwindows (XWINDOW (w->hchild));
2117 else if (!NILP (w->vchild))
2118 delete_all_subwindows (XWINDOW (w->vchild));
2120 mark_window_as_deleted (w);
2122 f->mirror_dirty = 1;
2127 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2128 Return next window after WINDOW in canonical ordering of windows.
2129 If omitted, WINDOW defaults to the selected window.
2131 Optional second arg MINIBUF t means count the minibuffer window even
2132 if not active. MINIBUF nil or omitted means count the minibuffer iff
2133 it is active. MINIBUF neither t nor nil means not to count the
2134 minibuffer even if it is active.
2136 Several frames may share a single minibuffer; if the minibuffer
2137 counts, all windows on all frames that share that minibuffer count
2138 too. Therefore, `next-window' can be used to iterate through the
2139 set of windows even when the minibuffer is on another frame. If the
2140 minibuffer does not count, only windows from WINDOW's frame count.
2142 Optional third arg ALL-FRAMES t means include windows on all frames.
2143 ALL-FRAMES nil or omitted means cycle within the frames as specified
2144 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2145 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2146 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2147 Anything else means restrict to WINDOW's frame.
2149 Optional fourth argument CONSOLE controls which consoles or devices the
2150 returned window may be on. If CONSOLE is a console, return windows only
2151 on that console. If CONSOLE is a device, return windows only on that
2152 device. If CONSOLE is a console type, return windows only on consoles
2153 of that type. If CONSOLE is 'window-system, return any windows on any
2154 window-system consoles. If CONSOLE is nil or omitted, return windows only
2155 on WINDOW's console. Otherwise, all windows are considered.
2157 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2158 can use `next-window' to iterate through the entire cycle of acceptable
2159 windows, eventually ending up back at the window you started with.
2160 `previous-window' traverses the same cycle, in the reverse order.
2162 (window, minibuf, all_frames, console))
2165 Lisp_Object start_window;
2168 window = Fselected_window (Qnil);
2170 CHECK_LIVE_WINDOW (window);
2172 start_window = window;
2174 /* minibuf == nil may or may not include minibuffers.
2175 Decide if it does. */
2177 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2178 else if (! EQ (minibuf, Qt))
2180 /* Now minibuf can be t => count all minibuffer windows,
2181 lambda => count none of them,
2182 or a specific minibuffer window (the active one) to count. */
2184 /* all_frames == nil doesn't specify which frames to include. */
2185 if (NILP (all_frames))
2186 all_frames = (! EQ (minibuf, Qlambda)
2187 ? (FRAME_MINIBUF_WINDOW
2190 (XWINDOW (window)))))
2192 else if (EQ (all_frames, Qvisible))
2194 else if (ZEROP (all_frames))
2196 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2197 /* If all_frames is a frame and window arg isn't on that frame, just
2198 return the first window on the frame. */
2199 return frame_first_window (XFRAME (all_frames));
2200 else if (! EQ (all_frames, Qt))
2202 /* Now all_frames is t meaning search all frames,
2203 nil meaning search just current frame,
2204 visible meaning search just visible frames,
2205 0 meaning search visible and iconified frames,
2206 or a window, meaning search the frame that window belongs to. */
2208 /* Do this loop at least once, to get the next window, and perhaps
2209 again, if we hit the minibuffer and that is not acceptable. */
2212 /* Find a window that actually has a next one. This loop
2213 climbs up the tree. */
2214 while (tem = XWINDOW (window)->next, NILP (tem))
2215 if (tem = XWINDOW (window)->parent, !NILP (tem))
2217 else /* window must be minibuffer window now */
2219 /* We've reached the end of this frame.
2220 Which other frames are acceptable? */
2221 tem = WINDOW_FRAME (XWINDOW (window));
2223 if (! NILP (all_frames))
2228 tem = next_frame (tem, all_frames, console);
2229 /* In the case where the minibuffer is active,
2230 and we include its frame as well as the selected one,
2231 next_frame may get stuck in that frame.
2232 If that happens, go back to the selected frame
2233 so we can complete the cycle. */
2235 XSETFRAME (tem, selected_frame ());
2238 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2244 /* If we're in a combination window, find its first child and
2245 recurse on that. Otherwise, we've found the window we want. */
2248 if (!NILP (XWINDOW (window)->hchild))
2249 window = XWINDOW (window)->hchild;
2250 else if (!NILP (XWINDOW (window)->vchild))
2251 window = XWINDOW (window)->vchild;
2255 /* "acceptable" is the correct spelling. */
2256 /* Which windows are acceptable?
2257 Exit the loop and accept this window if
2258 this isn't a minibuffer window,
2259 or we're accepting all minibuffer windows,
2260 or this is the active minibuffer and we are accepting that one, or
2261 we've come all the way around and we're back at the original window. */
2262 while (MINI_WINDOW_P (XWINDOW (window))
2263 && ! EQ (minibuf, Qt)
2264 && ! EQ (minibuf, window)
2265 && ! EQ (window, start_window));
2270 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2271 Return the window preceding WINDOW in canonical ordering of windows.
2272 If omitted, WINDOW defaults to the selected window.
2274 Optional second arg MINIBUF t means count the minibuffer window even
2275 if not active. MINIBUF nil or omitted means count the minibuffer iff
2276 it is active. MINIBUF neither t nor nil means not to count the
2277 minibuffer even if it is active.
2279 Several frames may share a single minibuffer; if the minibuffer
2280 counts, all windows on all frames that share that minibuffer count
2281 too. Therefore, `previous-window' can be used to iterate through
2282 the set of windows even when the minibuffer is on another frame. If
2283 the minibuffer does not count, only windows from WINDOW's frame count
2285 If optional third arg ALL-FRAMES t means include windows on all frames.
2286 ALL-FRAMES nil or omitted means cycle within the frames as specified
2287 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2288 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2289 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2290 Anything else means restrict to WINDOW's frame.
2292 Optional fourth argument CONSOLE controls which consoles or devices the
2293 returned window may be on. If CONSOLE is a console, return windows only
2294 on that console. If CONSOLE is a device, return windows only on that
2295 device. If CONSOLE is a console type, return windows only on consoles
2296 of that type. If CONSOLE is 'window-system, return any windows on any
2297 window-system consoles. If CONSOLE is nil or omitted, return windows only
2298 on WINDOW's console. Otherwise, all windows are considered.
2300 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2301 can use `previous-window' to iterate through the entire cycle of acceptable
2302 windows, eventually ending up back at the window you started with.
2303 `next-window' traverses the same cycle, in the reverse order.
2305 (window, minibuf, all_frames, console))
2308 Lisp_Object start_window;
2311 window = Fselected_window (Qnil);
2313 CHECK_LIVE_WINDOW (window);
2315 start_window = window;
2317 /* minibuf == nil may or may not include minibuffers.
2318 Decide if it does. */
2320 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2321 else if (! EQ (minibuf, Qt))
2323 /* Now minibuf can be t => count all minibuffer windows,
2324 lambda => count none of them,
2325 or a specific minibuffer window (the active one) to count. */
2327 /* all_frames == nil doesn't specify which frames to include.
2328 Decide which frames it includes. */
2329 if (NILP (all_frames))
2330 all_frames = (! EQ (minibuf, Qlambda)
2331 ? (FRAME_MINIBUF_WINDOW
2334 (XWINDOW (window)))))
2336 else if (EQ (all_frames, Qvisible))
2338 else if (ZEROP (all_frames))
2340 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2341 /* If all_frames is a frame and window arg isn't on that frame, just
2342 return the first window on the frame. */
2343 return frame_first_window (XFRAME (all_frames));
2344 else if (! EQ (all_frames, Qt))
2346 /* Now all_frames is t meaning search all frames,
2347 nil meaning search just current frame,
2348 visible meaning search just visible frames,
2349 0 meaning search visible and iconified frames,
2350 or a window, meaning search the frame that window belongs to. */
2352 /* Do this loop at least once, to get the next window, and perhaps
2353 again, if we hit the minibuffer and that is not acceptable. */
2356 /* Find a window that actually has a next one. This loop
2357 climbs up the tree. */
2358 while (tem = XWINDOW (window)->prev, NILP (tem))
2359 if (tem = XWINDOW (window)->parent, !NILP (tem))
2361 else /* window must be minibuffer window now */
2363 /* We have found the top window on the frame.
2364 Which frames are acceptable? */
2365 tem = WINDOW_FRAME (XWINDOW (window));
2367 if (! NILP (all_frames))
2368 /* It's actually important that we use prev_frame here,
2369 rather than next_frame. All the windows acceptable
2370 according to the given parameters should form a ring;
2371 Fnext_window and Fprevious_window should go back and
2372 forth around the ring. If we use next_frame here,
2373 then Fnext_window and Fprevious_window take different
2374 paths through the set of acceptable windows.
2375 window_loop assumes that these `ring' requirement are
2381 tem = prev_frame (tem, all_frames, console);
2382 /* In the case where the minibuffer is active,
2383 and we include its frame as well as the selected one,
2384 next_frame may get stuck in that frame.
2385 If that happens, go back to the selected frame
2386 so we can complete the cycle. */
2388 XSETFRAME (tem, selected_frame ());
2391 /* If this frame has a minibuffer, find that window first,
2392 because it is conceptually the last window in that frame. */
2393 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2394 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2396 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2403 /* If we're in a combination window, find its first child and
2404 recurse on that. Otherwise, we've found the window we want. */
2407 if (!NILP (XWINDOW (window)->hchild))
2408 window = XWINDOW (window)->hchild;
2409 else if (!NILP (XWINDOW (window)->vchild))
2410 window = XWINDOW (window)->vchild;
2412 while (tem = XWINDOW (window)->next, !NILP (tem))
2416 /* Which windows are acceptable?
2417 Exit the loop and accept this window if
2418 this isn't a minibuffer window,
2419 or we're accepting all minibuffer windows,
2420 or this is the active minibuffer and we are accepting that one, or
2421 we've come all the way around and we're back at the original window. */
2422 while (MINI_WINDOW_P (XWINDOW (window))
2423 && ! EQ (minibuf, Qt)
2424 && ! EQ (minibuf, window)
2425 && ! EQ (window, start_window));
2430 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2431 Return the next window which is vertically after WINDOW.
2436 struct window *w = decode_window (window);
2437 XSETWINDOW (window, w);
2439 if (MINI_WINDOW_P (XWINDOW (window)))
2442 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2444 if (EQ (window, root))
2447 if (!NILP (XWINDOW (window)->hchild))
2448 window = XWINDOW (window)->hchild;
2449 else if (!NILP (XWINDOW (window)->vchild))
2450 window = XWINDOW (window)->vchild;
2457 if (!NILP (XWINDOW (window)->parent) &&
2458 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2460 if (!NILP (XWINDOW (window)->next))
2461 return XWINDOW (window)->next;
2463 window = XWINDOW (window)->parent;
2466 window = XWINDOW (window)->parent;
2468 while (!EQ (window, root));
2471 if (!NILP (XWINDOW (window)->hchild))
2472 window = XWINDOW (window)->hchild;
2473 else if (!NILP (XWINDOW (window)->vchild))
2474 window = XWINDOW (window)->vchild;
2479 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2480 Select the N'th different window on this frame.
2481 All windows on current frame are arranged in a cyclic order.
2482 This command selects the window N steps away in that order.
2483 A negative N moves in the opposite order.
2485 If optional argument FRAME is `visible', search all visible frames.
2486 If FRAME is 0, search all visible and iconified frames.
2487 If FRAME is t, search all frames.
2488 If FRAME is nil, search only the selected frame.
2489 If FRAME is a frame, search only that frame.
2491 Optional third argument CONSOLE controls which consoles or devices the
2492 returned window may be on. If CONSOLE is a console, return windows only
2493 on that console. If CONSOLE is a device, return windows only on that
2494 device. If CONSOLE is a console type, return windows only on consoles
2495 of that type. If CONSOLE is 'window-system, return any windows on any
2496 window-system consoles. If CONSOLE is nil or omitted, return windows only
2497 on FRAME'S console, or on the selected console if FRAME is not a frame.
2498 Otherwise, all windows are considered.
2500 (n, frame, console))
2506 w = Fselected_window (Qnil);
2511 w = Fnext_window (w, Qnil, frame, console);
2516 w = Fprevious_window (w, Qnil, frame, console);
2519 Fselect_window (w, Qnil);
2524 /* Look at all windows, performing an operation specified by TYPE
2527 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2528 frame. If FRAMES is a frame, just look at windows on that frame.
2529 If MINI is non-zero, perform the operation on minibuffer windows too.
2535 GET_BUFFER_WINDOW, /* Arg is buffer */
2536 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2537 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2538 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2540 UNSHOW_BUFFER, /* Arg is buffer */
2541 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2542 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2546 window_loop (enum window_loop type,
2551 Lisp_Object console)
2553 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2555 Lisp_Object best_window = Qnil;
2556 Lisp_Object next_window;
2557 Lisp_Object last_window;
2558 struct frame *frame;
2559 Lisp_Object frame_arg = Qt;
2560 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2561 /* #### I think the change of "precomputing" last_window and next_window
2562 * #### catch the lossage this is meant(?) to punt on...
2565 Lisp_Object devcons, concons;
2567 /* FRAME_ARG is Qlambda to stick to one frame,
2568 Qvisible to consider all visible frames,
2571 /* If we're only looping through windows on a particular frame,
2572 FRAME points to that frame. If we're looping through windows
2573 on all frames, FRAME is 0. */
2575 if (FRAMEP (frames))
2576 frame = XFRAME (frames);
2577 else if (NILP (frames))
2578 frame = selected_frame ();
2582 frame_arg = Qlambda;
2583 else if (ZEROP (frames))
2585 else if (EQ (frames, Qvisible))
2588 DEVICE_LOOP_NO_BREAK (devcons, concons)
2590 Lisp_Object device = XCAR (devcons);
2591 Lisp_Object the_frame;
2594 XSETFRAME (the_frame, frame);
2596 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2598 if (NILP (the_frame))
2601 if (!device_matches_console_spec (the_frame, device, console))
2604 /* Pick a window to start with. */
2608 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2610 /* Figure out the last window we're going to mess with. Since
2611 Fnext_window, given the same options, is guaranteed to go in a
2612 ring, we can just use Fprevious_window to find the last one.
2614 We can't just wait until we hit the first window again,
2615 because it might be deleted. */
2617 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2622 struct window *p = XWINDOW (w);
2623 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2625 /* Pick the next window now, since some operations will delete
2626 the current window. */
2627 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2629 /* #### Still needed ?? */
2630 /* Given the outstanding quality of the rest of this code,
2631 I feel no shame about putting this piece of shit in. */
2632 if (++lose_lose >= 500)
2635 /* Note that we do not pay attention here to whether
2636 the frame is visible, since Fnext_window skips non-visible frames
2637 if that is desired, under the control of frame_arg. */
2638 if (! MINI_WINDOW_P (p)
2639 || (mini && minibuf_level > 0))
2642 case GET_BUFFER_WINDOW:
2644 if (XBUFFER (p->buffer) == XBUFFER (obj))
2649 case GET_BUFFER_WINDOW_COUNT:
2651 if (XBUFFER (p->buffer) == XBUFFER (obj))
2656 case GET_LRU_WINDOW:
2658 /* t as arg means consider only full-width windows */
2660 && !window_full_width_p (p))
2662 /* Ignore dedicated windows and minibuffers. */
2663 if (MINI_WINDOW_P (p)
2664 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2666 if (NILP (best_window)
2667 || (XINT (XWINDOW (best_window)->use_time)
2668 > XINT (p->use_time)))
2673 case GET_BUFFER_MRU_WINDOW:
2675 /* #### what about the first check in GET_LRU_WINDOW? */
2676 /* Ignore dedicated windows and minibuffers. */
2677 if (MINI_WINDOW_P (p)
2678 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2681 if (XBUFFER (p->buffer) == XBUFFER (obj))
2683 if (NILP (best_window)
2684 || (XINT (XWINDOW (best_window)->use_time)
2685 < XINT (p->use_time)))
2691 case DELETE_OTHER_WINDOWS:
2693 /* Don't delete the last window on a frame; this can
2694 happen when the minibuffer is selected, and would
2695 cause the frame to be deleted. */
2696 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2697 Fdelete_window (w, Qnil);
2701 case DELETE_BUFFER_WINDOWS:
2703 if (EQ (p->buffer, obj))
2705 struct frame *f = XFRAME (WINDOW_FRAME (p));
2707 /* If this window is dedicated, and in a frame
2708 of its own, kill the frame. */
2709 if (EQ (w, FRAME_ROOT_WINDOW (f))
2710 && !NILP (p->dedicated)
2711 && other_visible_frames (f))
2713 /* Skip the other windows on this frame.
2714 There might be one, the minibuffer! */
2715 if (! EQ (w, last_window))
2716 while (f == XFRAME (WINDOW_FRAME
2717 (XWINDOW (next_window))))
2719 /* As we go, check for the end of the
2720 loop. We mustn't start going
2721 around a second time. */
2722 if (EQ (next_window, last_window))
2727 next_window = Fnext_window (next_window,
2731 /* Now we can safely delete the frame. */
2732 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2735 /* If we're deleting the buffer displayed in
2736 the only window on the frame, find a new
2737 buffer to display there. */
2738 if (NILP (p->parent))
2740 Lisp_Object new_buffer;
2741 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2742 if (NILP (new_buffer))
2743 new_buffer = Fget_buffer_create (QSscratch);
2744 Fset_window_buffer (w, new_buffer, Qnil);
2745 if (EQ (w, Fselected_window (Qnil)))
2746 Fset_buffer (p->buffer);
2749 Fdelete_window (w, Qnil);
2754 case GET_LARGEST_WINDOW:
2756 /* Ignore dedicated windows and minibuffers. */
2757 if (MINI_WINDOW_P (p)
2758 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2761 /* write the check as follows to avoid tripping
2762 error_check_window() --ben */
2763 struct window *b = NILP (best_window) ? 0 :
2764 XWINDOW (best_window);
2765 if (NILP (best_window)
2766 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2767 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2775 if (EQ (p->buffer, obj))
2777 /* Find another buffer to show in this window. */
2778 Lisp_Object another_buffer =
2779 Fother_buffer (obj, Qnil, Qnil);
2780 if (NILP (another_buffer))
2782 = Fget_buffer_create (QSscratch);
2783 /* If this window is dedicated, and in a frame
2784 of its own, kill the frame. */
2785 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2786 && !NILP (p->dedicated)
2787 && other_visible_frames (w_frame))
2789 /* Skip the other windows on this frame.
2790 There might be one, the minibuffer! */
2791 if (! EQ (w, last_window))
2792 while (w_frame == XFRAME (WINDOW_FRAME
2793 (XWINDOW (next_window))))
2795 /* As we go, check for the end of the
2796 loop. We mustn't start going
2797 around a second time. */
2798 if (EQ (next_window, last_window))
2803 next_window = Fnext_window (next_window,
2807 /* Now we can safely delete the frame. */
2808 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2813 /* Otherwise show a different buffer in the
2815 p->dedicated = Qnil;
2816 Fset_window_buffer (w, another_buffer, Qnil);
2817 if (EQ (w, Fselected_window (Qnil)))
2818 Fset_buffer (p->buffer);
2828 if (EQ (w, last_window))
2835 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2838 #if 0 /* not currently used */
2841 buffer_window_count (struct buffer *b, struct frame *f)
2843 Lisp_Object buffer, frame;
2845 XSETFRAME (frame, f);
2846 XSETBUFFER (buffer, b);
2848 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2853 buffer_window_mru (struct window *w)
2855 Lisp_Object window =
2856 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2860 else if (XWINDOW (window) == w)
2869 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2870 Return the window least recently selected or used for display.
2871 If optional argument FRAME is `visible', search all visible frames.
2872 If FRAME is 0, search all visible and iconified frames.
2873 If FRAME is t, search all frames.
2874 If FRAME is nil, search only the selected frame.
2875 If FRAME is a frame, search only that frame.
2877 Optional second argument CONSOLE controls which consoles or devices the
2878 returned window may be on. If CONSOLE is a console, return windows only
2879 on that console. If CONSOLE is a device, return windows only on that
2880 device. If CONSOLE is a console type, return windows only on consoles
2881 of that type. If CONSOLE is 'window-system, return any windows on any
2882 window-system consoles. If CONSOLE is nil or omitted, return windows only
2883 on FRAME'S console, or on the selected console if FRAME is not a frame.
2884 Otherwise, all windows are considered.
2889 /* First try for a non-dedicated window that is full-width */
2890 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2891 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2894 /* Then try for any non-dedicated window */
2895 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2896 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2900 /* FSFmacs never returns a dedicated window here. If we do,
2901 it makes `display-buffer' not work right. #### All of this
2902 shit is so disgusting and awful that it needs to be rethought
2904 /* then try for a dedicated window that is full-width */
2905 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2906 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2909 /* If none of them, then all windows, dedicated or not. */
2910 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2912 /* At this point we damn well better have found something. */
2913 if (NILP (w)) abort ();
2919 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2920 Return the window largest in area.
2921 If optional argument FRAME is `visible', search all visible frames.
2922 If FRAME is 0, search all visible and iconified frames.
2923 If FRAME is t, search all frames.
2924 If FRAME is nil, search only the selected frame.
2925 If FRAME is a frame, search only that frame.
2927 Optional second argument CONSOLE controls which consoles or devices the
2928 returned window may be on. If CONSOLE is a console, return windows only
2929 on that console. If CONSOLE is a device, return windows only on that
2930 device. If CONSOLE is a console type, return windows only on consoles
2931 of that type. If CONSOLE is 'window-system, return any windows on any
2932 window-system consoles. If CONSOLE is nil or omitted, return windows only
2933 on FRAME'S console, or on the selected console if FRAME is not a frame.
2934 Otherwise, all windows are considered.
2938 /* Don't search dedicated windows because FSFmacs doesn't.
2939 This stuff is all black magic so don't try to apply common
2941 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2944 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2945 Return a window currently displaying BUFFER, or nil if none.
2946 If optional argument FRAME is `visible', search all visible frames.
2947 If optional argument FRAME is 0, search all visible and iconified frames.
2948 If FRAME is t, search all frames.
2949 If FRAME is nil, search only the selected frame.
2950 If FRAME is a frame, search only that frame.
2952 Optional third argument CONSOLE controls which consoles or devices the
2953 returned window may be on. If CONSOLE is a console, return windows only
2954 on that console. If CONSOLE is a device, return windows only on that
2955 device. If CONSOLE is a console type, return windows only on consoles
2956 of that type. If CONSOLE is 'window-system, return any windows on any
2957 window-system consoles. If CONSOLE is nil or omitted, return windows only
2958 on FRAME'S console, or on the selected console if FRAME is not a frame.
2959 Otherwise, all windows are considered.
2961 (buffer, frame, console))
2963 buffer = Fget_buffer (buffer);
2964 if (BUFFERP (buffer))
2965 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2966 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2971 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2972 but there is no sensible way to implement those functions, since
2973 you can't in general derive a window from a buffer. */
2975 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2977 Return the width in pixels of the left outside margin of window WINDOW.
2978 If WINDOW is nil, the selected window is assumed.
2982 return make_int (window_left_margin_width (decode_window (window)));
2985 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2987 Return the width in pixels of the right outside margin of window WINDOW.
2988 If WINDOW is nil, the selected window is assumed.
2992 return make_int (window_right_margin_width (decode_window (window)));
2995 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2996 Make WINDOW (or the selected window) fill its frame.
2997 Only the frame WINDOW is on is affected.
2998 This function tries to reduce display jumps
2999 by keeping the text previously visible in WINDOW
3000 in the same place on the frame. Doing this depends on
3001 the value of (window-start WINDOW), so if calling this function
3002 in a program gives strange scrolling, make sure the window-start
3003 value is reasonable when this function is called.
3007 struct window *w = decode_window (window);
3008 struct buffer *b = XBUFFER (w->buffer);
3010 int old_top = WINDOW_TOP (w);
3012 XSETWINDOW (window, w);
3014 if (MINI_WINDOW_P (w) && old_top > 0)
3015 error ("Can't expand minibuffer to full frame");
3017 /* Ignore dedicated windows. */
3018 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3020 start_pos = marker_position (w->start[CURRENT_DISP]);
3022 /* Try to minimize scrolling, by setting the window start to the
3023 point which will cause the text at the old window start to be at
3024 the same place on the frame. But don't try to do this if the
3025 window start is outside the visible portion (as might happen when
3026 the display is not current, due to typeahead). */
3027 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
3028 && !MINI_WINDOW_P (w))
3030 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
3032 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
3034 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
3036 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3038 /* We need to do this, so that the window-scroll-functions
3046 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3047 "bDelete windows on (buffer): ", /*
3048 Delete all windows showing BUFFER.
3049 Optional second argument FRAME controls which frames are affected.
3050 If nil or omitted, delete all windows showing BUFFER in any frame.
3051 If t, delete only windows showing BUFFER in the selected frame.
3052 If `visible', delete all windows showing BUFFER in any visible frame.
3053 If a frame, delete only windows showing BUFFER in that frame.
3055 Optional third argument CONSOLE controls which consoles or devices the
3056 returned window may be on. If CONSOLE is a console, return windows only
3057 on that console. If CONSOLE is a device, return windows only on that
3058 device. If CONSOLE is a console type, return windows only on consoles
3059 of that type. If CONSOLE is 'window-system, return any windows on any
3060 window-system consoles. If CONSOLE is nil or omitted, return windows only
3061 on FRAME'S console, or on the selected console if FRAME is not a frame.
3062 Otherwise, all windows are considered.
3064 (buffer, frame, console))
3066 /* This function can GC */
3067 /* FRAME uses t and nil to mean the opposite of what window_loop
3069 if (!FRAMEP (frame))
3070 frame = NILP (frame) ? Qt : Qnil;
3074 buffer = Fget_buffer (buffer);
3075 CHECK_BUFFER (buffer);
3076 /* Ignore dedicated windows. */
3077 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
3082 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
3083 "bReplace buffer in windows: ", /*
3084 Replace BUFFER with some other buffer in all windows showing it.
3088 /* This function can GC */
3091 buffer = Fget_buffer (buffer);
3092 CHECK_BUFFER (buffer);
3093 /* Ignore dedicated windows. */
3094 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
3099 /* The smallest acceptable dimensions for a window. Anything smaller
3100 might crash Emacs. */
3101 #define MIN_SAFE_WINDOW_WIDTH (2)
3102 #define MIN_SAFE_WINDOW_HEIGHT (2)
3104 /* Make sure that window_min_height and window_min_width are
3105 not too small; if they are, set them to safe minima. */
3108 check_min_window_sizes (void)
3110 /* Smaller values might permit a crash. */
3111 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3112 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3113 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3114 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3118 frame_min_height (struct frame *frame)
3120 /* For height, we have to see whether the frame has a minibuffer, and
3121 whether it wants a modeline. */
3122 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3123 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3124 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3127 /* Return non-zero if both frame sizes are less than or equal to
3128 minimal allowed values. ROWS and COLS are in characters */
3130 frame_size_valid_p (struct frame *frame, int rows, int cols)
3132 return (rows >= frame_min_height (frame)
3133 && cols >= MIN_SAFE_WINDOW_WIDTH);
3136 /* Return non-zero if both frame sizes are less than or equal to
3137 minimal allowed values. WIDTH and HEIGHT are in pixels */
3139 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3142 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3143 return frame_size_valid_p (frame, rows, cols);
3146 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3147 minimum allowable size. */
3149 check_frame_size (struct frame *frame, int *rows, int *cols)
3151 int min_height = frame_min_height (frame);
3153 if (*rows < min_height)
3155 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3156 *cols = MIN_SAFE_WINDOW_WIDTH;
3159 /* Normally the window is deleted if it gets too small.
3160 nodelete nonzero means do not do this.
3161 (The caller should check later and do so if appropriate) */
3163 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3166 struct window *w = XWINDOW (window);
3167 struct frame *f = XFRAME (w->frame);
3169 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3170 Lisp_Object child, minor_kid, major_kid;
3173 int defheight, defwidth;
3175 /* #### This is very likely incorrect and instead the char_to_pixel_
3176 functions should be called. */
3177 default_face_height_and_width (window, &defheight, &defwidth);
3178 line_size = (set_height ? defheight : defwidth);
3180 check_min_window_sizes ();
3182 minsize = (set_height ? window_min_height : window_min_width);
3183 minsize *= line_size;
3186 && !TOP_LEVEL_WINDOW_P (w)
3187 && new_pixsize < minsize)
3189 Fdelete_window (window, Qnil);
3193 SET_LAST_MODIFIED (w, 0);
3194 SET_LAST_FACECHANGE (w);
3195 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3198 WINDOW_HEIGHT (w) = new_pixsize;
3199 major_kid = w->vchild;
3200 minor_kid = w->hchild;
3204 WINDOW_WIDTH (w) = new_pixsize;
3205 major_kid = w->hchild;
3206 minor_kid = w->vchild;
3209 if (!NILP (minor_kid))
3211 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3214 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3216 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3218 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3221 else if (!NILP (major_kid))
3223 int last_pos, last_old_pos, pos, old_pos, first;
3224 int pixel_adj_left = new_pixsize - old_pixsize;
3225 int div_val = old_pixsize << 1;
3228 * Previously we bailed out here if there was no size change.
3229 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3230 * toolbar appears or disappears, windows may not change size,
3231 * but their top and left coordinates need to be updated.
3233 * So we don't bail until after the loop below.
3236 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3239 for (child = major_kid; !NILP (child); child = c->next)
3241 c = XWINDOW (child);
3245 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3246 WINDOW_TOP (c) = last_pos;
3250 old_pos = last_old_pos + WINDOW_WIDTH (c);
3251 WINDOW_LEFT (c) = last_pos;
3254 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3255 /* All but the last window should have a height which is
3256 a multiple of the default line height. */
3257 if (!NILP (c->next))
3258 pos = (pos / line_size) * line_size;
3260 /* Avoid confusion: don't delete child if it becomes too small */
3261 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3263 last_pos = pos + first;
3264 last_old_pos = old_pos;
3267 /* Sometimes we may get called with our old size. In that case
3268 we don't need to do anything else. */
3269 if (!pixel_adj_left)
3272 /* Now delete any children that became too small. */
3274 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3277 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3279 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3284 /* Set the height of WINDOW and all its inferiors. */
3286 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3288 set_window_pixsize (window, new_pixheight, nodelete, 1);
3291 /* Recursively set width of WINDOW and its inferiors. */
3293 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3295 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3299 static int window_select_count;
3301 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3302 Make WINDOW display BUFFER as its contents.
3303 BUFFER can be a buffer or buffer name.
3305 With non-nil optional argument `norecord', do not modify the
3306 global or per-frame buffer ordering.
3308 (window, buffer, norecord))
3311 struct window *w = decode_window (window);
3313 buffer = Fget_buffer (buffer);
3314 CHECK_BUFFER (buffer);
3316 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3317 error ("Attempt to display deleted buffer");
3321 error ("Window is deleted");
3323 /* While this seems like a logical thing to do, it causes problems
3324 because of saved window configurations. It is possible for a
3325 buffer to get restored into a window in which it is already being
3326 displayed, but start and point are actually at completely
3327 different locations. So we let this function complete fully and
3328 it will then make sure redisplay correctly updates things.
3330 #### This is a kludge. The correct approach is not to do this
3331 but to fix set-window-configuration. */
3333 else if (EQ (tem, buffer))
3336 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3337 is first being set up. */
3339 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3340 error ("Window is dedicated to buffer %s",
3341 XSTRING_DATA (XBUFFER (tem)->name));
3347 w->window_end_pos[CURRENT_DISP] = 0;
3349 w->modeline_hscroll = 0;
3350 Fset_marker (w->pointm[CURRENT_DISP],
3351 make_int (BUF_PT (XBUFFER (buffer))),
3353 set_marker_restricted (w->start[CURRENT_DISP],
3354 make_int (XBUFFER (buffer)->last_window_start),
3356 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3357 /* set start_at_line_beg correctly. GE */
3358 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3359 marker_position (w->start[CURRENT_DISP]));
3360 w->force_start = 0; /* Lucid fix */
3361 SET_LAST_MODIFIED (w, 1);
3362 SET_LAST_FACECHANGE (w);
3363 MARK_WINDOWS_CHANGED (w);
3364 recompute_all_cached_specifiers_in_window (w);
3365 if (EQ (window, Fselected_window (Qnil)))
3367 if (NILP (norecord))
3368 Frecord_buffer (buffer);
3370 Fset_buffer (buffer);
3375 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3376 Select WINDOW. Most editing will apply to WINDOW's buffer.
3377 The main editor command loop selects the buffer of the selected window
3378 before each command.
3380 With non-nil optional argument `norecord', do not modify the
3381 global or per-frame buffer ordering.
3386 Lisp_Object old_selected_window = Fselected_window (Qnil);
3388 CHECK_LIVE_WINDOW (window);
3389 w = XWINDOW (window);
3391 /* we have already caught dead-window errors */
3392 if (!NILP (w->hchild) || !NILP (w->vchild))
3393 error ("Trying to select non-leaf window");
3395 w->use_time = make_int (++window_select_count);
3397 if (EQ (window, old_selected_window))
3400 /* deselect the old window, if it exists (it might not exist if
3401 the selected device has no frames, which occurs at startup) */
3402 if (!NILP (old_selected_window))
3404 struct window *ow = XWINDOW (old_selected_window);
3406 Fset_marker (ow->pointm[CURRENT_DISP],
3407 make_int (BUF_PT (XBUFFER (ow->buffer))),
3410 MARK_WINDOWS_CHANGED (ow);
3413 /* now select the window's frame */
3414 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3416 select_frame_1 (WINDOW_FRAME (w));
3418 /* also select the window's buffer */
3419 if (NILP (norecord))
3420 Frecord_buffer (w->buffer);
3421 Fset_buffer (w->buffer);
3423 /* Go to the point recorded in the window.
3424 This is important when the buffer is in more
3425 than one window. It also matters when
3426 redisplay_window has altered point after scrolling,
3427 because it makes the change only in the window. */
3429 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3430 if (new_point < BUF_BEGV (current_buffer))
3431 new_point = BUF_BEGV (current_buffer);
3432 else if (new_point > BUF_ZV (current_buffer))
3433 new_point = BUF_ZV (current_buffer);
3435 BUF_SET_PT (current_buffer, new_point);
3438 MARK_WINDOWS_CHANGED (w);
3444 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3445 Lisp_Object override_frame)
3447 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3451 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3453 /* This function can GC */
3456 struct buffer *b = XBUFFER (buf);
3458 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3459 widen_buffer (b, 0);
3460 BUF_SET_PT (b, BUF_BEG (b));
3462 if (!NILP (Vtemp_buffer_show_function))
3463 call1 (Vtemp_buffer_show_function, buf);
3466 window = display_buffer (buf, Qnil, same_frame);
3468 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3469 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3471 Vminibuffer_scroll_window = window;
3472 w = XWINDOW (window);
3474 w->modeline_hscroll = 0;
3475 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3476 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3477 set_marker_restricted (w->sb_point, make_int (1), buf);
3479 /* Run temp-buffer-show-hook, with the chosen window selected. */
3480 if (!preparing_for_armageddon)
3483 tem = Fboundp (Qtemp_buffer_show_hook);
3486 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3489 int count = specpdl_depth ();
3491 /* Select the window that was chosen, for running
3493 record_unwind_protect (save_window_excursion_unwind,
3494 Fcurrent_window_configuration (Qnil));
3496 Fselect_window (window, Qnil);
3497 run_hook (Qtemp_buffer_show_hook);
3498 unbind_to (count, Qnil);
3506 make_dummy_parent (Lisp_Object window)
3509 struct window *o = XWINDOW (window);
3510 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3512 XSETWINDOW (new, p);
3513 copy_lcrecord (p, o);
3515 /* Don't copy the pointers to the line start cache or the face
3517 p->line_start_cache = Dynarr_new (line_start_cache);
3518 p->face_cachels = Dynarr_new (face_cachel);
3519 p->glyph_cachels = Dynarr_new (glyph_cachel);
3520 p->subwindow_instance_cache =
3521 make_lisp_hash_table (30,
3522 HASH_TABLE_KEY_WEAK,
3525 /* Put new into window structure in place of window */
3526 replace_window (window, new);
3534 p->start[CURRENT_DISP] = Qnil;
3535 p->start[DESIRED_DISP] = Qnil;
3536 p->start[CMOTION_DISP] = Qnil;
3537 p->pointm[CURRENT_DISP] = Qnil;
3538 p->pointm[DESIRED_DISP] = Qnil;
3539 p->pointm[CMOTION_DISP] = Qnil;
3544 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3545 Split WINDOW, putting SIZE lines in the first of the pair.
3546 WINDOW defaults to selected one and SIZE to half its size.
3547 If optional third arg HOR-FLAG is non-nil, split side by side
3548 and put SIZE columns in the first of the pair.
3550 (window, chsize, horflag))
3553 struct window *o, *p;
3559 window = Fselected_window (Qnil);
3561 CHECK_LIVE_WINDOW (window);
3563 o = XWINDOW (window);
3564 f = XFRAME (WINDOW_FRAME (o));
3568 if (!NILP (horflag))
3569 /* In the new scheme, we are symmetric with respect to separators
3570 so there is no need to do weird things here. */
3572 psize = WINDOW_WIDTH (o) >> 1;
3573 size = window_pixel_width_to_char_width (o, psize, 0);
3577 psize = WINDOW_HEIGHT (o) >> 1;
3578 size = window_pixel_height_to_char_height (o, psize, 1);
3584 size = XINT (chsize);
3585 if (!NILP (horflag))
3586 psize = window_char_width_to_pixel_width (o, size, 0);
3588 psize = window_char_height_to_pixel_height (o, size, 1);
3591 if (MINI_WINDOW_P (o))
3592 error ("Attempt to split minibuffer window");
3593 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3594 error ("Attempt to split unsplittable frame");
3596 check_min_window_sizes ();
3600 if (size < window_min_height)
3601 error ("Window height %d too small (after splitting)", size);
3602 if (size + window_min_height > window_char_height (o, 1))
3603 error ("Window height %d too small (after splitting)",
3604 window_char_height (o, 1) - size);
3605 if (NILP (o->parent)
3606 || NILP (XWINDOW (o->parent)->vchild))
3608 make_dummy_parent (window);
3609 reset_face_cachels (XWINDOW (window));
3611 XWINDOW (new)->vchild = window;
3612 XFRAME (o->frame)->mirror_dirty = 1;
3617 if (size < window_min_width)
3618 error ("Window width %d too small (after splitting)", size);
3619 if (size + window_min_width > window_char_width (o, 0))
3620 error ("Window width %d too small (after splitting)",
3621 window_char_width (o, 0) - size);
3622 if (NILP (o->parent)
3623 || NILP (XWINDOW (o->parent)->hchild))
3625 make_dummy_parent (window);
3626 reset_face_cachels (XWINDOW (window));
3628 XWINDOW (new)->hchild = window;
3629 XFRAME (o->frame)->mirror_dirty = 1;
3633 /* Now we know that window's parent is a vertical combination
3634 if we are dividing vertically, or a horizontal combination
3635 if we are making side-by-side windows */
3637 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3638 new = allocate_window ();
3641 p->frame = o->frame;
3643 if (!NILP (p->next))
3644 XWINDOW (p->next)->prev = new;
3647 p->parent = o->parent;
3650 reset_face_cachels (p);
3651 reset_glyph_cachels (p);
3654 /* Apportion the available frame space among the two new windows */
3656 if (!NILP (horflag))
3658 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3659 WINDOW_TOP (p) = WINDOW_TOP (o);
3660 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3661 WINDOW_WIDTH (o) = psize;
3662 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3666 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3667 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3668 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3669 WINDOW_HEIGHT (o) = psize;
3670 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3673 XFRAME (p->frame)->mirror_dirty = 1;
3674 /* do this last (after the window is completely initialized and
3675 the mirror-dirty flag is set) so that specifier recomputation
3676 caused as a result of this will work properly and not abort. */
3677 Fset_window_buffer (new, o->buffer, Qt);
3682 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3683 Make the selected window N lines bigger.
3684 From program, optional second arg SIDE non-nil means grow sideways N columns,
3685 and optional third arg WINDOW specifies the window to change instead of the
3690 struct window *w = decode_window (window);
3692 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3696 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3697 Make the selected window N pixels bigger.
3698 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3699 and optional third arg WINDOW specifies the window to change instead of the
3704 struct window *w = decode_window (window);
3706 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3710 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3711 Make the selected window N lines smaller.
3712 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3713 and optional third arg WINDOW specifies the window to change instead of the
3719 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3724 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3725 Make the selected window N pixels smaller.
3726 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3727 and optional third arg WINDOW specifies the window to change instead of the
3733 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3739 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3740 int include_gutters_p)
3743 int defheight, defwidth;
3747 XSETWINDOW (window, w);
3749 avail_height = (pixel_height -
3750 (include_gutters_p ? 0 :
3751 window_top_window_gutter_height (w) +
3752 window_bottom_window_gutter_height (w)));
3754 default_face_height_and_width (window, &defheight, &defwidth);
3756 char_height = avail_height / defheight;
3758 /* It's the calling function's responsibility to check these values
3759 and make sure they're not out of range.
3761 #### We need to go through the calling functions and actually
3763 return max (0, char_height);
3767 window_char_height_to_pixel_height (struct window *w, int char_height,
3768 int include_gutters_p)
3771 int defheight, defwidth;
3776 XSETWINDOW (window, w);
3778 default_face_height_and_width (window, &defheight, &defwidth);
3780 avail_height = char_height * defheight;
3781 pixel_height = (avail_height +
3782 (include_gutters_p ? 0 :
3783 window_top_window_gutter_height (w) +
3784 window_bottom_window_gutter_height (w)));
3786 /* It's the calling function's responsibility to check these values
3787 and make sure they're not out of range.
3789 #### We need to go through the calling functions and actually
3791 return max (0, pixel_height);
3794 /* Return number of default lines of text can fit in the window W.
3795 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3796 horizontal scrollbar) in the space that is used for the calculation.
3797 This doesn't include space used by the frame gutters.
3800 window_char_height (struct window *w, int include_gutters_p)
3802 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3807 * Return number of lines currently displayed in window w. If
3808 * end-of-buffer is displayed then the area below end-of-buffer is assume
3809 * to be blank lines of default height.
3810 * Does not include the modeline.
3813 window_displayed_height (struct window *w)
3815 struct buffer *b = XBUFFER (w->buffer);
3816 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3818 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3820 : w->window_end_pos[CURRENT_DISP]);
3822 if (!Dynarr_length (dla))
3823 return window_char_height (w, 0);
3825 num_lines = Dynarr_length (dla);
3827 /* #### Document and assert somewhere that w->window_end_pos == -1
3828 indicates that end-of-buffer is being displayed. */
3831 struct display_line *dl = Dynarr_atp (dla, 0);
3832 int ypos1 = dl->ypos + dl->descent;
3833 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3835 int defheight, defwidth;
3837 XSETWINDOW (window, w);
3843 if (Dynarr_length (dla) == 1)
3844 ypos1 = WINDOW_TEXT_TOP (w);
3847 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3848 /* If this line is clipped then we know that there is no
3849 blank room between eob and the modeline. If we are
3850 scrolling on clipped lines just know off the clipped
3852 if (scroll_on_clipped_lines && dl->clip)
3853 return num_lines - 1;
3854 ypos1 = dl->ypos + dl->descent - dl->clip;
3858 default_face_height_and_width (window, &defheight, &defwidth);
3859 /* #### This probably needs to know about the clipping area once a
3860 final definition is decided on. */
3861 num_lines += ((ypos2 - ypos1) / defheight);
3865 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3868 if (scroll_on_clipped_lines
3869 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3877 window_pixel_width (Lisp_Object window)
3879 return WINDOW_WIDTH (XWINDOW (window));
3882 /* Calculate the pixel of a window, optionally including margin space
3883 but no vertical gutters. */
3885 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3886 int include_margins_p)
3890 int defheight, defwidth;
3893 XSETWINDOW (window, w);
3895 avail_width = (pixel_width -
3896 window_left_gutter_width (w, 0) -
3897 window_right_gutter_width (w, 0) -
3898 (include_margins_p ? 0 : window_left_margin_width (w)) -
3899 (include_margins_p ? 0 : window_right_margin_width (w)));
3901 default_face_height_and_width (window, &defheight, &defwidth);
3903 char_width = (avail_width / defwidth);
3905 /* It's the calling function's responsibility to check these values
3906 and make sure they're not out of range.
3908 #### We need to go through the calling functions and actually
3910 return max (0, char_width);
3914 window_char_width_to_pixel_width (struct window *w, int char_width,
3915 int include_margins_p)
3919 int defheight, defwidth;
3922 XSETWINDOW (window, w);
3924 default_face_height_and_width (window, &defheight, &defwidth);
3926 avail_width = char_width * defwidth;
3927 pixel_width = (avail_width +
3928 window_left_window_gutter_width (w, 0) +
3929 window_right_window_gutter_width (w, 0) +
3930 (include_margins_p ? 0 : window_left_margin_width (w)) +
3931 (include_margins_p ? 0 : window_right_margin_width (w)));
3933 /* It's the calling function's responsibility to check these values
3934 and make sure they're not out of range.
3936 #### We need to go through the calling functions and actually
3938 return max (0, pixel_width);
3941 /* This returns the usable space which doesn't include space needed by
3942 scrollbars or divider lines. */
3944 window_char_width (struct window *w, int include_margins_p)
3946 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3950 #define MINSIZE(w) \
3952 ? window_min_width * defwidth \
3953 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3956 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3958 #define CURSIZE(w) \
3959 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3961 #define CURCHARSIZE(w) \
3962 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3964 #define MINCHARSIZE(window) \
3965 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3966 ? 1 : window_min_height)
3969 window_pixheight (Lisp_Object w)
3971 return window_pixel_height (XWINDOW (w));
3974 /* Unlike set_window_pixheight, this function
3975 also changes the heights of the siblings so as to
3976 keep everything consistent. */
3979 change_window_height (struct window *win, int delta, int widthflag,
3987 int (*sizefun) (Lisp_Object) = (widthflag
3988 ? window_pixel_width
3989 : window_pixheight);
3990 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3991 ? set_window_pixwidth
3992 : set_window_pixheight);
3994 int defheight, defwidth;
3999 check_min_window_sizes ();
4001 XSETWINDOW (window, win);
4002 f = XFRAME (win->frame);
4003 if (EQ (window, FRAME_ROOT_WINDOW (f)))
4004 error ("Won't change only window");
4006 /* #### This is very likely incorrect and instead the char_to_pixel_
4007 functions should be called. */
4008 default_face_height_and_width (window, &defheight, &defwidth);
4012 w = XWINDOW (window);
4017 error ("No other window to side of this one");
4021 ? !NILP (XWINDOW (parent)->hchild)
4022 : !NILP (XWINDOW (parent)->vchild))
4027 sizep = &CURSIZE (w);
4028 dim = CURCHARSIZE (w);
4030 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4031 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4033 if (MINI_WINDOW_P (XWINDOW (window)))
4035 else if (!NILP (parent))
4037 Fdelete_window (window, Qnil);
4043 delta *= (widthflag ? defwidth : defheight);
4048 maxdelta = ((!NILP (parent))
4049 ? (*sizefun) (parent) - *sizep
4050 : ((!NILP (w->next))
4051 ? (*sizefun) (w->next) - MINSIZE (w->next)
4052 : ((!NILP (w->prev))
4053 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4054 /* This is a frame with only one window,
4055 a minibuffer-only or a minibufferless frame. */
4058 if (delta > maxdelta)
4059 /* This case traps trying to make the minibuffer
4060 the full frame, or make the only window aside from the
4061 minibuffer the full frame. */
4068 /* #### Chuck: is this correct? */
4069 if (*sizep + delta < MINSIZE (window))
4071 Fdelete_window (window);
4077 if (!NILP (w->next) &&
4078 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4080 CURBEG (XWINDOW (w->next)) += delta;
4081 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4082 (*setsizefun) (window, *sizep + delta, 0);
4084 else if (!NILP (w->prev) &&
4085 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4087 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4088 CURBEG (w) -= delta;
4089 (*setsizefun) (window, *sizep + delta, 0);
4094 int opht = (*sizefun) (parent);
4096 /* If trying to grow this window to or beyond size of the parent,
4097 make delta1 so big that, on shrinking back down,
4098 all the siblings end up with less than one line and are deleted. */
4099 if (opht <= *sizep + delta)
4100 delta1 = opht * opht * 2;
4101 /* Otherwise, make delta1 just right so that if we add delta1
4102 lines to this window and to the parent, and then shrink
4103 the parent back to its original size, the new proportional
4104 size of this window will increase by delta. */
4106 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4108 /* Add delta1 lines or columns to this window, and to the parent,
4109 keeping things consistent while not affecting siblings. */
4110 CURSIZE (XWINDOW (parent)) = opht + delta1;
4111 (*setsizefun) (window, *sizep + delta1, 0);
4113 /* Squeeze out delta1 lines or columns from our parent,
4114 shrinking this window and siblings proportionately.
4115 This brings parent back to correct size.
4116 Delta1 was calculated so this makes this window the desired size,
4117 taking it all out of the siblings. */
4118 (*setsizefun) (parent, opht, 0);
4121 SET_LAST_MODIFIED (w, 0);
4122 SET_LAST_FACECHANGE (w);
4123 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4124 /* overkill maybe, but better to be correct */
4125 MARK_FRAME_GUTTERS_CHANGED (f);
4135 /* Scroll contents of window WINDOW up N lines. If N < (top line height /
4136 average line height) then we just adjust the top clip. */
4138 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
4139 Error_behavior errb)
4141 struct window *w = XWINDOW (window);
4142 struct buffer *b = XBUFFER (w->buffer);
4143 int selected = EQ (window, Fselected_window (Qnil));
4145 Lisp_Object point, tem;
4146 display_line_dynarr *dla;
4147 int fheight, fwidth, modeline = 0;
4148 struct display_line* dl;
4151 point = make_int (BUF_PT (b));
4154 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4156 if (pos < BUF_BEGV (b))
4158 else if (pos > BUF_ZV (b))
4161 point = make_int (pos);
4164 /* Always set force_start so that redisplay_window will run
4165 the window-scroll-functions. */
4168 /* #### When the fuck does this happen? I'm so glad that history has
4169 completely documented the behavior of the scrolling functions under
4170 all circumstances. */
4171 tem = Fpos_visible_in_window_p (point, window);
4174 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4176 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4177 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4178 WINDOW_TEXT_TOP_CLIP (w) = 0;
4179 MARK_WINDOWS_CHANGED (w);
4188 n = Fprefix_numeric_value (n);
4189 value = XINT (n) * direction;
4192 return; /* someone just made a pointless call */
4196 /* If the user didn't specify how far to scroll then we have to figure it
4197 out by ourselves. */
4198 if (NILP (n) || EQ (n, Qminus))
4200 /* Going forwards is easy. If that is what we are doing then just
4201 set value and the section which handles the user specifying a
4202 positive value will work. */
4205 value = window_displayed_height (w) - next_screen_context_lines;
4206 value = (value < 1 ? 1 : value);
4209 /* Going backwards is hard. We can't use the same loop used if the
4210 user specified a negative value because we care about
4211 next_screen_context_lines. In a variable height world you don't
4212 know how many lines above you can actually be displayed and still
4213 have the context lines appear. So we leave value set to 0 and add
4214 a separate section to deal with this. */
4218 if (direction == 1 && !value)
4223 /* Determine parameters to test for partial line scrolling with. */
4224 dla = window_display_lines (w, CURRENT_DISP);
4226 if (INTP (Vwindow_pixel_scroll_increment))
4227 fheight = XINT (Vwindow_pixel_scroll_increment);
4228 else if (!NILP (Vwindow_pixel_scroll_increment))
4229 default_face_height_and_width (window, &fheight, &fwidth);
4231 if (Dynarr_length (dla) >= 1)
4232 modeline = Dynarr_atp (dla, 0)->modeline;
4234 dl = Dynarr_atp (dla, modeline);
4238 /* Go for partial display line scrolling. This just means bumping
4239 the clip by a reasonable amount and redisplaying, everything else
4240 remains unchanged. */
4241 if (!NILP (Vwindow_pixel_scroll_increment)
4243 Dynarr_length (dla) >= (1 + modeline)
4245 (dl->ascent - dl->top_clip) - fheight * value > 0)
4247 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4248 MARK_WINDOWS_CHANGED (w);
4253 Bufpos startp, old_start;
4255 if (WINDOW_TEXT_TOP_CLIP (w))
4257 WINDOW_TEXT_TOP_CLIP (w) = 0;
4258 MARK_WINDOWS_CHANGED (w);
4261 old_start = marker_position (w->start[CURRENT_DISP]);
4262 startp = vmotion (w, old_start, value, &vtarget);
4264 if (vtarget < value &&
4265 (w->window_end_pos[CURRENT_DISP] == -1
4266 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4268 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4273 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4276 w->start_at_line_beg = beginning_of_line_p (b, startp);
4277 MARK_WINDOWS_CHANGED (w);
4279 if (!point_would_be_visible (w, startp, XINT (point)))
4282 BUF_SET_PT (b, startp);
4284 set_marker_restricted (w->pointm[CURRENT_DISP],
4293 /* Go for partial display line scrolling. This just means bumping
4294 the clip by a reasonable amount and redisplaying, everything else
4295 remains unchanged. */
4296 if (!NILP (Vwindow_pixel_scroll_increment)
4298 Dynarr_length (dla) >= (1 + modeline)
4300 (dl->ascent - dl->top_clip) - fheight * value <
4301 (dl->ascent + dl->descent - dl->clip)
4303 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4305 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4306 MARK_WINDOWS_CHANGED (w);
4311 Bufpos startp, old_start;
4313 if (WINDOW_TEXT_TOP_CLIP (w))
4315 WINDOW_TEXT_TOP_CLIP (w) = 0;
4316 MARK_WINDOWS_CHANGED (w);
4319 old_start = marker_position (w->start[CURRENT_DISP]);
4320 startp = vmotion (w, old_start, value, &vtarget);
4323 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4325 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4330 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4333 w->start_at_line_beg = beginning_of_line_p (b, startp);
4334 MARK_WINDOWS_CHANGED (w);
4336 /* #### Scroll back by less than a line. This code was
4337 originally for scrolling over large pixmaps and it
4338 loses when a line being *exposed* at the top of the
4339 window is bigger than the current one. However, for
4340 pixel based scrolling in general we can guess that
4341 the line we are going to display is probably the same
4342 size as the one we are on. In that instance we can
4343 have a reasonable stab at a suitable top clip. Fixing
4344 this properly is hard (and probably slow) as we would
4345 have to call redisplay to figure out the exposed line
4347 if (!NILP (Vwindow_pixel_scroll_increment)
4348 && Dynarr_length (dla) >= (1 + modeline)
4349 && dl->ascent + fheight * value > 0)
4351 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4354 if (!point_would_be_visible (w, startp, XINT (point)))
4358 if (MINI_WINDOW_P (w))
4361 new_point = start_of_last_line (w, startp);
4364 BUF_SET_PT (b, new_point);
4366 set_marker_restricted (w->pointm[CURRENT_DISP],
4367 make_int (new_point),
4373 else /* value == 0 && direction == -1 */
4375 if (WINDOW_TEXT_TOP_CLIP (w))
4377 WINDOW_TEXT_TOP_CLIP (w) = 0;
4378 MARK_WINDOWS_CHANGED (w);
4380 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4382 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4388 int movement = next_screen_context_lines - 1;
4389 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4390 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4392 start_with_point_on_display_line (w, bottom,
4393 -1 - (movement - vtarget));
4395 if (startp >= old_startp)
4396 startp = vmotion (w, old_startp, -1, NULL);
4398 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4401 w->start_at_line_beg = beginning_of_line_p (b, startp);
4402 MARK_WINDOWS_CHANGED (w);
4404 if (!point_would_be_visible (w, startp, XINT (point)))
4406 Bufpos new_point = start_of_last_line (w, startp);
4409 BUF_SET_PT (b, new_point);
4411 set_marker_restricted (w->pointm[CURRENT_DISP],
4412 make_int (new_point),
4419 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4420 Scroll text of current window upward N lines; or near full screen if no arg.
4421 A near full screen is `next-screen-context-lines' less than a full screen.
4422 Negative N means scroll downward.
4423 When calling from a program, supply an integer as argument or nil.
4424 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4425 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4430 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4434 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4435 Scroll text of current window downward N lines; or near full screen if no arg.
4436 A near full screen is `next-screen-context-lines' less than a full screen.
4437 Negative N means scroll upward.
4438 When calling from a program, supply a number as argument or nil.
4439 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4440 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4445 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4449 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4450 Return the other window for "other window scroll" commands.
4451 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4452 specifies the window.
4453 If `other-window-scroll-buffer' is non-nil, a window
4454 showing that buffer is used.
4459 Lisp_Object selected_window = Fselected_window (Qnil);
4461 if (MINI_WINDOW_P (XWINDOW (selected_window))
4462 && !NILP (Vminibuffer_scroll_window))
4463 window = Vminibuffer_scroll_window;
4464 /* If buffer is specified, scroll that buffer. */
4465 else if (!NILP (Vother_window_scroll_buffer))
4467 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4469 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4473 /* Nothing specified; look for a neighboring window on the same
4475 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4477 if (EQ (window, selected_window))
4478 /* That didn't get us anywhere; look for a window on another
4481 window = Fnext_window (window, Qnil, Qt, Qnil);
4482 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4483 && ! EQ (window, selected_window));
4486 CHECK_LIVE_WINDOW (window);
4488 if (EQ (window, selected_window))
4489 error ("There is no other window");
4494 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4495 Scroll next window upward N lines; or near full frame if no arg.
4496 The next window is the one below the current one; or the one at the top
4497 if the current one is at the bottom. Negative N means scroll downward.
4498 When calling from a program, supply a number as argument or nil.
4500 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4501 specifies the window to scroll.
4502 If `other-window-scroll-buffer' is non-nil, scroll the window
4503 showing that buffer, popping the buffer up if necessary.
4507 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4511 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4512 Scroll selected window display N columns left.
4513 Default for N is window width minus 2.
4517 Lisp_Object window = Fselected_window (Qnil);
4518 struct window *w = XWINDOW (window);
4519 int count = (NILP (n) ?
4520 window_char_width (w, 0) - 2 :
4521 XINT (Fprefix_numeric_value (n)));
4523 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4526 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4527 Scroll selected window display N columns right.
4528 Default for N is window width minus 2.
4532 Lisp_Object window = Fselected_window (Qnil);
4533 struct window *w = XWINDOW (window);
4534 int count = (NILP (n) ?
4535 window_char_width (w, 0) - 2 :
4536 XINT (Fprefix_numeric_value (n)));
4538 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4541 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4542 Center point in WINDOW. With N, put point on line N.
4543 The desired position of point is always relative to the window.
4544 If WINDOW is nil, the selected window is used.
4548 struct window *w = decode_window (window);
4549 struct buffer *b = XBUFFER (w->buffer);
4550 Bufpos opoint = BUF_PT (b);
4554 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4557 n = Fprefix_numeric_value (n);
4559 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4562 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4564 w->start_at_line_beg = beginning_of_line_p (b, startp);
4566 MARK_WINDOWS_CHANGED (w);
4570 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4571 Position point relative to WINDOW.
4572 With no argument, position text at center of window.
4573 An argument specifies window line; zero means top of window,
4574 negative means relative to bottom of window.
4575 If WINDOW is nil, the selected window is used.
4582 Bufpos start, new_point;
4585 /* Don't use decode_window() because we need the new value of
4588 window = Fselected_window (Qnil);
4590 CHECK_LIVE_WINDOW (window);
4591 w = XWINDOW (window);
4592 b = XBUFFER (w->buffer);
4594 height = window_displayed_height (w);
4595 selected = EQ (window, Fselected_window (w->frame));
4601 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4602 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4604 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4607 BUF_SET_PT (b, new_point);
4609 Fset_window_point (window, make_int (new_point));
4611 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4615 start = marker_position (w->start[CURRENT_DISP]);
4616 if (start < BUF_BEGV (b))
4617 start = BUF_BEGV (b);
4618 else if (start > BUF_ZV (b))
4622 new_point = BUF_PT (b);
4624 new_point = marker_position (w->pointm[CURRENT_DISP]);
4626 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4629 BUF_SET_PT (b, new_point);
4631 Fset_window_point (window, make_int (new_point));
4633 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4636 return make_int (retval);
4640 /* #### Is this going to work right when at eob? */
4641 arg = Fprefix_numeric_value (arg);
4643 XSETINT (arg, XINT (arg) + height);
4646 start = marker_position (w->start[CURRENT_DISP]);
4647 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4650 new_point = BUF_PT (b);
4652 new_point = marker_position (w->pointm[CURRENT_DISP]);
4654 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4657 BUF_SET_PT (b, new_point);
4659 Fset_window_point (window, make_int (new_point));
4661 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4663 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4669 BUF_SET_PT (b, start);
4671 Fset_window_point (window, make_int (start));
4675 return Fvertical_motion (arg, window, Qnil);
4679 new_point = vmotion (XWINDOW (window),
4680 marker_position (w->pointm[CURRENT_DISP]),
4682 Fset_window_point (window, make_int (new_point));
4683 return make_int (vpos);
4689 map_windows_1 (Lisp_Object window,
4690 int (*mapfun) (struct window *w, void *closure),
4693 for (; !NILP (window); window = XWINDOW (window)->next)
4696 struct window *w = XWINDOW (window);
4698 if (!NILP (w->vchild))
4699 retval = map_windows_1 (w->vchild, mapfun, closure);
4700 else if (!NILP (w->hchild))
4701 retval = map_windows_1 (w->hchild, mapfun, closure);
4703 retval = (mapfun) (w, closure);
4712 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4713 invocation of MAPFUN. If any invocation of MAPFUN returns
4714 non-zero, the mapping is halted. Otherwise, map_windows() maps
4715 over all windows in F.
4717 If MAPFUN creates or deletes windows, the behavior is undefined. */
4720 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4724 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4727 Lisp_Object frmcons, devcons, concons;
4729 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4731 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4743 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4746 w->shadow_thickness_changed = 1;
4747 MARK_WINDOWS_CHANGED (w);
4751 vertical_divider_changed_in_window (Lisp_Object specifier,
4755 MARK_WINDOWS_CHANGED (w);
4756 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4759 /* also used in scrollbar.c */
4761 some_window_value_changed (Lisp_Object specifier, struct window *w,
4764 MARK_WINDOWS_CHANGED (w);
4767 #ifdef MEMORY_USAGE_STATS
4773 #ifdef HAVE_SCROLLBARS
4777 int other_redisplay;
4782 compute_window_mirror_usage (struct window_mirror *mir,
4783 struct window_stats *stats,
4784 struct overhead_stats *ovstats)
4788 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4790 #ifdef HAVE_SCROLLBARS
4792 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4795 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4798 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4801 #endif /* HAVE_SCROLLBARS */
4802 stats->other_redisplay +=
4803 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4804 stats->other_redisplay +=
4805 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4809 compute_window_usage (struct window *w, struct window_stats *stats,
4810 struct overhead_stats *ovstats)
4813 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4814 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4815 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4816 stats->line_start +=
4817 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4818 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4821 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4822 Return stats about the memory usage of window WINDOW.
4823 The values returned are in the form of an alist of usage types and byte
4824 counts. The byte counts attempt to encompass all the memory used
4825 by the window (separate from the memory logically associated with a
4826 buffer or frame), including internal structures and any malloc()
4827 overhead associated with them. In practice, the byte counts are
4828 underestimated because certain memory usage is very hard to determine
4829 \(e.g. the amount of memory used inside the Xt library or inside the
4830 X server) and because there is other stuff that might logically
4831 be associated with a window, buffer, or frame (e.g. window configurations,
4832 glyphs) but should not obviously be included in the usage counts.
4834 Multiple slices of the total memory usage may be returned, separated
4835 by a nil. Each slice represents a particular view of the memory, a
4836 particular way of partitioning it into groups. Within a slice, there
4837 is no overlap between the groups of memory, and each slice collectively
4838 represents all the memory concerned.
4842 struct window_stats stats;
4843 struct overhead_stats ovstats;
4844 Lisp_Object val = Qnil;
4846 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4848 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4850 val = acons (Qface_cache, make_int (stats.face), val);
4851 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4852 #ifdef HAVE_SCROLLBARS
4853 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4855 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4856 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4857 val = acons (Qother, make_int (stats.other), val);
4858 val = Fcons (Qnil, val);
4859 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4860 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4861 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4863 return Fnreverse (val);
4866 #endif /* MEMORY_USAGE_STATS */
4869 /************************************************************************/
4870 /* Window configurations */
4871 /************************************************************************/
4873 /* #### This window configuration stuff has had serious bugs lurking in it
4874 for years; it would be a -huge- win if this was reimplemented in lisp.
4877 /* If you add anything to this structure make sure saved_window_equal
4881 Lisp_Object window; /* window */
4882 Lisp_Object buffer; /* buffer */
4883 Lisp_Object start; /* copied marker */
4884 Lisp_Object pointm; /* copied marker */
4885 Lisp_Object sb_point; /* copied marker */
4886 Lisp_Object mark; /* copied marker */
4892 Charcount modeline_hscroll;
4893 int parent_index; /* index into saved_windows */
4894 int prev_index; /* index into saved_windows */
4895 char start_at_line_beg; /* boolean */
4897 #define WINDOW_SLOT_DECLARATION
4898 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4899 #include "winslots.h"
4902 /* If you add anything to this structure make sure window_config_equal
4904 struct window_config
4906 struct lcrecord_header header;
4907 /* int frame_width; No longer needed, JV
4908 int frame_height; */
4910 Lisp_Object selected_frame;
4912 Lisp_Object current_window;
4913 Lisp_Object current_buffer;
4914 Lisp_Object minibuffer_scroll_window;
4915 Lisp_Object root_window;
4916 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4917 /* Record the values of window-min-width and window-min-height
4918 so that window sizes remain consistent with them. */
4919 int min_width, min_height;
4920 int saved_windows_count;
4921 /* Zero-sized arrays aren't ANSI C */
4922 struct saved_window saved_windows[1];
4925 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4926 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4927 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4928 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4929 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4932 mark_window_config (Lisp_Object obj)
4934 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4936 mark_object (config->current_window);
4937 mark_object (config->current_buffer);
4938 mark_object (config->minibuffer_scroll_window);
4939 mark_object (config->root_window);
4941 for (i = 0; i < config->saved_windows_count; i++)
4943 struct saved_window *s = SAVED_WINDOW_N (config, i);
4944 mark_object (s->window);
4945 mark_object (s->buffer);
4946 mark_object (s->start);
4947 mark_object (s->pointm);
4948 mark_object (s->sb_point);
4949 mark_object (s->mark);
4951 /* #### This looked like this. I do not see why specifier cached
4952 values should not be marked, as such specifiers as toolbars
4953 might have GC-able instances. Freed configs are not marked,
4954 aren't they? -- kkm */
4955 mark_object (s->dedicated);
4957 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
4958 #include "winslots.h"
4965 sizeof_window_config_for_n_windows (int n)
4967 return (sizeof (struct window_config) +
4968 /* n - 1 because zero-sized arrays aren't ANSI C */
4969 (n - 1) *sizeof (struct saved_window));
4973 sizeof_window_config (const void *h)
4975 const struct window_config *c = (const struct window_config *) h;
4976 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4980 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4982 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4985 error ("printing unreadable object #<window-configuration 0x%x>",
4986 config->header.uid);
4987 write_c_string ("#<window-configuration ", printcharfun);
4988 sprintf (buf, "0x%x>", config->header.uid);
4989 write_c_string (buf, printcharfun);
4992 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4993 window_configuration,
4995 print_window_config,
4996 0, 0, 0, 0, sizeof_window_config,
4997 struct window_config);
5000 /* Returns a boolean indicating whether the two saved windows are
5003 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
5005 #define WINDOW_SLOT(slot, compare) \
5006 if (!compare (win1->slot, win2->slot)) \
5008 #include "winslots.h"
5011 EQ (win1->window, win2->window) &&
5012 EQ (win1->buffer, win2->buffer) &&
5013 internal_equal (win1->start, win2->start, 0) &&
5014 internal_equal (win1->pointm, win2->pointm, 0) &&
5015 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5016 internal_equal (win1->mark, win2->mark, 0) &&
5017 win1->pixel_left == win2->pixel_left &&
5018 win1->pixel_top == win2->pixel_top &&
5019 win1->pixel_width == win2->pixel_width &&
5020 win1->pixel_height == win2->pixel_height &&
5021 win1->hscroll == win2->hscroll &&
5022 win1->modeline_hscroll == win2->modeline_hscroll &&
5023 win1->parent_index == win2->parent_index &&
5024 win1->prev_index == win2->prev_index &&
5025 win1->start_at_line_beg == win2->start_at_line_beg;
5028 /* Returns a boolean indicating whether the two given configurations
5031 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5033 struct window_config *fig1, *fig2;
5036 /* First check if they are truly the same. */
5037 if (EQ (conf1, conf2))
5040 fig1 = XWINDOW_CONFIGURATION (conf1);
5041 fig2 = XWINDOW_CONFIGURATION (conf2);
5043 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5044 EQ (fig1->current_window, fig2->current_window) &&
5045 EQ (fig1->current_buffer, fig2->current_buffer) &&
5046 EQ (fig1->root_window, fig2->root_window) &&
5047 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5049 fig1->frame_width == fig2->frame_width &&
5050 fig1->frame_height == fig2->frame_height)) */
5053 for (i = 0; i < fig1->saved_windows_count; i++)
5055 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5056 SAVED_WINDOW_N (fig2, i)))
5063 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5064 Return t if OBJECT is a window-configuration object.
5068 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
5072 mark_windows_in_use_closure (struct window *w, void *closure)
5074 int mark = *(int *)closure;
5075 w->config_mark = mark;
5080 mark_windows_in_use (struct frame *f, int mark)
5082 map_windows (f, mark_windows_in_use_closure, &mark);
5085 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5087 free_window_configuration (Lisp_Object window_config)
5090 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5092 /* Free all the markers. It's not completely necessary that
5093 we do this (window configs sitting in a free list aren't
5094 marked normally so the markers wouldn't be marked anyway)
5095 but it's more efficient. */
5096 for (i = 0; i < config->saved_windows_count; i++)
5098 struct saved_window *p = SAVED_WINDOW_N (config, i);
5100 if (!NILP (p->pointm))
5102 free_marker (XMARKER (p->pointm));
5105 if (!NILP (p->start))
5107 free_marker (XMARKER (p->start));
5110 if (!NILP (p->sb_point))
5112 free_marker (XMARKER (p->sb_point));
5115 if (!NILP (p->mark))
5117 free_marker (XMARKER (p->mark));
5122 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5123 free_managed_lcrecord (Vwindow_configuration_free_list
5124 [config->saved_windows_count - 1],
5130 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5131 Set the configuration of windows and buffers as specified by CONFIGURATION.
5132 CONFIGURATION must be a value previously returned
5133 by `current-window-configuration' (which see).
5138 struct window_config *config;
5139 struct saved_window *p;
5140 Lisp_Object new_current_buffer;
5144 struct gcpro gcpro1;
5145 Lisp_Object old_window_config;
5146 /* int previous_frame_height;
5147 int previous_frame_width;*/
5148 int previous_pixel_top;
5149 int previous_pixel_height;
5150 int previous_pixel_left;
5151 int previous_pixel_width;
5152 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5153 int real_font_height;
5154 int converted_minibuf_height,target_minibuf_height;
5155 int specpdl_count = specpdl_depth ();
5157 GCPRO1 (configuration);
5159 CHECK_WINDOW_CONFIGURATION (configuration);
5160 config = XWINDOW_CONFIGURATION (configuration);
5162 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5165 /* Do not signal an error here if the frame was deleted. There are
5166 reasonable cases where we could get here with a deleted frame and
5167 just want to do close to nothing instead. */
5169 if (FRAME_LIVE_P (f))
5171 /* restore the frame characteristics */
5173 new_current_buffer = config->current_buffer;
5174 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5175 new_current_buffer = Qnil;
5178 * Assumed precondition: w->config_mark = 0 for all w
5179 * This procedure should ensure this is true by the time it exits
5180 * to ensure the precondition for future calls.
5182 * We use w->config_mark to know whether we're modifying a
5183 * window that is currently visible on the frame (#### we
5184 * should just be able to check whether the window is dead
5185 * or not, but this way is safer?). As we process each
5186 * window, we set its config_mark to 0. At the end, we
5187 * go through all the windows that used to be on the frame,
5188 * set each one's config_mark to 0 (to maintain the
5189 * assumed precondition) and delete each one that's no
5192 * #### Using a window-configuration to keep track of
5193 * the current windows is wasteful. All we need is the
5194 * list of windows, so we could just use a dynarr.
5196 old_window_config = Fcurrent_window_configuration (frame);
5198 /* If the new configuration is already equal to the old, then stop
5199 right here. This saves the work below and it also saves
5200 triggering a full redisplay of this window. This is a huge win
5201 when using the mouse since the mode motion code uses
5202 save-window-excursion extensively but will rarely cause the
5203 configuration to actually change. */
5204 if (window_config_equal (configuration, old_window_config))
5206 free_window_configuration (old_window_config);
5211 /* We can't quit or even check for quit because that may cause
5212 investigation of the frame state, which may crash if the frame is
5213 in an inconsistent state. */
5214 begin_dont_check_for_quit ();
5215 record_unwind_protect (free_window_configuration, old_window_config);
5217 mark_windows_in_use (f, 1);
5219 /* Force subwindows to be reinstantiated. They are all going
5220 anyway and if we don't do this GC may not happen between now
5221 and the next time we check their integrity. */
5222 reset_frame_subwindow_instance_cache (f);
5225 /* JV: This is bogus,
5226 First of all, the units are inconsistent. The frame sizes are measured
5227 in characters but the window sizes are stored in pixels. So if a
5228 font size change happened between saving and restoring, the
5229 frame "sizes" maybe equal but the windows still should be
5230 resized. This is tickled alot by the new "character size
5231 stays constant" policy in 21.0. It leads to very wierd
5232 glitches (and possibly crashes when asserts are tickled).
5234 Just changing the units doens't help because changing the
5235 toolbar configuration can also change the pixel positions.
5236 Luckily there is a much simpler way of doing this, see below.
5238 previous_frame_width = FRAME_WIDTH (f);
5239 previous_frame_height = FRAME_HEIGHT (f);
5240 /* If the frame has been resized since this window configuration was
5241 made, we change the frame to the size specified in the
5242 configuration, restore the configuration, and then resize it
5243 back. We keep track of the prevailing height in these variables. */
5244 if (config->frame_height != FRAME_HEIGHT (f)
5245 || config->frame_width != FRAME_WIDTH (f))
5246 change_frame_size (f, config->frame_height, config->frame_width, 0);
5249 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5250 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5251 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5252 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5254 /* remember some properties of the minibuffer */
5256 default_face_height_and_width (frame, &real_font_height, 0);
5257 assert(real_font_height > 0);
5259 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5261 previous_minibuf_height
5262 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5263 previous_minibuf_top
5264 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5265 previous_minibuf_width
5266 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5270 previous_minibuf_height = 0;
5271 previous_minibuf_top = 0;
5272 previous_minibuf_width = 0;
5274 converted_minibuf_height =
5275 (previous_minibuf_height % real_font_height) == 0 ?
5276 - (previous_minibuf_height / real_font_height ) : /* lines */
5277 previous_minibuf_height; /* pixels */
5279 /* Temporarily avoid any problems with windows that are smaller
5280 than they are supposed to be. */
5281 window_min_height = 1;
5282 window_min_width = 1;
5284 /* OK, now restore all the windows in the window config.
5285 This may involve "undeleting" windows, since the
5286 windows in the window config may be deleted.
5288 for (k = 0; k < config->saved_windows_count; k++)
5290 p = SAVED_WINDOW_N (config, k);
5291 w = XWINDOW (p->window);
5294 /* The window might be dead. In this case, its redisplay
5295 structures were freed, so we need to reallocate them. */
5296 if (!w->face_cachels)
5298 w->face_cachels = Dynarr_new (face_cachel);
5299 reset_face_cachels (w);
5301 if (!w->glyph_cachels)
5302 w->glyph_cachels = Dynarr_new (glyph_cachel);
5303 if (!w->line_start_cache)
5304 w->line_start_cache = Dynarr_new (line_start_cache);
5305 w->gutter_extent_modiff[0] = 0;
5306 w->gutter_extent_modiff[1] = 0;
5307 w->gutter_extent_modiff[2] = 0;
5308 w->gutter_extent_modiff[3] = 0;
5311 if (p->parent_index >= 0)
5312 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5316 if (p->prev_index >= 0)
5318 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5320 /* This is true for a minibuffer-only frame. */
5321 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5324 XWINDOW (w->prev)->next = p->window;
5329 if (!NILP (w->parent))
5331 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5333 XWINDOW (w->parent)->vchild = p->window;
5334 XWINDOW (w->parent)->hchild = Qnil;
5338 XWINDOW (w->parent)->hchild = p->window;
5339 XWINDOW (w->parent)->vchild = Qnil;
5343 if (!w->config_mark)
5345 /* #### This should be equivalent to the window previously
5346 having been dead. If we're brave, we'll put in an
5347 assertion to this effect. */
5348 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5350 else /* if (!EQ (w->buffer, p->buffer)) */
5352 /* With the new redisplay we let it know that a change has
5353 been made and it will take care of the rest. If we don't
5354 tell it something has possibly changed it could lead to
5355 incorrect display. */
5356 MARK_WINDOWS_CHANGED (w);
5359 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5360 WINDOW_TOP (w) = WINDOW_TOP (p);
5361 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5362 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5363 w->hscroll = p->hscroll;
5364 w->modeline_hscroll = p->modeline_hscroll;
5365 w->line_cache_last_updated = Qzero;
5366 /* The subwindow instance cache isn't preserved across
5367 window configurations, and in fact doing so would be
5368 wrong. We just reset to zero and then redisplay will fill
5370 w->subwindow_instance_cache =
5371 make_lisp_hash_table (30,
5372 HASH_TABLE_KEY_WEAK,
5374 SET_LAST_MODIFIED (w, 1);
5375 SET_LAST_FACECHANGE (w);
5378 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5379 #include "winslots.h"
5381 /* Reinstall the saved buffer and pointers into it. */
5382 if (NILP (p->buffer))
5383 w->buffer = p->buffer;
5386 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5387 /* If saved buffer is alive, install it. */
5389 w->buffer = p->buffer;
5390 w->start_at_line_beg = p->start_at_line_beg;
5391 set_marker_restricted (w->start[CURRENT_DISP],
5392 Fmarker_position (p->start),
5394 set_marker_restricted (w->pointm[CURRENT_DISP],
5395 Fmarker_position (p->pointm),
5397 set_marker_restricted (w->sb_point,
5398 Fmarker_position (p->sb_point),
5400 Fset_marker (XBUFFER (w->buffer)->mark,
5401 Fmarker_position (p->mark), w->buffer);
5403 /* As documented in Fcurrent_window_configuration, don't
5404 save the location of point in the buffer which was current
5405 when the window configuration was recorded. */
5406 if (!EQ (p->buffer, new_current_buffer) &&
5407 XBUFFER (p->buffer) == current_buffer)
5408 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5410 else if (NILP (w->buffer) ||
5411 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5412 /* Else if window's old buffer is dead too, get a live one. */
5414 /* #### The following line makes me nervous... */
5415 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5416 w->buffer = Fget_buffer_create (QSscratch);
5417 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5418 /* This will set the markers to beginning of visible
5420 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5421 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5423 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5424 w->start_at_line_beg = 1;
5427 /* Keeping window's old buffer; make sure the markers
5430 /* Set window markers at start of visible range. */
5431 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5432 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5434 if (XMARKER (w->sb_point)->buffer == 0)
5435 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5436 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5437 set_marker_restricted (w->pointm[CURRENT_DISP],
5439 (BUF_PT (XBUFFER (w->buffer))),
5441 w->start_at_line_beg = 1;
5446 FRAME_ROOT_WINDOW (f) = config->root_window;
5447 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5448 then calls do_switch_frame() below to select the frame that was
5449 recorded in the window config as being selected.
5451 Instead, we don't ever change the selected frame, and either
5452 call Fselect_window() below if the window config's frame is
5453 currently selected, or just set the selected window of the
5454 window config's frame. */
5457 /* Set the frame height to the value it had before this function. */
5458 if (previous_frame_height != FRAME_HEIGHT (f)
5459 || previous_frame_width != FRAME_WIDTH (f))
5460 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5462 /* We just reset the size and position of the minibuffer, to its old
5463 value, which needn't be valid. So we do some magic to see which value
5464 to actually take. Then we set it.
5467 We take the old value if is in the same units but differs from the
5470 #### Now we get more cases correct then ever before, but
5471 are we treating all? For instance what if the frames minibuf window
5472 is no longer the same one?
5474 target_minibuf_height = previous_minibuf_height;
5475 if (converted_minibuf_height &&
5476 (converted_minibuf_height * config->minibuf_height) > 0 &&
5477 (converted_minibuf_height != config->minibuf_height))
5479 target_minibuf_height = config->minibuf_height < 0 ?
5480 - (config->minibuf_height * real_font_height) :
5481 config->minibuf_height;
5482 target_minibuf_height =
5483 max(target_minibuf_height,real_font_height);
5485 if (previous_minibuf_height)
5487 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5488 = previous_minibuf_top -
5489 (target_minibuf_height - previous_minibuf_height);
5490 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5491 target_minibuf_height, 0);
5492 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5493 previous_minibuf_width, 0);
5496 /* This is a better way to deal with frame resizing, etc.
5497 What we _actually_ want is for the old (just restored)
5499 into the place of the new one. So we just do that. Simple! */
5500 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5501 /* Note that this function also updates the subwindow
5503 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5504 previous_pixel_height -
5505 (target_minibuf_height - previous_minibuf_height), 0);
5506 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5507 /* Note that this function also updates the subwindow
5509 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5511 /* If restoring in the current frame make the window current,
5512 otherwise just update the frame selected_window slot to be
5513 the restored current_window. */
5514 if (f == selected_frame ())
5517 /* When using `pop-window-configuration', often the minibuffer
5518 ends up as the selected window even though it's not active ...
5519 I really don't know the cause of this, but it should never
5520 happen. This kludge should fix it.
5522 #### Find out why this is really going wrong. */
5523 if (!minibuf_level &&
5524 MINI_WINDOW_P (XWINDOW (config->current_window)))
5525 window_to_select = Fnext_window (config->current_window,
5528 window_to_select = config->current_window;
5530 /* Do this last so that buffer stacking is calculated
5532 Fselect_window (config->current_window, Qnil);
5534 if (!NILP (new_current_buffer))
5536 Fset_buffer (new_current_buffer);
5537 Frecord_buffer (new_current_buffer);
5541 Fset_buffer (XWINDOW (config->current_window)->buffer);
5542 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5546 set_frame_selected_window (f, config->current_window);
5549 old_window_config = Qnil; /* Warning suppression */
5551 /* Restore the minimum heights recorded in the configuration. */
5552 window_min_height = config->min_height;
5553 window_min_width = config->min_width;
5556 /* see above comment */
5557 /* Fselect_window will have made f the selected frame, so we
5558 reselect the proper frame here. Fhandle_switch_frame will change the
5559 selected window too, but that doesn't make the call to
5560 Fselect_window above totally superfluous; it still sets f's
5562 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5563 do_switch_frame (config->selected_frame, Qnil, 0);
5566 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5568 if (FRAME_LIVE_P (f))
5570 /* Do this before calling recompute_all_cached_specifiers_in_window()
5571 so that things like redisplay_redraw_cursor() won't abort due
5572 to no window mirror present. */
5573 f->mirror_dirty = 1;
5575 config = XWINDOW_CONFIGURATION (old_window_config);
5576 for (k = 0; k < config->saved_windows_count; k++)
5578 p = SAVED_WINDOW_N (config, k);
5579 w = XWINDOW (p->window);
5580 /* Remember, we set w->config_mark on all currently visible
5581 windows, and reset it on all newly visible windows.
5582 Any windows still marked need to be deleted. */
5585 mark_window_as_deleted (w);
5590 /* We just potentially changed the window's buffer and
5591 potentially turned a dead window into a live one,
5592 so we need to recompute the cached specifier values. */
5593 recompute_all_cached_specifiers_in_window (w);
5598 /* Now restore things, when everything else if OK. */
5600 unbind_to (specpdl_count, Qnil);
5607 /* Mark all subwindows of a window as deleted. The argument
5608 W is actually the subwindow tree of the window in question. */
5611 delete_all_subwindows (struct window *w)
5613 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5614 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5615 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5617 mark_window_as_deleted (w);
5622 count_windows (struct window *window)
5625 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5626 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5627 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5631 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5634 for (j = 0; j < lim; j++)
5636 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5640 return 0; /* suppress compiler warning */
5644 save_window_save (Lisp_Object window, struct window_config *config, int i)
5648 for (; !NILP (window); window = w->next)
5650 struct saved_window *p = SAVED_WINDOW_N (config, i);
5652 w = XWINDOW (window);
5655 p->buffer = w->buffer;
5656 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5657 WINDOW_TOP (p) = WINDOW_TOP (w);
5658 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5659 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5660 p->hscroll = w->hscroll;
5661 p->modeline_hscroll = w->modeline_hscroll;
5663 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5664 #include "winslots.h"
5666 if (!NILP (w->buffer))
5668 /* Save w's value of point in the window configuration.
5669 If w is the selected window, then get the value of point
5670 from the buffer; pointm is garbage in the selected window. */
5671 if (EQ (window, Fselected_window (Qnil)))
5673 p->pointm = noseeum_make_marker ();
5674 Fset_marker (p->pointm,
5675 make_int (BUF_PT (XBUFFER (w->buffer))),
5679 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5681 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5682 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5683 p->start_at_line_beg = w->start_at_line_beg;
5685 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5693 p->start_at_line_beg = 0;
5696 if (NILP (w->parent))
5697 p->parent_index = -1;
5699 p->parent_index = saved_window_index (w->parent, config, i);
5703 p->prev_index = saved_window_index (w->prev, config, i);
5704 if (!NILP (w->vchild))
5705 i = save_window_save (w->vchild, config, i);
5706 if (!NILP (w->hchild))
5707 i = save_window_save (w->hchild, config, i);
5714 /* Added to doc string:
5716 This also records the currently selected frame, and FRAME's focus
5717 redirection (see `redirect-frame-focus').
5722 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5723 Return an object representing the current window configuration of FRAME.
5724 If FRAME is nil or omitted, use the selected frame.
5725 This describes the number of windows, their sizes and current buffers,
5726 and for each displayed buffer, where display starts, and the positions of
5727 point and mark. An exception is made for point in the current buffer:
5728 its value is -not- saved.
5733 struct frame *f = decode_frame (frame);
5734 struct window_config *config;
5735 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5737 int real_font_height;
5739 if (n_windows <= countof (Vwindow_configuration_free_list))
5740 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5741 (Vwindow_configuration_free_list
5744 /* More than ten windows; just allocate directly */
5745 config = (struct window_config *)
5746 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5747 &lrecord_window_configuration);
5748 XSETWINDOW_CONFIGURATION (result, config);
5750 config->frame_width = FRAME_WIDTH (f);
5751 config->frame_height = FRAME_HEIGHT (f); */
5752 /* When using `push-window-configuration', often the minibuffer ends
5753 up as the selected window because functions run as the result of
5754 user interaction e.g. hyper-apropros. It seems to me the sensible
5755 thing to do is not record the minibuffer here. */
5756 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5757 config->current_window = FRAME_SELECTED_WINDOW (f);
5759 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5760 XSETBUFFER (config->current_buffer, current_buffer);
5761 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5762 config->root_window = FRAME_ROOT_WINDOW (f);
5763 config->min_height = window_min_height;
5764 config->min_width = window_min_width;
5765 config->saved_windows_count = n_windows;
5766 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5768 /* save the minibuffer height using the heuristics from
5769 change_frame_size_1 */
5771 XSETFRAME (frame, f); /* frame could have been nil ! */
5772 default_face_height_and_width (frame, &real_font_height, 0);
5773 assert(real_font_height > 0);
5775 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5776 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5779 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5780 - (minibuf_height / real_font_height ) : /* lines */
5781 minibuf_height; /* pixels */
5787 save_window_excursion_unwind (Lisp_Object window_config)
5789 Lisp_Object val = Fset_window_configuration (window_config);
5790 free_window_configuration (window_config);
5794 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5795 Execute body, preserving window sizes and contents.
5796 Restores which buffer appears in which window, where display starts,
5797 as well as the current buffer.
5798 Does not restore the value of point in current buffer.
5802 /* This function can GC */
5804 int speccount = specpdl_depth ();
5806 record_unwind_protect (save_window_excursion_unwind,
5807 Fcurrent_window_configuration (Qnil));
5808 val = Fprogn (args);
5809 return unbind_to (speccount, val);
5812 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5813 Return the horizontal pixel position of POS in window.
5814 Beginning of line is column 0. This is calculated using the redisplay
5815 display tables. If WINDOW is nil, the current window is assumed.
5816 If POS is nil, point is assumed. Note that POS must be visible for
5817 a non-nil result to be returned.
5821 struct window* w = decode_window (window);
5822 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5824 struct display_line *dl = 0;
5825 struct display_block *db = 0;
5826 struct rune* rb = 0;
5827 int y = w->last_point_y[CURRENT_DISP];
5828 int x = w->last_point_x[CURRENT_DISP];
5830 if (MINI_WINDOW_P (w))
5833 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5839 pos = Fwindow_point (window);
5844 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5849 for (i = first_line; i < Dynarr_length (dla); i++)
5851 dl = Dynarr_atp (dla, i);
5852 /* find the vertical location first */
5853 if (point >= dl->bufpos && point <= dl->end_bufpos)
5855 db = get_display_block_from_line (dl, TEXT);
5856 for (i = 0; i < Dynarr_length (db->runes); i++)
5858 rb = Dynarr_atp (db->runes, i);
5859 if (point <= rb->bufpos)
5871 /* optimised case */
5872 dl = Dynarr_atp (dla, y);
5873 db = get_display_block_from_line (dl, TEXT);
5875 if (x >= Dynarr_length (db->runes))
5878 rb = Dynarr_atp (db->runes, x);
5881 return make_int (rb->xpos - WINDOW_LEFT (w));
5886 /* This is short and simple in elisp, but... it was written to debug
5887 problems purely on the C side. That is where we need to call it so
5890 debug_print_window (Lisp_Object window, int level)
5893 Lisp_Object child = Fwindow_first_vchild (window);
5896 child = Fwindow_first_hchild (window);
5898 for (i = level; i > 0; i--)
5901 stderr_out ("#<window");
5903 Lisp_Object buffer = XWINDOW (window)->buffer;
5904 if (!NILP (buffer) && BUFFERP (buffer))
5905 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5907 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
5909 while (!NILP (child))
5911 debug_print_window (child, level + 1);
5912 child = Fwindow_next_child (child);
5916 void debug_print_windows (struct frame *f);
5918 debug_print_windows (struct frame *f)
5920 debug_print_window (f->root_window, 0);
5921 putc ('\n', stderr);
5923 #endif /* DEBUG_XEMACS */
5926 /************************************************************************/
5927 /* initialization */
5928 /************************************************************************/
5931 syms_of_window (void)
5933 INIT_LRECORD_IMPLEMENTATION (window);
5934 INIT_LRECORD_IMPLEMENTATION (window_configuration);
5936 defsymbol (&Qwindowp, "windowp");
5937 defsymbol (&Qwindow_live_p, "window-live-p");
5938 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5939 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5940 defsymbol (&Qdisplay_buffer, "display-buffer");
5942 #ifdef MEMORY_USAGE_STATS
5943 defsymbol (&Qface_cache, "face-cache");
5944 defsymbol (&Qglyph_cache, "glyph-cache");
5945 defsymbol (&Qline_start_cache, "line-start-cache");
5946 #ifdef HAVE_SCROLLBARS
5947 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5949 defsymbol (&Qother_redisplay, "other-redisplay");
5950 /* Qother in general.c */
5953 DEFSUBR (Fselected_window);
5954 DEFSUBR (Flast_nonminibuf_window);
5955 DEFSUBR (Fminibuffer_window);
5956 DEFSUBR (Fwindow_minibuffer_p);
5958 DEFSUBR (Fwindow_live_p);
5959 DEFSUBR (Fwindow_first_hchild);
5960 DEFSUBR (Fwindow_first_vchild);
5961 DEFSUBR (Fwindow_next_child);
5962 DEFSUBR (Fwindow_previous_child);
5963 DEFSUBR (Fwindow_parent);
5964 DEFSUBR (Fwindow_lowest_p);
5965 DEFSUBR (Fwindow_truncated_p);
5966 DEFSUBR (Fwindow_highest_p);
5967 DEFSUBR (Fwindow_leftmost_p);
5968 DEFSUBR (Fwindow_rightmost_p);
5969 DEFSUBR (Fpos_visible_in_window_p);
5970 DEFSUBR (Fwindow_buffer);
5971 DEFSUBR (Fwindow_frame);
5972 DEFSUBR (Fwindow_height);
5973 DEFSUBR (Fwindow_displayed_height);
5974 DEFSUBR (Fwindow_width);
5975 DEFSUBR (Fwindow_full_width);
5976 DEFSUBR (Fwindow_pixel_height);
5977 DEFSUBR (Fwindow_pixel_width);
5978 DEFSUBR (Fwindow_text_area_height);
5979 DEFSUBR (Fwindow_text_area_pixel_height);
5980 DEFSUBR (Fwindow_displayed_text_pixel_height);
5981 DEFSUBR (Fwindow_text_area_pixel_width);
5982 DEFSUBR (Fwindow_hscroll);
5983 DEFSUBR (Fset_window_hscroll);
5984 DEFSUBR (Fmodeline_hscroll);
5985 DEFSUBR (Fset_modeline_hscroll);
5986 #if 0 /* bogus FSF crock */
5987 DEFSUBR (Fwindow_redisplay_end_trigger);
5988 DEFSUBR (Fset_window_redisplay_end_trigger);
5990 DEFSUBR (Fwindow_pixel_edges);
5991 DEFSUBR (Fwindow_text_area_pixel_edges);
5992 DEFSUBR (Fwindow_point);
5993 DEFSUBR (Fwindow_start);
5994 DEFSUBR (Fwindow_end);
5995 DEFSUBR (Fwindow_last_line_visible_height);
5996 DEFSUBR (Fset_window_point);
5997 DEFSUBR (Fset_window_start);
5998 DEFSUBR (Fwindow_dedicated_p);
5999 DEFSUBR (Fset_window_dedicated_p);
6000 DEFSUBR (Fnext_window);
6001 DEFSUBR (Fprevious_window);
6002 DEFSUBR (Fnext_vertical_window);
6003 DEFSUBR (Fother_window);
6004 DEFSUBR (Fget_lru_window);
6005 DEFSUBR (Fget_largest_window);
6006 DEFSUBR (Fget_buffer_window);
6007 DEFSUBR (Fwindow_left_margin_pixel_width);
6008 DEFSUBR (Fwindow_right_margin_pixel_width);
6009 DEFSUBR (Fdelete_other_windows);
6010 DEFSUBR (Fdelete_windows_on);
6011 DEFSUBR (Freplace_buffer_in_windows);
6012 DEFSUBR (Fdelete_window);
6013 DEFSUBR (Fset_window_buffer);
6014 DEFSUBR (Fselect_window);
6015 DEFSUBR (Fsplit_window);
6016 DEFSUBR (Fenlarge_window);
6017 DEFSUBR (Fenlarge_window_pixels);
6018 DEFSUBR (Fshrink_window);
6019 DEFSUBR (Fshrink_window_pixels);
6020 DEFSUBR (Fscroll_up);
6021 DEFSUBR (Fscroll_down);
6022 DEFSUBR (Fscroll_left);
6023 DEFSUBR (Fscroll_right);
6024 DEFSUBR (Fother_window_for_scrolling);
6025 DEFSUBR (Fscroll_other_window);
6026 DEFSUBR (Fcenter_to_window_line);
6027 DEFSUBR (Fmove_to_window_line);
6028 #ifdef MEMORY_USAGE_STATS
6029 DEFSUBR (Fwindow_memory_usage);
6031 DEFSUBR (Fwindow_configuration_p);
6032 DEFSUBR (Fset_window_configuration);
6033 DEFSUBR (Fcurrent_window_configuration);
6034 DEFSUBR (Fsave_window_excursion);
6035 DEFSUBR (Fcurrent_pixel_column);
6039 reinit_vars_of_window (void)
6042 /* Make sure all windows get marked */
6043 minibuf_window = Qnil;
6044 staticpro_nodump (&minibuf_window);
6046 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6048 Vwindow_configuration_free_list[i] =
6049 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6050 &lrecord_window_configuration);
6051 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6056 vars_of_window (void)
6058 reinit_vars_of_window ();
6060 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6061 *Non-nil means to scroll if point lands on a line which is clipped.
6063 scroll_on_clipped_lines = 1;
6065 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6066 See `temp-buffer-show-function'.
6068 Vtemp_buffer_show_hook = Qnil;
6070 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6071 Non-nil means call as function to display a help buffer.
6072 The function is called with one argument, the buffer to be displayed.
6073 Used by `with-output-to-temp-buffer'.
6074 If this function is used, then it must do the entire job of showing
6075 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6077 Vtemp_buffer_show_function = Qnil;
6079 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6080 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6082 Vminibuffer_scroll_window = Qnil;
6084 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6085 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6087 Vother_window_scroll_buffer = Qnil;
6089 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6090 *Number of pixels to scroll by per requested line.
6091 If nil then normal line scrolling occurs regardless of line height.
6092 If t then scrolling is done in increments equal to the height of the default face.
6094 Vwindow_pixel_scroll_increment = Qt;
6096 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6097 *Number of lines of continuity when scrolling by screenfuls.
6099 next_screen_context_lines = 2;
6101 DEFVAR_INT ("window-min-height", &window_min_height /*
6102 *Delete any window less than this tall (including its modeline).
6104 window_min_height = 4;
6106 DEFVAR_INT ("window-min-width", &window_min_width /*
6107 *Delete any window less than this wide.
6109 window_min_width = 10;
6113 specifier_vars_of_window (void)
6115 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6116 *How thick to draw 3D shadows around modelines.
6117 If this is set to 0, modelines will be the traditional 2D. Sizes above
6118 10 will be accepted but the maximum thickness that will be drawn is 10.
6119 This is a specifier; use `set-specifier' to change it.
6121 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6122 /* The initial value for modeline-shadow-thickness is 2, but if the
6123 user removes all specifications we provide a fallback value of 0,
6124 which is probably what was expected. */
6125 set_specifier_fallback (Vmodeline_shadow_thickness,
6126 list1 (Fcons (Qnil, Qzero)));
6127 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6129 set_specifier_caching (Vmodeline_shadow_thickness,
6130 offsetof (struct window, modeline_shadow_thickness),
6131 modeline_shadow_thickness_changed,
6134 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6135 *Whether the modeline should be displayed.
6136 This is a specifier; use `set-specifier' to change it.
6138 Vhas_modeline_p = Fmake_specifier (Qboolean);
6139 set_specifier_fallback (Vhas_modeline_p,
6140 list1 (Fcons (Qnil, Qt)));
6141 set_specifier_caching (Vhas_modeline_p,
6142 offsetof (struct window, has_modeline_p),
6143 /* #### It's strange that we need a special
6144 flag to indicate that the shadow-thickness
6145 has changed, but not one to indicate that
6146 the modeline has been turned off or on. */
6147 some_window_value_changed,
6150 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6151 &Vvertical_divider_always_visible_p /*
6152 *Should XEmacs always display vertical dividers between windows.
6154 When this is non-nil, vertical dividers are always shown, and are
6155 draggable. When it is nil, vertical dividers are shown only when
6156 there are no scrollbars in between windows, and are not draggable.
6158 This is a specifier; use `set-specifier' to change it.
6160 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6161 set_specifier_fallback (Vvertical_divider_always_visible_p,
6162 list1 (Fcons (Qnil, Qt)));
6163 set_specifier_caching (Vvertical_divider_always_visible_p,
6164 offsetof (struct window,
6165 vertical_divider_always_visible_p),
6166 vertical_divider_changed_in_window,
6169 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6170 *How thick to draw 3D shadows around vertical dividers.
6171 This is a specifier; use `set-specifier' to change it.
6173 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6174 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6175 list1 (Fcons (Qnil, Qzero)));
6176 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6178 set_specifier_caching (Vvertical_divider_shadow_thickness,
6179 offsetof (struct window,
6180 vertical_divider_shadow_thickness),
6181 vertical_divider_changed_in_window,
6183 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6184 *The width of the vertical dividers, not including shadows.
6186 For TTY windows, divider line is always one character wide. When
6187 instance of this specifier is zero in a TTY window, no divider is
6188 drawn at all between windows. When non-zero, a one character wide
6189 divider is displayed.
6191 This is a specifier; use `set-specifier' to change it.
6194 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6196 Lisp_Object fb = Qnil;
6198 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6200 #ifdef HAVE_X_WINDOWS
6201 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6203 #ifdef HAVE_MS_WINDOWS
6204 /* #### This should be made magic and made to obey system settings */
6205 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6207 set_specifier_fallback (Vvertical_divider_line_width, fb);
6209 set_specifier_caching (Vvertical_divider_line_width,
6210 offsetof (struct window,
6211 vertical_divider_line_width),
6212 vertical_divider_changed_in_window,
6215 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6216 *How much space to leave around the vertical dividers.
6218 In TTY windows, spacing is always zero, and the value of this
6219 specifier is ignored.
6221 This is a specifier; use `set-specifier' to change it.
6223 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6225 Lisp_Object fb = Qnil;
6227 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6229 #ifdef HAVE_X_WINDOWS
6230 /* #### 3D dividers look great on MS Windows with spacing = 0.
6231 Should not the same value be the fallback under X? - kkm */
6232 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6234 #ifdef HAVE_MS_WINDOWS
6235 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6237 set_specifier_fallback (Vvertical_divider_spacing, fb);
6239 set_specifier_caching (Vvertical_divider_spacing,
6240 offsetof (struct window, vertical_divider_spacing),
6241 vertical_divider_changed_in_window,