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 (10,
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. */
1872 /* we're deleting W; set the structure of W to indicate this. */
1875 mark_window_as_deleted (struct window *w)
1878 (while t (split-window) (delete-window))
1879 we end up with a tree of deleted windows which are all connected
1880 through the `next' slot. This might not seem so bad, as they're
1881 deleted, and will presumably be GCed - but if even *one* of those
1882 windows is still being pointed to, by the user, or by a window
1883 configuration, then *all* of those windows stick around.
1885 Since the window-configuration code doesn't need any of the
1886 pointers to other windows (they are all recreated from the
1887 window-config data), we set them all to nil so that we
1888 are able to collect more actual garbage.
1898 /* Free the extra data structures attached to windows immediately so
1899 they don't sit around consuming excess space. They will be
1900 reinitialized by the window-configuration code as necessary. */
1901 finalize_window ((void *) w, 0);
1904 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1905 Remove WINDOW from the display. Default is selected window.
1906 If window is the only one on the frame, the frame is destroyed.
1907 Normally, you cannot delete the last non-minibuffer-only frame (you must
1908 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1909 second argument FORCE is non-nil, you can delete the last frame. (This
1910 will automatically call `save-buffers-kill-emacs'.)
1914 /* This function can GC if this is the only window in the frame */
1922 /* Note: this function is called by other C code on non-leaf
1925 /* Do the equivalent of decode_window() but don't error out on
1926 deleted window; it's OK to delete an already-deleted window. */
1928 window = Fselected_window (Qnil);
1930 CHECK_WINDOW (window);
1931 w = XWINDOW (window);
1933 /* It's okay to delete an already-deleted window. */
1934 if (! WINDOW_LIVE_P (w))
1937 frame = WINDOW_FRAME (w);
1939 d = XDEVICE (FRAME_DEVICE (f));
1941 if (TOP_LEVEL_WINDOW_P (w))
1943 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1944 /* this frame isn't fully initialized yet; don't blow up. */
1947 if (MINI_WINDOW_P (XWINDOW (window)))
1948 error ("Attempt to delete the minibuffer window");
1950 /* It has been suggested that it's a good thing for C-x 0 to have this
1951 behavior, but not such a good idea for #'delete-window to have it.
1952 Maybe C-x 0 should be bound to something else, or maybe frame
1953 deletion should only happen when this is called interactively.
1955 delete_frame_internal (f, !NILP (force), 0, 0);
1959 /* At this point, we know the window has a parent. */
1961 par = XWINDOW (parent);
1963 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1964 /* It's quite likely that deleting a window will result in
1965 subwindows needing to be deleted also (since they are cached
1966 per-window). So we mark them as changed, so that the cachels will
1967 get reset by redisplay and thus deleted subwindows can get
1969 MARK_FRAME_SUBWINDOWS_CHANGED (f);
1971 /* Are we trying to delete any frame's selected window?
1972 Note that we could be dealing with a non-leaf window
1973 where the selected window is one of our children.
1974 So, we check by scanning all the ancestors of the
1975 frame's selected window and comparing each one with
1978 Lisp_Object pwindow;
1980 pwindow = FRAME_SELECTED_WINDOW (f);
1982 while (!NILP (pwindow))
1984 if (EQ (window, pwindow))
1986 pwindow = XWINDOW (pwindow)->parent;
1989 if (EQ (window, pwindow))
1991 /* OK, we found it. */
1992 Lisp_Object alternative;
1993 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1995 /* If we're about to delete the selected window on the
1996 selected frame, then we should use Fselect_window to select
1997 the new window. On the other hand, if we're about to
1998 delete the selected window on any other frame, we shouldn't do
1999 anything but set the frame's selected_window slot. */
2000 if (EQ (frame, Fselected_frame (Qnil)))
2001 Fselect_window (alternative, Qnil);
2003 set_frame_selected_window (f, alternative);
2007 /* w->buffer is nil in a non-leaf window; in this case,
2008 get rid of the markers we maintain that point into that buffer. */
2009 if (!NILP (w->buffer))
2012 unchain_marker (w->pointm[CURRENT_DISP]);
2013 unchain_marker (w->pointm[DESIRED_DISP]);
2014 unchain_marker (w->pointm[CMOTION_DISP]);
2015 unchain_marker (w->start[CURRENT_DISP]);
2016 unchain_marker (w->start[DESIRED_DISP]);
2017 unchain_marker (w->start[CMOTION_DISP]);
2018 unchain_marker (w->sb_point);
2019 /* This breaks set-window-configuration if windows in the saved
2020 configuration get deleted and multiple frames are in use. */
2021 /* w->buffer = Qnil; */
2024 /* close up the hole in the sibling list */
2025 if (!NILP (w->next))
2026 XWINDOW (w->next)->prev = w->prev;
2027 if (!NILP (w->prev))
2028 XWINDOW (w->prev)->next = w->next;
2029 if (EQ (window, par->hchild))
2030 par->hchild = w->next;
2031 if (EQ (window, par->vchild))
2032 par->vchild = w->next;
2034 /* Find one of our siblings to give our space to. */
2036 Lisp_Object sib = w->prev;
2039 /* If w gives its space to its next sibling, that sibling needs
2040 to have its top/left side pulled back to where w's is.
2041 set_window_{height,width} will re-position the sibling's
2044 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
2045 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
2048 /* Stretch that sibling. */
2049 if (!NILP (par->vchild))
2050 set_window_pixheight
2051 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
2052 if (!NILP (par->hchild))
2054 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
2057 /* If parent now has only one child,
2058 put the child into the parent's place. */
2060 Lisp_Object parchild = par->hchild;
2061 if (NILP (parchild))
2062 parchild = par->vchild;
2063 if (NILP (XWINDOW (parchild)->next))
2065 replace_window (parent, parchild);
2066 mark_window_as_deleted (XWINDOW (parent));
2070 /* Since we may be deleting combination windows, we must make sure that
2071 not only W but all its children have been marked as deleted. */
2072 if (!NILP (w->hchild))
2073 delete_all_subwindows (XWINDOW (w->hchild));
2074 else if (!NILP (w->vchild))
2075 delete_all_subwindows (XWINDOW (w->vchild));
2077 mark_window_as_deleted (w);
2079 f->mirror_dirty = 1;
2084 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2085 Return next window after WINDOW in canonical ordering of windows.
2086 If omitted, WINDOW defaults to the selected window.
2088 Optional second arg MINIBUF t means count the minibuffer window even
2089 if not active. MINIBUF nil or omitted means count the minibuffer iff
2090 it is active. MINIBUF neither t nor nil means not to count the
2091 minibuffer even if it is active.
2093 Several frames may share a single minibuffer; if the minibuffer
2094 counts, all windows on all frames that share that minibuffer count
2095 too. Therefore, `next-window' can be used to iterate through the
2096 set of windows even when the minibuffer is on another frame. If the
2097 minibuffer does not count, only windows from WINDOW's frame count.
2099 Optional third arg ALL-FRAMES t means include windows on all frames.
2100 ALL-FRAMES nil or omitted means cycle within the frames as specified
2101 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2102 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2103 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2104 Anything else means restrict to WINDOW's frame.
2106 Optional fourth argument CONSOLE controls which consoles or devices the
2107 returned window may be on. If CONSOLE is a console, return windows only
2108 on that console. If CONSOLE is a device, return windows only on that
2109 device. If CONSOLE is a console type, return windows only on consoles
2110 of that type. If CONSOLE is 'window-system, return any windows on any
2111 window-system consoles. If CONSOLE is nil or omitted, return windows only
2112 on WINDOW's console. Otherwise, all windows are considered.
2114 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2115 can use `next-window' to iterate through the entire cycle of acceptable
2116 windows, eventually ending up back at the window you started with.
2117 `previous-window' traverses the same cycle, in the reverse order.
2119 (window, minibuf, all_frames, console))
2122 Lisp_Object start_window;
2125 window = Fselected_window (Qnil);
2127 CHECK_LIVE_WINDOW (window);
2129 start_window = window;
2131 /* minibuf == nil may or may not include minibuffers.
2132 Decide if it does. */
2134 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2135 else if (! EQ (minibuf, Qt))
2137 /* Now minibuf can be t => count all minibuffer windows,
2138 lambda => count none of them,
2139 or a specific minibuffer window (the active one) to count. */
2141 /* all_frames == nil doesn't specify which frames to include. */
2142 if (NILP (all_frames))
2143 all_frames = (! EQ (minibuf, Qlambda)
2144 ? (FRAME_MINIBUF_WINDOW
2147 (XWINDOW (window)))))
2149 else if (EQ (all_frames, Qvisible))
2151 else if (ZEROP (all_frames))
2153 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2154 /* If all_frames is a frame and window arg isn't on that frame, just
2155 return the first window on the frame. */
2156 return frame_first_window (XFRAME (all_frames));
2157 else if (! EQ (all_frames, Qt))
2159 /* Now all_frames is t meaning search all frames,
2160 nil meaning search just current frame,
2161 visible meaning search just visible frames,
2162 0 meaning search visible and iconified frames,
2163 or a window, meaning search the frame that window belongs to. */
2165 /* Do this loop at least once, to get the next window, and perhaps
2166 again, if we hit the minibuffer and that is not acceptable. */
2169 /* Find a window that actually has a next one. This loop
2170 climbs up the tree. */
2171 while (tem = XWINDOW (window)->next, NILP (tem))
2172 if (tem = XWINDOW (window)->parent, !NILP (tem))
2174 else /* window must be minibuffer window now */
2176 /* We've reached the end of this frame.
2177 Which other frames are acceptable? */
2178 tem = WINDOW_FRAME (XWINDOW (window));
2180 if (! NILP (all_frames))
2185 tem = next_frame (tem, all_frames, console);
2186 /* In the case where the minibuffer is active,
2187 and we include its frame as well as the selected one,
2188 next_frame may get stuck in that frame.
2189 If that happens, go back to the selected frame
2190 so we can complete the cycle. */
2192 XSETFRAME (tem, selected_frame ());
2195 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2201 /* If we're in a combination window, find its first child and
2202 recurse on that. Otherwise, we've found the window we want. */
2205 if (!NILP (XWINDOW (window)->hchild))
2206 window = XWINDOW (window)->hchild;
2207 else if (!NILP (XWINDOW (window)->vchild))
2208 window = XWINDOW (window)->vchild;
2212 /* "acceptable" is the correct spelling. */
2213 /* Which windows are acceptable?
2214 Exit the loop and accept this window if
2215 this isn't a minibuffer window,
2216 or we're accepting all minibuffer windows,
2217 or this is the active minibuffer and we are accepting that one, or
2218 we've come all the way around and we're back at the original window. */
2219 while (MINI_WINDOW_P (XWINDOW (window))
2220 && ! EQ (minibuf, Qt)
2221 && ! EQ (minibuf, window)
2222 && ! EQ (window, start_window));
2227 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2228 Return the window preceding WINDOW in canonical ordering of windows.
2229 If omitted, WINDOW defaults to the selected window.
2231 Optional second arg MINIBUF t means count the minibuffer window even
2232 if not active. MINIBUF nil or omitted means count the minibuffer iff
2233 it is active. MINIBUF neither t nor nil means not to count the
2234 minibuffer even if it is active.
2236 Several frames may share a single minibuffer; if the minibuffer
2237 counts, all windows on all frames that share that minibuffer count
2238 too. Therefore, `previous-window' can be used to iterate through
2239 the set of windows even when the minibuffer is on another frame. If
2240 the minibuffer does not count, only windows from WINDOW's frame count
2242 If optional third arg ALL-FRAMES t means include windows on all frames.
2243 ALL-FRAMES nil or omitted means cycle within the frames as specified
2244 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2245 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2246 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2247 Anything else means restrict to WINDOW's frame.
2249 Optional fourth argument CONSOLE controls which consoles or devices the
2250 returned window may be on. If CONSOLE is a console, return windows only
2251 on that console. If CONSOLE is a device, return windows only on that
2252 device. If CONSOLE is a console type, return windows only on consoles
2253 of that type. If CONSOLE is 'window-system, return any windows on any
2254 window-system consoles. If CONSOLE is nil or omitted, return windows only
2255 on WINDOW's console. Otherwise, all windows are considered.
2257 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2258 can use `previous-window' to iterate through the entire cycle of acceptable
2259 windows, eventually ending up back at the window you started with.
2260 `next-window' traverses the same cycle, in the reverse order.
2262 (window, minibuf, all_frames, console))
2265 Lisp_Object start_window;
2268 window = Fselected_window (Qnil);
2270 CHECK_LIVE_WINDOW (window);
2272 start_window = window;
2274 /* minibuf == nil may or may not include minibuffers.
2275 Decide if it does. */
2277 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2278 else if (! EQ (minibuf, Qt))
2280 /* Now minibuf can be t => count all minibuffer windows,
2281 lambda => count none of them,
2282 or a specific minibuffer window (the active one) to count. */
2284 /* all_frames == nil doesn't specify which frames to include.
2285 Decide which frames it includes. */
2286 if (NILP (all_frames))
2287 all_frames = (! EQ (minibuf, Qlambda)
2288 ? (FRAME_MINIBUF_WINDOW
2291 (XWINDOW (window)))))
2293 else if (EQ (all_frames, Qvisible))
2295 else if (ZEROP (all_frames))
2297 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2298 /* If all_frames is a frame and window arg isn't on that frame, just
2299 return the first window on the frame. */
2300 return frame_first_window (XFRAME (all_frames));
2301 else if (! EQ (all_frames, Qt))
2303 /* Now all_frames is t meaning search all frames,
2304 nil meaning search just current frame,
2305 visible meaning search just visible frames,
2306 0 meaning search visible and iconified frames,
2307 or a window, meaning search the frame that window belongs to. */
2309 /* Do this loop at least once, to get the next window, and perhaps
2310 again, if we hit the minibuffer and that is not acceptable. */
2313 /* Find a window that actually has a next one. This loop
2314 climbs up the tree. */
2315 while (tem = XWINDOW (window)->prev, NILP (tem))
2316 if (tem = XWINDOW (window)->parent, !NILP (tem))
2318 else /* window must be minibuffer window now */
2320 /* We have found the top window on the frame.
2321 Which frames are acceptable? */
2322 tem = WINDOW_FRAME (XWINDOW (window));
2324 if (! NILP (all_frames))
2325 /* It's actually important that we use prev_frame here,
2326 rather than next_frame. All the windows acceptable
2327 according to the given parameters should form a ring;
2328 Fnext_window and Fprevious_window should go back and
2329 forth around the ring. If we use next_frame here,
2330 then Fnext_window and Fprevious_window take different
2331 paths through the set of acceptable windows.
2332 window_loop assumes that these `ring' requirement are
2338 tem = prev_frame (tem, all_frames, console);
2339 /* In the case where the minibuffer is active,
2340 and we include its frame as well as the selected one,
2341 next_frame may get stuck in that frame.
2342 If that happens, go back to the selected frame
2343 so we can complete the cycle. */
2345 XSETFRAME (tem, selected_frame ());
2348 /* If this frame has a minibuffer, find that window first,
2349 because it is conceptually the last window in that frame. */
2350 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2351 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2353 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2360 /* If we're in a combination window, find its first child and
2361 recurse on that. Otherwise, we've found the window we want. */
2364 if (!NILP (XWINDOW (window)->hchild))
2365 window = XWINDOW (window)->hchild;
2366 else if (!NILP (XWINDOW (window)->vchild))
2367 window = XWINDOW (window)->vchild;
2369 while (tem = XWINDOW (window)->next, !NILP (tem))
2373 /* Which windows are acceptable?
2374 Exit the loop and accept this window if
2375 this isn't a minibuffer window,
2376 or we're accepting all minibuffer windows,
2377 or this is the active minibuffer and we are accepting that one, or
2378 we've come all the way around and we're back at the original window. */
2379 while (MINI_WINDOW_P (XWINDOW (window))
2380 && ! EQ (minibuf, Qt)
2381 && ! EQ (minibuf, window)
2382 && ! EQ (window, start_window));
2387 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2388 Return the next window which is vertically after WINDOW.
2393 struct window *w = decode_window (window);
2394 XSETWINDOW (window, w);
2396 if (MINI_WINDOW_P (XWINDOW (window)))
2399 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2401 if (EQ (window, root))
2404 if (!NILP (XWINDOW (window)->hchild))
2405 window = XWINDOW (window)->hchild;
2406 else if (!NILP (XWINDOW (window)->vchild))
2407 window = XWINDOW (window)->vchild;
2414 if (!NILP (XWINDOW (window)->parent) &&
2415 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2417 if (!NILP (XWINDOW (window)->next))
2418 return XWINDOW (window)->next;
2420 window = XWINDOW (window)->parent;
2423 window = XWINDOW (window)->parent;
2425 while (!EQ (window, root));
2428 if (!NILP (XWINDOW (window)->hchild))
2429 window = XWINDOW (window)->hchild;
2430 else if (!NILP (XWINDOW (window)->vchild))
2431 window = XWINDOW (window)->vchild;
2436 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2437 Select the N'th different window on this frame.
2438 All windows on current frame are arranged in a cyclic order.
2439 This command selects the window N steps away in that order.
2440 A negative N moves in the opposite order.
2442 If optional argument FRAME is `visible', search all visible frames.
2443 If FRAME is 0, search all visible and iconified frames.
2444 If FRAME is t, search all frames.
2445 If FRAME is nil, search only the selected frame.
2446 If FRAME is a frame, search only that frame.
2448 Optional third argument CONSOLE controls which consoles or devices the
2449 returned window may be on. If CONSOLE is a console, return windows only
2450 on that console. If CONSOLE is a device, return windows only on that
2451 device. If CONSOLE is a console type, return windows only on consoles
2452 of that type. If CONSOLE is 'window-system, return any windows on any
2453 window-system consoles. If CONSOLE is nil or omitted, return windows only
2454 on FRAME'S console, or on the selected console if FRAME is not a frame.
2455 Otherwise, all windows are considered.
2457 (n, frame, console))
2463 w = Fselected_window (Qnil);
2468 w = Fnext_window (w, Qnil, frame, console);
2473 w = Fprevious_window (w, Qnil, frame, console);
2476 Fselect_window (w, Qnil);
2481 /* Look at all windows, performing an operation specified by TYPE
2484 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2485 frame. If FRAMES is a frame, just look at windows on that frame.
2486 If MINI is non-zero, perform the operation on minibuffer windows too.
2492 GET_BUFFER_WINDOW, /* Arg is buffer */
2493 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2494 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2495 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2497 UNSHOW_BUFFER, /* Arg is buffer */
2498 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2499 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2503 window_loop (enum window_loop type,
2508 Lisp_Object console)
2510 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2512 Lisp_Object best_window = Qnil;
2513 Lisp_Object next_window;
2514 Lisp_Object last_window;
2515 struct frame *frame;
2516 Lisp_Object frame_arg = Qt;
2517 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2518 /* #### I think the change of "precomputing" last_window and next_window
2519 * #### catch the lossage this is meant(?) to punt on...
2522 Lisp_Object devcons, concons;
2524 /* FRAME_ARG is Qlambda to stick to one frame,
2525 Qvisible to consider all visible frames,
2528 /* If we're only looping through windows on a particular frame,
2529 FRAME points to that frame. If we're looping through windows
2530 on all frames, FRAME is 0. */
2532 if (FRAMEP (frames))
2533 frame = XFRAME (frames);
2534 else if (NILP (frames))
2535 frame = selected_frame ();
2539 frame_arg = Qlambda;
2540 else if (ZEROP (frames))
2542 else if (EQ (frames, Qvisible))
2545 DEVICE_LOOP_NO_BREAK (devcons, concons)
2547 Lisp_Object device = XCAR (devcons);
2548 Lisp_Object the_frame;
2551 XSETFRAME (the_frame, frame);
2553 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2555 if (NILP (the_frame))
2558 if (!device_matches_console_spec (the_frame, device, console))
2561 /* Pick a window to start with. */
2565 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2567 /* Figure out the last window we're going to mess with. Since
2568 Fnext_window, given the same options, is guaranteed to go in a
2569 ring, we can just use Fprevious_window to find the last one.
2571 We can't just wait until we hit the first window again,
2572 because it might be deleted. */
2574 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2579 struct window *p = XWINDOW (w);
2580 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2582 /* Pick the next window now, since some operations will delete
2583 the current window. */
2584 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2586 /* #### Still needed ?? */
2587 /* Given the outstanding quality of the rest of this code,
2588 I feel no shame about putting this piece of shit in. */
2589 if (++lose_lose >= 500)
2592 /* Note that we do not pay attention here to whether
2593 the frame is visible, since Fnext_window skips non-visible frames
2594 if that is desired, under the control of frame_arg. */
2595 if (! MINI_WINDOW_P (p)
2596 || (mini && minibuf_level > 0))
2599 case GET_BUFFER_WINDOW:
2601 if (XBUFFER (p->buffer) == XBUFFER (obj))
2606 case GET_BUFFER_WINDOW_COUNT:
2608 if (XBUFFER (p->buffer) == XBUFFER (obj))
2613 case GET_LRU_WINDOW:
2615 /* t as arg means consider only full-width windows */
2617 && !window_full_width_p (p))
2619 /* Ignore dedicated windows and minibuffers. */
2620 if (MINI_WINDOW_P (p)
2621 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2623 if (NILP (best_window)
2624 || (XINT (XWINDOW (best_window)->use_time)
2625 > XINT (p->use_time)))
2630 case GET_BUFFER_MRU_WINDOW:
2632 /* #### what about the first check in GET_LRU_WINDOW? */
2633 /* Ignore dedicated windows and minibuffers. */
2634 if (MINI_WINDOW_P (p)
2635 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2638 if (XBUFFER (p->buffer) == XBUFFER (obj))
2640 if (NILP (best_window)
2641 || (XINT (XWINDOW (best_window)->use_time)
2642 < XINT (p->use_time)))
2648 case DELETE_OTHER_WINDOWS:
2650 /* Don't delete the last window on a frame; this can
2651 happen when the minibuffer is selected, and would
2652 cause the frame to be deleted. */
2653 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2654 Fdelete_window (w, Qnil);
2658 case DELETE_BUFFER_WINDOWS:
2660 if (EQ (p->buffer, obj))
2662 struct frame *f = XFRAME (WINDOW_FRAME (p));
2664 /* If this window is dedicated, and in a frame
2665 of its own, kill the frame. */
2666 if (EQ (w, FRAME_ROOT_WINDOW (f))
2667 && !NILP (p->dedicated)
2668 && other_visible_frames (f))
2670 /* Skip the other windows on this frame.
2671 There might be one, the minibuffer! */
2672 if (! EQ (w, last_window))
2673 while (f == XFRAME (WINDOW_FRAME
2674 (XWINDOW (next_window))))
2676 /* As we go, check for the end of the
2677 loop. We mustn't start going
2678 around a second time. */
2679 if (EQ (next_window, last_window))
2684 next_window = Fnext_window (next_window,
2688 /* Now we can safely delete the frame. */
2689 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2692 /* If we're deleting the buffer displayed in
2693 the only window on the frame, find a new
2694 buffer to display there. */
2695 if (NILP (p->parent))
2697 Lisp_Object new_buffer;
2698 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2699 if (NILP (new_buffer))
2700 new_buffer = Fget_buffer_create (QSscratch);
2701 Fset_window_buffer (w, new_buffer, Qnil);
2702 if (EQ (w, Fselected_window (Qnil)))
2703 Fset_buffer (p->buffer);
2706 Fdelete_window (w, Qnil);
2711 case GET_LARGEST_WINDOW:
2713 /* Ignore dedicated windows and minibuffers. */
2714 if (MINI_WINDOW_P (p)
2715 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2718 /* write the check as follows to avoid tripping
2719 error_check_window() --ben */
2720 struct window *b = NILP (best_window) ? 0 :
2721 XWINDOW (best_window);
2722 if (NILP (best_window)
2723 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2724 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2732 if (EQ (p->buffer, obj))
2734 /* Find another buffer to show in this window. */
2735 Lisp_Object another_buffer =
2736 Fother_buffer (obj, Qnil, Qnil);
2737 if (NILP (another_buffer))
2739 = Fget_buffer_create (QSscratch);
2740 /* If this window is dedicated, and in a frame
2741 of its own, kill the frame. */
2742 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2743 && !NILP (p->dedicated)
2744 && other_visible_frames (w_frame))
2746 /* Skip the other windows on this frame.
2747 There might be one, the minibuffer! */
2748 if (! EQ (w, last_window))
2749 while (w_frame == XFRAME (WINDOW_FRAME
2750 (XWINDOW (next_window))))
2752 /* As we go, check for the end of the
2753 loop. We mustn't start going
2754 around a second time. */
2755 if (EQ (next_window, last_window))
2760 next_window = Fnext_window (next_window,
2764 /* Now we can safely delete the frame. */
2765 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2770 /* Otherwise show a different buffer in the
2772 p->dedicated = Qnil;
2773 Fset_window_buffer (w, another_buffer, Qnil);
2774 if (EQ (w, Fselected_window (Qnil)))
2775 Fset_buffer (p->buffer);
2785 if (EQ (w, last_window))
2792 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2795 #if 0 /* not currently used */
2798 buffer_window_count (struct buffer *b, struct frame *f)
2800 Lisp_Object buffer, frame;
2802 XSETFRAME (frame, f);
2803 XSETBUFFER (buffer, b);
2805 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2810 buffer_window_mru (struct window *w)
2812 Lisp_Object window =
2813 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2817 else if (XWINDOW (window) == w)
2826 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2827 Return the window least recently selected or used for display.
2828 If optional argument FRAME is `visible', search all visible frames.
2829 If FRAME is 0, search all visible and iconified frames.
2830 If FRAME is t, search all frames.
2831 If FRAME is nil, search only the selected frame.
2832 If FRAME is a frame, search only that frame.
2834 Optional second argument CONSOLE controls which consoles or devices the
2835 returned window may be on. If CONSOLE is a console, return windows only
2836 on that console. If CONSOLE is a device, return windows only on that
2837 device. If CONSOLE is a console type, return windows only on consoles
2838 of that type. If CONSOLE is 'window-system, return any windows on any
2839 window-system consoles. If CONSOLE is nil or omitted, return windows only
2840 on FRAME'S console, or on the selected console if FRAME is not a frame.
2841 Otherwise, all windows are considered.
2846 /* First try for a non-dedicated window that is full-width */
2847 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2848 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2851 /* Then try for any non-dedicated window */
2852 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2853 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2857 /* FSFmacs never returns a dedicated window here. If we do,
2858 it makes `display-buffer' not work right. #### All of this
2859 shit is so disgusting and awful that it needs to be rethought
2861 /* then try for a dedicated window that is full-width */
2862 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2863 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2866 /* If none of them, then all windows, dedicated or not. */
2867 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2869 /* At this point we damn well better have found something. */
2870 if (NILP (w)) abort ();
2876 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2877 Return the window largest in area.
2878 If optional argument FRAME is `visible', search all visible frames.
2879 If FRAME is 0, search all visible and iconified frames.
2880 If FRAME is t, search all frames.
2881 If FRAME is nil, search only the selected frame.
2882 If FRAME is a frame, search only that frame.
2884 Optional second argument CONSOLE controls which consoles or devices the
2885 returned window may be on. If CONSOLE is a console, return windows only
2886 on that console. If CONSOLE is a device, return windows only on that
2887 device. If CONSOLE is a console type, return windows only on consoles
2888 of that type. If CONSOLE is 'window-system, return any windows on any
2889 window-system consoles. If CONSOLE is nil or omitted, return windows only
2890 on FRAME'S console, or on the selected console if FRAME is not a frame.
2891 Otherwise, all windows are considered.
2895 /* Don't search dedicated windows because FSFmacs doesn't.
2896 This stuff is all black magic so don't try to apply common
2898 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2901 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2902 Return a window currently displaying BUFFER, or nil if none.
2903 If optional argument FRAME is `visible', search all visible frames.
2904 If optional argument FRAME is 0, search all visible and iconified frames.
2905 If FRAME is t, search all frames.
2906 If FRAME is nil, search only the selected frame.
2907 If FRAME is a frame, search only that frame.
2909 Optional third argument CONSOLE controls which consoles or devices the
2910 returned window may be on. If CONSOLE is a console, return windows only
2911 on that console. If CONSOLE is a device, return windows only on that
2912 device. If CONSOLE is a console type, return windows only on consoles
2913 of that type. If CONSOLE is 'window-system, return any windows on any
2914 window-system consoles. If CONSOLE is nil or omitted, return windows only
2915 on FRAME'S console, or on the selected console if FRAME is not a frame.
2916 Otherwise, all windows are considered.
2918 (buffer, frame, console))
2920 buffer = Fget_buffer (buffer);
2921 if (BUFFERP (buffer))
2922 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2923 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2928 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2929 but there is no sensible way to implement those functions, since
2930 you can't in general derive a window from a buffer. */
2932 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2934 Return the width in pixels of the left outside margin of window WINDOW.
2935 If WINDOW is nil, the selected window is assumed.
2939 return make_int (window_left_margin_width (decode_window (window)));
2942 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2944 Return the width in pixels of the right outside margin of window WINDOW.
2945 If WINDOW is nil, the selected window is assumed.
2949 return make_int (window_right_margin_width (decode_window (window)));
2952 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2953 Make WINDOW (or the selected window) fill its frame.
2954 Only the frame WINDOW is on is affected.
2955 This function tries to reduce display jumps
2956 by keeping the text previously visible in WINDOW
2957 in the same place on the frame. Doing this depends on
2958 the value of (window-start WINDOW), so if calling this function
2959 in a program gives strange scrolling, make sure the window-start
2960 value is reasonable when this function is called.
2964 struct window *w = decode_window (window);
2965 struct buffer *b = XBUFFER (w->buffer);
2967 int old_top = WINDOW_TOP (w);
2969 XSETWINDOW (window, w);
2971 if (MINI_WINDOW_P (w) && old_top > 0)
2972 error ("Can't expand minibuffer to full frame");
2974 /* Ignore dedicated windows. */
2975 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2977 start_pos = marker_position (w->start[CURRENT_DISP]);
2979 /* Try to minimize scrolling, by setting the window start to the
2980 point which will cause the text at the old window start to be at
2981 the same place on the frame. But don't try to do this if the
2982 window start is outside the visible portion (as might happen when
2983 the display is not current, due to typeahead). */
2984 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2985 && !MINI_WINDOW_P (w))
2987 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2989 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2991 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2993 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2995 /* We need to do this, so that the window-scroll-functions
3003 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3004 "bDelete windows on (buffer): ", /*
3005 Delete all windows showing BUFFER.
3006 Optional second argument FRAME controls which frames are affected.
3007 If nil or omitted, delete all windows showing BUFFER in any frame.
3008 If t, delete only windows showing BUFFER in the selected frame.
3009 If `visible', delete all windows showing BUFFER in any visible frame.
3010 If a frame, delete only windows showing BUFFER in that frame.
3012 Optional third argument CONSOLE controls which consoles or devices the
3013 returned window may be on. If CONSOLE is a console, return windows only
3014 on that console. If CONSOLE is a device, return windows only on that
3015 device. If CONSOLE is a console type, return windows only on consoles
3016 of that type. If CONSOLE is 'window-system, return any windows on any
3017 window-system consoles. If CONSOLE is nil or omitted, return windows only
3018 on FRAME'S console, or on the selected console if FRAME is not a frame.
3019 Otherwise, all windows are considered.
3021 (buffer, frame, console))
3023 /* This function can GC */
3024 /* FRAME uses t and nil to mean the opposite of what window_loop
3026 if (!FRAMEP (frame))
3027 frame = NILP (frame) ? Qt : Qnil;
3031 buffer = Fget_buffer (buffer);
3032 CHECK_BUFFER (buffer);
3033 /* Ignore dedicated windows. */
3034 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
3039 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
3040 "bReplace buffer in windows: ", /*
3041 Replace BUFFER with some other buffer in all windows showing it.
3045 /* This function can GC */
3048 buffer = Fget_buffer (buffer);
3049 CHECK_BUFFER (buffer);
3050 /* Ignore dedicated windows. */
3051 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
3056 /* The smallest acceptable dimensions for a window. Anything smaller
3057 might crash Emacs. */
3058 #define MIN_SAFE_WINDOW_WIDTH (2)
3059 #define MIN_SAFE_WINDOW_HEIGHT (2)
3061 /* Make sure that window_min_height and window_min_width are
3062 not too small; if they are, set them to safe minima. */
3065 check_min_window_sizes (void)
3067 /* Smaller values might permit a crash. */
3068 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3069 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3070 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3071 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3075 frame_min_height (struct frame *frame)
3077 /* For height, we have to see whether the frame has a minibuffer, and
3078 whether it wants a modeline. */
3079 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3080 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3081 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3084 /* Return non-zero if both frame sizes are less than or equal to
3085 minimal allowed values. ROWS and COLS are in characters */
3087 frame_size_valid_p (struct frame *frame, int rows, int cols)
3089 return (rows >= frame_min_height (frame)
3090 && cols >= MIN_SAFE_WINDOW_WIDTH);
3093 /* Return non-zero if both frame sizes are less than or equal to
3094 minimal allowed values. WIDTH and HEIGHT are in pixels */
3096 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3099 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3100 return frame_size_valid_p (frame, rows, cols);
3103 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3104 minimum allowable size. */
3106 check_frame_size (struct frame *frame, int *rows, int *cols)
3108 int min_height = frame_min_height (frame);
3110 if (*rows < min_height)
3112 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3113 *cols = MIN_SAFE_WINDOW_WIDTH;
3116 /* Normally the window is deleted if it gets too small.
3117 nodelete nonzero means do not do this.
3118 (The caller should check later and do so if appropriate) */
3120 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3123 struct window *w = XWINDOW (window);
3124 struct frame *f = XFRAME (w->frame);
3126 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3127 Lisp_Object child, minor_kid, major_kid;
3130 int defheight, defwidth;
3132 /* #### This is very likely incorrect and instead the char_to_pixel_
3133 functions should be called. */
3134 default_face_height_and_width (window, &defheight, &defwidth);
3135 line_size = (set_height ? defheight : defwidth);
3137 check_min_window_sizes ();
3139 minsize = (set_height ? window_min_height : window_min_width);
3140 minsize *= line_size;
3143 && !TOP_LEVEL_WINDOW_P (w)
3144 && new_pixsize < minsize)
3146 Fdelete_window (window, Qnil);
3150 SET_LAST_MODIFIED (w, 0);
3151 SET_LAST_FACECHANGE (w);
3152 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3155 WINDOW_HEIGHT (w) = new_pixsize;
3156 major_kid = w->vchild;
3157 minor_kid = w->hchild;
3161 WINDOW_WIDTH (w) = new_pixsize;
3162 major_kid = w->hchild;
3163 minor_kid = w->vchild;
3166 if (!NILP (minor_kid))
3168 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3171 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3173 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3175 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3178 else if (!NILP (major_kid))
3180 int last_pos, last_old_pos, pos, old_pos, first;
3181 int pixel_adj_left = new_pixsize - old_pixsize;
3182 int div_val = old_pixsize << 1;
3185 * Previously we bailed out here if there was no size change.
3186 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3187 * toolbar appears or disappears, windows may not change size,
3188 * but their top and left coordinates need to be updated.
3190 * So we don't bail until after the loop below.
3193 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3196 for (child = major_kid; !NILP (child); child = c->next)
3198 c = XWINDOW (child);
3202 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3203 WINDOW_TOP (c) = last_pos;
3207 old_pos = last_old_pos + WINDOW_WIDTH (c);
3208 WINDOW_LEFT (c) = last_pos;
3211 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3212 /* All but the last window should have a height which is
3213 a multiple of the default line height. */
3214 if (!NILP (c->next))
3215 pos = (pos / line_size) * line_size;
3217 /* Avoid confusion: don't delete child if it becomes too small */
3218 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3220 last_pos = pos + first;
3221 last_old_pos = old_pos;
3224 /* Sometimes we may get called with our old size. In that case
3225 we don't need to do anything else. */
3226 if (!pixel_adj_left)
3229 /* Now delete any children that became too small. */
3231 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3234 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3236 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3241 /* Set the height of WINDOW and all its inferiors. */
3243 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3245 set_window_pixsize (window, new_pixheight, nodelete, 1);
3248 /* Recursively set width of WINDOW and its inferiors. */
3250 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3252 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3256 static int window_select_count;
3258 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3259 Make WINDOW display BUFFER as its contents.
3260 BUFFER can be a buffer or buffer name.
3262 With non-nil optional argument `norecord', do not modify the
3263 global or per-frame buffer ordering.
3265 (window, buffer, norecord))
3268 struct window *w = decode_window (window);
3270 buffer = Fget_buffer (buffer);
3271 CHECK_BUFFER (buffer);
3273 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3274 error ("Attempt to display deleted buffer");
3278 error ("Window is deleted");
3280 /* While this seems like a logical thing to do, it causes problems
3281 because of saved window configurations. It is possible for a
3282 buffer to get restored into a window in which it is already being
3283 displayed, but start and point are actually at completely
3284 different locations. So we let this function complete fully and
3285 it will then make sure redisplay correctly updates things.
3287 #### This is a kludge. The correct approach is not to do this
3288 but to fix set-window-configuration. */
3290 else if (EQ (tem, buffer))
3293 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3294 is first being set up. */
3296 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3297 error ("Window is dedicated to buffer %s",
3298 XSTRING_DATA (XBUFFER (tem)->name));
3304 w->window_end_pos[CURRENT_DISP] = 0;
3306 w->modeline_hscroll = 0;
3307 Fset_marker (w->pointm[CURRENT_DISP],
3308 make_int (BUF_PT (XBUFFER (buffer))),
3310 set_marker_restricted (w->start[CURRENT_DISP],
3311 make_int (XBUFFER (buffer)->last_window_start),
3313 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3314 /* set start_at_line_beg correctly. GE */
3315 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3316 marker_position (w->start[CURRENT_DISP]));
3317 w->force_start = 0; /* Lucid fix */
3318 SET_LAST_MODIFIED (w, 1);
3319 SET_LAST_FACECHANGE (w);
3320 MARK_WINDOWS_CHANGED (w);
3321 recompute_all_cached_specifiers_in_window (w);
3322 if (EQ (window, Fselected_window (Qnil)))
3324 if (NILP (norecord))
3325 Frecord_buffer (buffer);
3327 Fset_buffer (buffer);
3332 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3333 Select WINDOW. Most editing will apply to WINDOW's buffer.
3334 The main editor command loop selects the buffer of the selected window
3335 before each command.
3337 With non-nil optional argument `norecord', do not modify the
3338 global or per-frame buffer ordering.
3343 Lisp_Object old_selected_window = Fselected_window (Qnil);
3345 CHECK_LIVE_WINDOW (window);
3346 w = XWINDOW (window);
3348 /* we have already caught dead-window errors */
3349 if (!NILP (w->hchild) || !NILP (w->vchild))
3350 error ("Trying to select non-leaf window");
3352 w->use_time = make_int (++window_select_count);
3354 if (EQ (window, old_selected_window))
3357 /* deselect the old window, if it exists (it might not exist if
3358 the selected device has no frames, which occurs at startup) */
3359 if (!NILP (old_selected_window))
3361 struct window *ow = XWINDOW (old_selected_window);
3363 Fset_marker (ow->pointm[CURRENT_DISP],
3364 make_int (BUF_PT (XBUFFER (ow->buffer))),
3367 MARK_WINDOWS_CHANGED (ow);
3370 /* now select the window's frame */
3371 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3373 select_frame_1 (WINDOW_FRAME (w));
3375 /* also select the window's buffer */
3376 if (NILP (norecord))
3377 Frecord_buffer (w->buffer);
3378 Fset_buffer (w->buffer);
3380 /* Go to the point recorded in the window.
3381 This is important when the buffer is in more
3382 than one window. It also matters when
3383 redisplay_window has altered point after scrolling,
3384 because it makes the change only in the window. */
3386 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3387 if (new_point < BUF_BEGV (current_buffer))
3388 new_point = BUF_BEGV (current_buffer);
3389 else if (new_point > BUF_ZV (current_buffer))
3390 new_point = BUF_ZV (current_buffer);
3392 BUF_SET_PT (current_buffer, new_point);
3395 MARK_WINDOWS_CHANGED (w);
3401 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3402 Lisp_Object override_frame)
3404 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3408 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3410 /* This function can GC */
3413 struct buffer *b = XBUFFER (buf);
3415 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3416 widen_buffer (b, 0);
3417 BUF_SET_PT (b, BUF_BEG (b));
3419 if (!NILP (Vtemp_buffer_show_function))
3420 call1 (Vtemp_buffer_show_function, buf);
3423 window = display_buffer (buf, Qnil, same_frame);
3425 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3426 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3428 Vminibuffer_scroll_window = window;
3429 w = XWINDOW (window);
3431 w->modeline_hscroll = 0;
3432 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3433 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3434 set_marker_restricted (w->sb_point, make_int (1), buf);
3436 /* Run temp-buffer-show-hook, with the chosen window selected. */
3437 if (!preparing_for_armageddon)
3440 tem = Fboundp (Qtemp_buffer_show_hook);
3443 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3446 int count = specpdl_depth ();
3448 /* Select the window that was chosen, for running
3450 record_unwind_protect (save_window_excursion_unwind,
3451 Fcurrent_window_configuration (Qnil));
3453 Fselect_window (window, Qnil);
3454 run_hook (Qtemp_buffer_show_hook);
3455 unbind_to (count, Qnil);
3463 make_dummy_parent (Lisp_Object window)
3466 struct window *o = XWINDOW (window);
3467 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3469 XSETWINDOW (new, p);
3470 copy_lcrecord (p, o);
3472 /* Don't copy the pointers to the line start cache or the face
3474 p->line_start_cache = Dynarr_new (line_start_cache);
3475 p->face_cachels = Dynarr_new (face_cachel);
3476 p->glyph_cachels = Dynarr_new (glyph_cachel);
3477 p->subwindow_instance_cache =
3478 make_lisp_hash_table (10,
3479 HASH_TABLE_KEY_WEAK,
3482 /* Put new into window structure in place of window */
3483 replace_window (window, new);
3491 p->start[CURRENT_DISP] = Qnil;
3492 p->start[DESIRED_DISP] = Qnil;
3493 p->start[CMOTION_DISP] = Qnil;
3494 p->pointm[CURRENT_DISP] = Qnil;
3495 p->pointm[DESIRED_DISP] = Qnil;
3496 p->pointm[CMOTION_DISP] = Qnil;
3501 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3502 Split WINDOW, putting SIZE lines in the first of the pair.
3503 WINDOW defaults to selected one and SIZE to half its size.
3504 If optional third arg HOR-FLAG is non-nil, split side by side
3505 and put SIZE columns in the first of the pair.
3507 (window, chsize, horflag))
3510 struct window *o, *p;
3516 window = Fselected_window (Qnil);
3518 CHECK_LIVE_WINDOW (window);
3520 o = XWINDOW (window);
3521 f = XFRAME (WINDOW_FRAME (o));
3525 if (!NILP (horflag))
3526 /* In the new scheme, we are symmetric with respect to separators
3527 so there is no need to do weird things here. */
3529 psize = WINDOW_WIDTH (o) >> 1;
3530 size = window_pixel_width_to_char_width (o, psize, 0);
3534 psize = WINDOW_HEIGHT (o) >> 1;
3535 size = window_pixel_height_to_char_height (o, psize, 1);
3541 size = XINT (chsize);
3542 if (!NILP (horflag))
3543 psize = window_char_width_to_pixel_width (o, size, 0);
3545 psize = window_char_height_to_pixel_height (o, size, 1);
3548 if (MINI_WINDOW_P (o))
3549 error ("Attempt to split minibuffer window");
3550 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3551 error ("Attempt to split unsplittable frame");
3553 check_min_window_sizes ();
3557 if (size < window_min_height)
3558 error ("Window height %d too small (after splitting)", size);
3559 if (size + window_min_height > window_char_height (o, 1))
3560 error ("Window height %d too small (after splitting)",
3561 window_char_height (o, 1) - size);
3562 if (NILP (o->parent)
3563 || NILP (XWINDOW (o->parent)->vchild))
3565 make_dummy_parent (window);
3566 reset_face_cachels (XWINDOW (window));
3568 XWINDOW (new)->vchild = window;
3569 XFRAME (o->frame)->mirror_dirty = 1;
3574 if (size < window_min_width)
3575 error ("Window width %d too small (after splitting)", size);
3576 if (size + window_min_width > window_char_width (o, 0))
3577 error ("Window width %d too small (after splitting)",
3578 window_char_width (o, 0) - size);
3579 if (NILP (o->parent)
3580 || NILP (XWINDOW (o->parent)->hchild))
3582 make_dummy_parent (window);
3583 reset_face_cachels (XWINDOW (window));
3585 XWINDOW (new)->hchild = window;
3586 XFRAME (o->frame)->mirror_dirty = 1;
3590 /* Now we know that window's parent is a vertical combination
3591 if we are dividing vertically, or a horizontal combination
3592 if we are making side-by-side windows */
3594 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3595 new = allocate_window ();
3598 p->frame = o->frame;
3600 if (!NILP (p->next))
3601 XWINDOW (p->next)->prev = new;
3604 p->parent = o->parent;
3607 reset_face_cachels (p);
3608 reset_glyph_cachels (p);
3611 /* Apportion the available frame space among the two new windows */
3613 if (!NILP (horflag))
3615 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3616 WINDOW_TOP (p) = WINDOW_TOP (o);
3617 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3618 WINDOW_WIDTH (o) = psize;
3619 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3623 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3624 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3625 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3626 WINDOW_HEIGHT (o) = psize;
3627 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3630 XFRAME (p->frame)->mirror_dirty = 1;
3631 /* do this last (after the window is completely initialized and
3632 the mirror-dirty flag is set) so that specifier recomputation
3633 caused as a result of this will work properly and not abort. */
3634 Fset_window_buffer (new, o->buffer, Qt);
3639 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3640 Make the selected window N lines bigger.
3641 From program, optional second arg SIDE non-nil means grow sideways N columns,
3642 and optional third arg WINDOW specifies the window to change instead of the
3647 struct window *w = decode_window (window);
3649 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3653 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3654 Make the selected window N pixels bigger.
3655 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3656 and optional third arg WINDOW specifies the window to change instead of the
3661 struct window *w = decode_window (window);
3663 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3667 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3668 Make the selected window N lines smaller.
3669 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3670 and optional third arg WINDOW specifies the window to change instead of the
3676 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3681 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3682 Make the selected window N pixels smaller.
3683 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3684 and optional third arg WINDOW specifies the window to change instead of the
3690 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3696 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3697 int include_gutters_p)
3700 int defheight, defwidth;
3704 XSETWINDOW (window, w);
3706 avail_height = (pixel_height -
3707 (include_gutters_p ? 0 :
3708 window_top_window_gutter_height (w) +
3709 window_bottom_window_gutter_height (w)));
3711 default_face_height_and_width (window, &defheight, &defwidth);
3713 char_height = avail_height / defheight;
3715 /* It's the calling function's responsibility to check these values
3716 and make sure they're not out of range.
3718 #### We need to go through the calling functions and actually
3720 return max (0, char_height);
3724 window_char_height_to_pixel_height (struct window *w, int char_height,
3725 int include_gutters_p)
3728 int defheight, defwidth;
3733 XSETWINDOW (window, w);
3735 default_face_height_and_width (window, &defheight, &defwidth);
3737 avail_height = char_height * defheight;
3738 pixel_height = (avail_height +
3739 (include_gutters_p ? 0 :
3740 window_top_window_gutter_height (w) +
3741 window_bottom_window_gutter_height (w)));
3743 /* It's the calling function's responsibility to check these values
3744 and make sure they're not out of range.
3746 #### We need to go through the calling functions and actually
3748 return max (0, pixel_height);
3751 /* Return number of default lines of text can fit in the window W.
3752 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3753 horizontal scrollbar) in the space that is used for the calculation.
3754 This doesn't include space used by the frame gutters.
3757 window_char_height (struct window *w, int include_gutters_p)
3759 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3764 * Return number of lines currently displayed in window w. If
3765 * end-of-buffer is displayed then the area below end-of-buffer is assume
3766 * to be blank lines of default height.
3767 * Does not include the modeline.
3770 window_displayed_height (struct window *w)
3772 struct buffer *b = XBUFFER (w->buffer);
3773 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3775 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3777 : w->window_end_pos[CURRENT_DISP]);
3779 if (!Dynarr_length (dla))
3780 return window_char_height (w, 0);
3782 num_lines = Dynarr_length (dla);
3784 /* #### Document and assert somewhere that w->window_end_pos == -1
3785 indicates that end-of-buffer is being displayed. */
3788 struct display_line *dl = Dynarr_atp (dla, 0);
3789 int ypos1 = dl->ypos + dl->descent;
3790 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3792 int defheight, defwidth;
3794 XSETWINDOW (window, w);
3800 if (Dynarr_length (dla) == 1)
3801 ypos1 = WINDOW_TEXT_TOP (w);
3804 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3805 /* If this line is clipped then we know that there is no
3806 blank room between eob and the modeline. If we are
3807 scrolling on clipped lines just know off the clipped
3809 if (scroll_on_clipped_lines && dl->clip)
3810 return num_lines - 1;
3811 ypos1 = dl->ypos + dl->descent - dl->clip;
3815 default_face_height_and_width (window, &defheight, &defwidth);
3816 /* #### This probably needs to know about the clipping area once a
3817 final definition is decided on. */
3818 num_lines += ((ypos2 - ypos1) / defheight);
3822 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3825 if (scroll_on_clipped_lines
3826 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3834 window_pixel_width (Lisp_Object window)
3836 return WINDOW_WIDTH (XWINDOW (window));
3839 /* Calculate the pixel of a window, optionally including margin space
3840 but no vertical gutters. */
3842 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3843 int include_margins_p)
3847 int defheight, defwidth;
3850 XSETWINDOW (window, w);
3852 avail_width = (pixel_width -
3853 window_left_gutter_width (w, 0) -
3854 window_right_gutter_width (w, 0) -
3855 (include_margins_p ? 0 : window_left_margin_width (w)) -
3856 (include_margins_p ? 0 : window_right_margin_width (w)));
3858 default_face_height_and_width (window, &defheight, &defwidth);
3860 char_width = (avail_width / defwidth);
3862 /* It's the calling function's responsibility to check these values
3863 and make sure they're not out of range.
3865 #### We need to go through the calling functions and actually
3867 return max (0, char_width);
3871 window_char_width_to_pixel_width (struct window *w, int char_width,
3872 int include_margins_p)
3876 int defheight, defwidth;
3879 XSETWINDOW (window, w);
3881 default_face_height_and_width (window, &defheight, &defwidth);
3883 avail_width = char_width * defwidth;
3884 pixel_width = (avail_width +
3885 window_left_window_gutter_width (w, 0) +
3886 window_right_window_gutter_width (w, 0) +
3887 (include_margins_p ? 0 : window_left_margin_width (w)) +
3888 (include_margins_p ? 0 : window_right_margin_width (w)));
3890 /* It's the calling function's responsibility to check these values
3891 and make sure they're not out of range.
3893 #### We need to go through the calling functions and actually
3895 return max (0, pixel_width);
3898 /* This returns the usable space which doesn't include space needed by
3899 scrollbars or divider lines. */
3901 window_char_width (struct window *w, int include_margins_p)
3903 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3907 #define MINSIZE(w) \
3909 ? window_min_width * defwidth \
3910 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3913 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3915 #define CURSIZE(w) \
3916 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3918 #define CURCHARSIZE(w) \
3919 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3921 #define MINCHARSIZE(window) \
3922 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3923 ? 1 : window_min_height)
3926 window_pixheight (Lisp_Object w)
3928 return window_pixel_height (XWINDOW (w));
3931 /* Unlike set_window_pixheight, this function
3932 also changes the heights of the siblings so as to
3933 keep everything consistent. */
3936 change_window_height (struct window *win, int delta, int widthflag,
3944 int (*sizefun) (Lisp_Object) = (widthflag
3945 ? window_pixel_width
3946 : window_pixheight);
3947 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3948 ? set_window_pixwidth
3949 : set_window_pixheight);
3951 int defheight, defwidth;
3956 check_min_window_sizes ();
3958 XSETWINDOW (window, win);
3959 f = XFRAME (win->frame);
3960 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3961 error ("Won't change only window");
3963 /* #### This is very likely incorrect and instead the char_to_pixel_
3964 functions should be called. */
3965 default_face_height_and_width (window, &defheight, &defwidth);
3969 w = XWINDOW (window);
3974 error ("No other window to side of this one");
3978 ? !NILP (XWINDOW (parent)->hchild)
3979 : !NILP (XWINDOW (parent)->vchild))
3984 sizep = &CURSIZE (w);
3985 dim = CURCHARSIZE (w);
3987 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3988 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3990 if (MINI_WINDOW_P (XWINDOW (window)))
3992 else if (!NILP (parent))
3994 Fdelete_window (window, Qnil);
4000 delta *= (widthflag ? defwidth : defheight);
4005 maxdelta = ((!NILP (parent))
4006 ? (*sizefun) (parent) - *sizep
4007 : ((!NILP (w->next))
4008 ? (*sizefun) (w->next) - MINSIZE (w->next)
4009 : ((!NILP (w->prev))
4010 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4011 /* This is a frame with only one window,
4012 a minibuffer-only or a minibufferless frame. */
4015 if (delta > maxdelta)
4016 /* This case traps trying to make the minibuffer
4017 the full frame, or make the only window aside from the
4018 minibuffer the full frame. */
4025 /* #### Chuck: is this correct? */
4026 if (*sizep + delta < MINSIZE (window))
4028 Fdelete_window (window);
4034 if (!NILP (w->next) &&
4035 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4037 CURBEG (XWINDOW (w->next)) += delta;
4038 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4039 (*setsizefun) (window, *sizep + delta, 0);
4041 else if (!NILP (w->prev) &&
4042 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4044 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4045 CURBEG (w) -= delta;
4046 (*setsizefun) (window, *sizep + delta, 0);
4051 int opht = (*sizefun) (parent);
4053 /* If trying to grow this window to or beyond size of the parent,
4054 make delta1 so big that, on shrinking back down,
4055 all the siblings end up with less than one line and are deleted. */
4056 if (opht <= *sizep + delta)
4057 delta1 = opht * opht * 2;
4058 /* Otherwise, make delta1 just right so that if we add delta1
4059 lines to this window and to the parent, and then shrink
4060 the parent back to its original size, the new proportional
4061 size of this window will increase by delta. */
4063 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4065 /* Add delta1 lines or columns to this window, and to the parent,
4066 keeping things consistent while not affecting siblings. */
4067 CURSIZE (XWINDOW (parent)) = opht + delta1;
4068 (*setsizefun) (window, *sizep + delta1, 0);
4070 /* Squeeze out delta1 lines or columns from our parent,
4071 shrinking this window and siblings proportionately.
4072 This brings parent back to correct size.
4073 Delta1 was calculated so this makes this window the desired size,
4074 taking it all out of the siblings. */
4075 (*setsizefun) (parent, opht, 0);
4078 SET_LAST_MODIFIED (w, 0);
4079 SET_LAST_FACECHANGE (w);
4080 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4081 /* overkill maybe, but better to be correct */
4082 MARK_FRAME_GUTTERS_CHANGED (f);
4092 /* Scroll contents of window WINDOW up N lines. If N < (top line height /
4093 average line height) then we just adjust the top clip. */
4095 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
4096 Error_behavior errb)
4098 struct window *w = XWINDOW (window);
4099 struct buffer *b = XBUFFER (w->buffer);
4100 int selected = EQ (window, Fselected_window (Qnil));
4102 Lisp_Object point, tem;
4103 display_line_dynarr *dla;
4104 int fheight, fwidth, modeline = 0;
4105 struct display_line* dl;
4108 point = make_int (BUF_PT (b));
4111 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4113 if (pos < BUF_BEGV (b))
4115 else if (pos > BUF_ZV (b))
4118 point = make_int (pos);
4121 /* Always set force_start so that redisplay_window will run
4122 the window-scroll-functions. */
4125 /* #### When the fuck does this happen? I'm so glad that history has
4126 completely documented the behavior of the scrolling functions under
4127 all circumstances. */
4128 tem = Fpos_visible_in_window_p (point, window);
4131 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4133 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4134 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4135 WINDOW_TEXT_TOP_CLIP (w) = 0;
4136 MARK_WINDOWS_CHANGED (w);
4145 n = Fprefix_numeric_value (n);
4146 value = XINT (n) * direction;
4149 return; /* someone just made a pointless call */
4153 /* If the user didn't specify how far to scroll then we have to figure it
4154 out by ourselves. */
4155 if (NILP (n) || EQ (n, Qminus))
4157 /* Going forwards is easy. If that is what we are doing then just
4158 set value and the section which handles the user specifying a
4159 positive value will work. */
4162 value = window_displayed_height (w) - next_screen_context_lines;
4163 value = (value < 1 ? 1 : value);
4166 /* Going backwards is hard. We can't use the same loop used if the
4167 user specified a negative value because we care about
4168 next_screen_context_lines. In a variable height world you don't
4169 know how many lines above you can actually be displayed and still
4170 have the context lines appear. So we leave value set to 0 and add
4171 a separate section to deal with this. */
4175 if (direction == 1 && !value)
4180 /* Determine parameters to test for partial line scrolling with. */
4181 dla = window_display_lines (w, CURRENT_DISP);
4183 if (INTP (Vwindow_pixel_scroll_increment))
4184 fheight = XINT (Vwindow_pixel_scroll_increment);
4185 else if (!NILP (Vwindow_pixel_scroll_increment))
4186 default_face_height_and_width (window, &fheight, &fwidth);
4188 if (Dynarr_length (dla) >= 1)
4189 modeline = Dynarr_atp (dla, 0)->modeline;
4191 dl = Dynarr_atp (dla, modeline);
4195 /* Go for partial display line scrolling. This just means bumping
4196 the clip by a reasonable amount and redisplaying, everything else
4197 remains unchanged. */
4198 if (!NILP (Vwindow_pixel_scroll_increment)
4200 Dynarr_length (dla) >= (1 + modeline)
4202 (dl->ascent - dl->top_clip) - fheight * value > 0)
4204 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4205 MARK_WINDOWS_CHANGED (w);
4210 Bufpos startp, old_start;
4212 if (WINDOW_TEXT_TOP_CLIP (w))
4214 WINDOW_TEXT_TOP_CLIP (w) = 0;
4215 MARK_WINDOWS_CHANGED (w);
4218 old_start = marker_position (w->start[CURRENT_DISP]);
4219 startp = vmotion (w, old_start, value, &vtarget);
4221 if (vtarget < value &&
4222 (w->window_end_pos[CURRENT_DISP] == -1
4223 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4225 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4230 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4233 w->start_at_line_beg = beginning_of_line_p (b, startp);
4234 MARK_WINDOWS_CHANGED (w);
4236 if (!point_would_be_visible (w, startp, XINT (point)))
4239 BUF_SET_PT (b, startp);
4241 set_marker_restricted (w->pointm[CURRENT_DISP],
4250 /* Go for partial display line scrolling. This just means bumping
4251 the clip by a reasonable amount and redisplaying, everything else
4252 remains unchanged. */
4253 if (!NILP (Vwindow_pixel_scroll_increment)
4255 Dynarr_length (dla) >= (1 + modeline)
4257 (dl->ascent - dl->top_clip) - fheight * value <
4258 (dl->ascent + dl->descent - dl->clip)
4260 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4262 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4263 MARK_WINDOWS_CHANGED (w);
4268 Bufpos startp, old_start;
4270 if (WINDOW_TEXT_TOP_CLIP (w))
4272 WINDOW_TEXT_TOP_CLIP (w) = 0;
4273 MARK_WINDOWS_CHANGED (w);
4276 old_start = marker_position (w->start[CURRENT_DISP]);
4277 startp = vmotion (w, old_start, value, &vtarget);
4280 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4282 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4287 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4290 w->start_at_line_beg = beginning_of_line_p (b, startp);
4291 MARK_WINDOWS_CHANGED (w);
4293 /* #### Scroll back by less than a line. This code was
4294 originally for scrolling over large pixmaps and it
4295 loses when a line being *exposed* at the top of the
4296 window is bigger than the current one. However, for
4297 pixel based scrolling in general we can guess that
4298 the line we are going to display is probably the same
4299 size as the one we are on. In that instance we can
4300 have a reasonable stab at a suitable top clip. Fixing
4301 this properly is hard (and probably slow) as we would
4302 have to call redisplay to figure out the exposed line
4304 if (!NILP (Vwindow_pixel_scroll_increment)
4305 && Dynarr_length (dla) >= (1 + modeline)
4306 && dl->ascent + fheight * value > 0)
4308 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4311 if (!point_would_be_visible (w, startp, XINT (point)))
4315 if (MINI_WINDOW_P (w))
4318 new_point = start_of_last_line (w, startp);
4321 BUF_SET_PT (b, new_point);
4323 set_marker_restricted (w->pointm[CURRENT_DISP],
4324 make_int (new_point),
4330 else /* value == 0 && direction == -1 */
4332 if (WINDOW_TEXT_TOP_CLIP (w))
4334 WINDOW_TEXT_TOP_CLIP (w) = 0;
4335 MARK_WINDOWS_CHANGED (w);
4337 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4339 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4345 int movement = next_screen_context_lines - 1;
4346 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4347 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4349 start_with_point_on_display_line (w, bottom,
4350 -1 - (movement - vtarget));
4352 if (startp >= old_startp)
4353 startp = vmotion (w, old_startp, -1, NULL);
4355 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4358 w->start_at_line_beg = beginning_of_line_p (b, startp);
4359 MARK_WINDOWS_CHANGED (w);
4361 if (!point_would_be_visible (w, startp, XINT (point)))
4363 Bufpos new_point = start_of_last_line (w, startp);
4366 BUF_SET_PT (b, new_point);
4368 set_marker_restricted (w->pointm[CURRENT_DISP],
4369 make_int (new_point),
4376 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4377 Scroll text of current window upward N lines; or near full screen if no arg.
4378 A near full screen is `next-screen-context-lines' less than a full screen.
4379 Negative N means scroll downward.
4380 When calling from a program, supply an integer as argument or nil.
4381 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4382 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4387 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4391 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4392 Scroll text of current window downward N lines; or near full screen if no arg.
4393 A near full screen is `next-screen-context-lines' less than a full screen.
4394 Negative N means scroll upward.
4395 When calling from a program, supply a number as argument or nil.
4396 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4397 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4402 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4406 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4407 Return the other window for "other window scroll" commands.
4408 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4409 specifies the window.
4410 If `other-window-scroll-buffer' is non-nil, a window
4411 showing that buffer is used.
4416 Lisp_Object selected_window = Fselected_window (Qnil);
4418 if (MINI_WINDOW_P (XWINDOW (selected_window))
4419 && !NILP (Vminibuffer_scroll_window))
4420 window = Vminibuffer_scroll_window;
4421 /* If buffer is specified, scroll that buffer. */
4422 else if (!NILP (Vother_window_scroll_buffer))
4424 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4426 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4430 /* Nothing specified; look for a neighboring window on the same
4432 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4434 if (EQ (window, selected_window))
4435 /* That didn't get us anywhere; look for a window on another
4438 window = Fnext_window (window, Qnil, Qt, Qnil);
4439 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4440 && ! EQ (window, selected_window));
4443 CHECK_LIVE_WINDOW (window);
4445 if (EQ (window, selected_window))
4446 error ("There is no other window");
4451 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4452 Scroll next window upward N lines; or near full frame if no arg.
4453 The next window is the one below the current one; or the one at the top
4454 if the current one is at the bottom. Negative N means scroll downward.
4455 When calling from a program, supply a number as argument or nil.
4457 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4458 specifies the window to scroll.
4459 If `other-window-scroll-buffer' is non-nil, scroll the window
4460 showing that buffer, popping the buffer up if necessary.
4464 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4468 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4469 Scroll selected window display N columns left.
4470 Default for N is window width minus 2.
4474 Lisp_Object window = Fselected_window (Qnil);
4475 struct window *w = XWINDOW (window);
4476 int count = (NILP (n) ?
4477 window_char_width (w, 0) - 2 :
4478 XINT (Fprefix_numeric_value (n)));
4480 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4483 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4484 Scroll selected window display N columns right.
4485 Default for N is window width minus 2.
4489 Lisp_Object window = Fselected_window (Qnil);
4490 struct window *w = XWINDOW (window);
4491 int count = (NILP (n) ?
4492 window_char_width (w, 0) - 2 :
4493 XINT (Fprefix_numeric_value (n)));
4495 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4498 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4499 Center point in WINDOW. With N, put point on line N.
4500 The desired position of point is always relative to the window.
4501 If WINDOW is nil, the selected window is used.
4505 struct window *w = decode_window (window);
4506 struct buffer *b = XBUFFER (w->buffer);
4507 Bufpos opoint = BUF_PT (b);
4511 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4514 n = Fprefix_numeric_value (n);
4516 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4519 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4521 w->start_at_line_beg = beginning_of_line_p (b, startp);
4523 MARK_WINDOWS_CHANGED (w);
4527 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4528 Position point relative to WINDOW.
4529 With no argument, position text at center of window.
4530 An argument specifies window line; zero means top of window,
4531 negative means relative to bottom of window.
4532 If WINDOW is nil, the selected window is used.
4539 Bufpos start, new_point;
4542 /* Don't use decode_window() because we need the new value of
4545 window = Fselected_window (Qnil);
4547 CHECK_LIVE_WINDOW (window);
4548 w = XWINDOW (window);
4549 b = XBUFFER (w->buffer);
4551 height = window_displayed_height (w);
4552 selected = EQ (window, Fselected_window (w->frame));
4558 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4559 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4561 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4564 BUF_SET_PT (b, new_point);
4566 Fset_window_point (window, make_int (new_point));
4568 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4572 start = marker_position (w->start[CURRENT_DISP]);
4573 if (start < BUF_BEGV (b))
4574 start = BUF_BEGV (b);
4575 else if (start > BUF_ZV (b))
4579 new_point = BUF_PT (b);
4581 new_point = marker_position (w->pointm[CURRENT_DISP]);
4583 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4586 BUF_SET_PT (b, new_point);
4588 Fset_window_point (window, make_int (new_point));
4590 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4593 return make_int (retval);
4597 /* #### Is this going to work right when at eob? */
4598 arg = Fprefix_numeric_value (arg);
4600 XSETINT (arg, XINT (arg) + height);
4603 start = marker_position (w->start[CURRENT_DISP]);
4604 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4607 new_point = BUF_PT (b);
4609 new_point = marker_position (w->pointm[CURRENT_DISP]);
4611 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4614 BUF_SET_PT (b, new_point);
4616 Fset_window_point (window, make_int (new_point));
4618 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4620 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4626 BUF_SET_PT (b, start);
4628 Fset_window_point (window, make_int (start));
4632 return Fvertical_motion (arg, window, Qnil);
4636 new_point = vmotion (XWINDOW (window),
4637 marker_position (w->pointm[CURRENT_DISP]),
4639 Fset_window_point (window, make_int (new_point));
4640 return make_int (vpos);
4646 map_windows_1 (Lisp_Object window,
4647 int (*mapfun) (struct window *w, void *closure),
4650 for (; !NILP (window); window = XWINDOW (window)->next)
4653 struct window *w = XWINDOW (window);
4655 if (!NILP (w->vchild))
4656 retval = map_windows_1 (w->vchild, mapfun, closure);
4657 else if (!NILP (w->hchild))
4658 retval = map_windows_1 (w->hchild, mapfun, closure);
4660 retval = (mapfun) (w, closure);
4669 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4670 invocation of MAPFUN. If any invocation of MAPFUN returns
4671 non-zero, the mapping is halted. Otherwise, map_windows() maps
4672 over all windows in F.
4674 If MAPFUN creates or deletes windows, the behavior is undefined. */
4677 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4681 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4684 Lisp_Object frmcons, devcons, concons;
4686 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4688 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4700 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4703 w->shadow_thickness_changed = 1;
4704 MARK_WINDOWS_CHANGED (w);
4708 vertical_divider_changed_in_window (Lisp_Object specifier,
4712 MARK_WINDOWS_CHANGED (w);
4713 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4716 /* also used in scrollbar.c */
4718 some_window_value_changed (Lisp_Object specifier, struct window *w,
4721 MARK_WINDOWS_CHANGED (w);
4724 #ifdef MEMORY_USAGE_STATS
4730 #ifdef HAVE_SCROLLBARS
4734 int other_redisplay;
4739 compute_window_mirror_usage (struct window_mirror *mir,
4740 struct window_stats *stats,
4741 struct overhead_stats *ovstats)
4745 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4747 #ifdef HAVE_SCROLLBARS
4749 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4752 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4755 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4758 #endif /* HAVE_SCROLLBARS */
4759 stats->other_redisplay +=
4760 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4761 stats->other_redisplay +=
4762 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4766 compute_window_usage (struct window *w, struct window_stats *stats,
4767 struct overhead_stats *ovstats)
4770 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4771 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4772 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4773 stats->line_start +=
4774 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4775 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4778 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4779 Return stats about the memory usage of window WINDOW.
4780 The values returned are in the form of an alist of usage types and byte
4781 counts. The byte counts attempt to encompass all the memory used
4782 by the window (separate from the memory logically associated with a
4783 buffer or frame), including internal structures and any malloc()
4784 overhead associated with them. In practice, the byte counts are
4785 underestimated because certain memory usage is very hard to determine
4786 \(e.g. the amount of memory used inside the Xt library or inside the
4787 X server) and because there is other stuff that might logically
4788 be associated with a window, buffer, or frame (e.g. window configurations,
4789 glyphs) but should not obviously be included in the usage counts.
4791 Multiple slices of the total memory usage may be returned, separated
4792 by a nil. Each slice represents a particular view of the memory, a
4793 particular way of partitioning it into groups. Within a slice, there
4794 is no overlap between the groups of memory, and each slice collectively
4795 represents all the memory concerned.
4799 struct window_stats stats;
4800 struct overhead_stats ovstats;
4801 Lisp_Object val = Qnil;
4803 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4805 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4807 val = acons (Qface_cache, make_int (stats.face), val);
4808 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4809 #ifdef HAVE_SCROLLBARS
4810 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4812 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4813 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4814 val = acons (Qother, make_int (stats.other), val);
4815 val = Fcons (Qnil, val);
4816 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4817 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4818 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4820 return Fnreverse (val);
4823 #endif /* MEMORY_USAGE_STATS */
4826 /************************************************************************/
4827 /* Window configurations */
4828 /************************************************************************/
4830 /* #### This window configuration stuff has had serious bugs lurking in it
4831 for years; it would be a -huge- win if this was reimplemented in lisp.
4834 /* If you add anything to this structure make sure saved_window_equal
4838 Lisp_Object window; /* window */
4839 Lisp_Object buffer; /* buffer */
4840 Lisp_Object start; /* copied marker */
4841 Lisp_Object pointm; /* copied marker */
4842 Lisp_Object sb_point; /* copied marker */
4843 Lisp_Object mark; /* copied marker */
4849 Charcount modeline_hscroll;
4850 int parent_index; /* index into saved_windows */
4851 int prev_index; /* index into saved_windows */
4852 char start_at_line_beg; /* boolean */
4854 #define WINDOW_SLOT_DECLARATION
4855 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4856 #include "winslots.h"
4859 /* If you add anything to this structure make sure window_config_equal
4861 struct window_config
4863 struct lcrecord_header header;
4864 /* int frame_width; No longer needed, JV
4865 int frame_height; */
4867 Lisp_Object selected_frame;
4869 Lisp_Object current_window;
4870 Lisp_Object current_buffer;
4871 Lisp_Object minibuffer_scroll_window;
4872 Lisp_Object root_window;
4873 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4874 /* Record the values of window-min-width and window-min-height
4875 so that window sizes remain consistent with them. */
4876 int min_width, min_height;
4877 int saved_windows_count;
4878 /* Zero-sized arrays aren't ANSI C */
4879 struct saved_window saved_windows[1];
4882 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4883 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4884 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4885 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4886 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4889 mark_window_config (Lisp_Object obj)
4891 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4893 mark_object (config->current_window);
4894 mark_object (config->current_buffer);
4895 mark_object (config->minibuffer_scroll_window);
4896 mark_object (config->root_window);
4898 for (i = 0; i < config->saved_windows_count; i++)
4900 struct saved_window *s = SAVED_WINDOW_N (config, i);
4901 mark_object (s->window);
4902 mark_object (s->buffer);
4903 mark_object (s->start);
4904 mark_object (s->pointm);
4905 mark_object (s->sb_point);
4906 mark_object (s->mark);
4908 /* #### This looked like this. I do not see why specifier cached
4909 values should not be marked, as such specifiers as toolbars
4910 might have GC-able instances. Freed configs are not marked,
4911 aren't they? -- kkm */
4912 mark_object (s->dedicated);
4914 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
4915 #include "winslots.h"
4922 sizeof_window_config_for_n_windows (int n)
4924 return (sizeof (struct window_config) +
4925 /* n - 1 because zero-sized arrays aren't ANSI C */
4926 (n - 1) *sizeof (struct saved_window));
4930 sizeof_window_config (const void *h)
4932 const struct window_config *c = (const struct window_config *) h;
4933 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4937 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4939 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4942 error ("printing unreadable object #<window-configuration 0x%x>",
4943 config->header.uid);
4944 write_c_string ("#<window-configuration ", printcharfun);
4945 sprintf (buf, "0x%x>", config->header.uid);
4946 write_c_string (buf, printcharfun);
4949 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4950 window_configuration,
4952 print_window_config,
4953 0, 0, 0, 0, sizeof_window_config,
4954 struct window_config);
4957 /* Returns a boolean indicating whether the two saved windows are
4960 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4962 #define WINDOW_SLOT(slot, compare) \
4963 if (!compare (win1->slot, win2->slot)) \
4965 #include "winslots.h"
4968 EQ (win1->window, win2->window) &&
4969 EQ (win1->buffer, win2->buffer) &&
4970 internal_equal (win1->start, win2->start, 0) &&
4971 internal_equal (win1->pointm, win2->pointm, 0) &&
4972 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4973 internal_equal (win1->mark, win2->mark, 0) &&
4974 win1->pixel_left == win2->pixel_left &&
4975 win1->pixel_top == win2->pixel_top &&
4976 win1->pixel_width == win2->pixel_width &&
4977 win1->pixel_height == win2->pixel_height &&
4978 win1->hscroll == win2->hscroll &&
4979 win1->modeline_hscroll == win2->modeline_hscroll &&
4980 win1->parent_index == win2->parent_index &&
4981 win1->prev_index == win2->prev_index &&
4982 win1->start_at_line_beg == win2->start_at_line_beg;
4985 /* Returns a boolean indicating whether the two given configurations
4988 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4990 struct window_config *fig1, *fig2;
4993 /* First check if they are truly the same. */
4994 if (EQ (conf1, conf2))
4997 fig1 = XWINDOW_CONFIGURATION (conf1);
4998 fig2 = XWINDOW_CONFIGURATION (conf2);
5000 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5001 EQ (fig1->current_window, fig2->current_window) &&
5002 EQ (fig1->current_buffer, fig2->current_buffer) &&
5003 EQ (fig1->root_window, fig2->root_window) &&
5004 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5006 fig1->frame_width == fig2->frame_width &&
5007 fig1->frame_height == fig2->frame_height)) */
5010 for (i = 0; i < fig1->saved_windows_count; i++)
5012 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5013 SAVED_WINDOW_N (fig2, i)))
5020 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5021 Return t if OBJECT is a window-configuration object.
5025 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
5029 mark_windows_in_use_closure (struct window *w, void *closure)
5031 int mark = *(int *)closure;
5032 w->config_mark = mark;
5037 mark_windows_in_use (struct frame *f, int mark)
5039 map_windows (f, mark_windows_in_use_closure, &mark);
5042 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5044 free_window_configuration (Lisp_Object window_config)
5047 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5049 /* Free all the markers. It's not completely necessary that
5050 we do this (window configs sitting in a free list aren't
5051 marked normally so the markers wouldn't be marked anyway)
5052 but it's more efficient. */
5053 for (i = 0; i < config->saved_windows_count; i++)
5055 struct saved_window *p = SAVED_WINDOW_N (config, i);
5057 if (!NILP (p->pointm))
5059 free_marker (XMARKER (p->pointm));
5062 if (!NILP (p->start))
5064 free_marker (XMARKER (p->start));
5067 if (!NILP (p->sb_point))
5069 free_marker (XMARKER (p->sb_point));
5072 if (!NILP (p->mark))
5074 free_marker (XMARKER (p->mark));
5079 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5080 free_managed_lcrecord (Vwindow_configuration_free_list
5081 [config->saved_windows_count - 1],
5087 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5088 Set the configuration of windows and buffers as specified by CONFIGURATION.
5089 CONFIGURATION must be a value previously returned
5090 by `current-window-configuration' (which see).
5095 struct window_config *config;
5096 struct saved_window *p;
5097 Lisp_Object new_current_buffer;
5101 struct gcpro gcpro1;
5102 Lisp_Object old_window_config;
5103 /* int previous_frame_height;
5104 int previous_frame_width;*/
5105 int previous_pixel_top;
5106 int previous_pixel_height;
5107 int previous_pixel_left;
5108 int previous_pixel_width;
5109 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5110 int real_font_height;
5111 int converted_minibuf_height,target_minibuf_height;
5112 int specpdl_count = specpdl_depth ();
5114 GCPRO1 (configuration);
5116 CHECK_WINDOW_CONFIGURATION (configuration);
5117 config = XWINDOW_CONFIGURATION (configuration);
5119 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5122 /* Do not signal an error here if the frame was deleted. There are
5123 reasonable cases where we could get here with a deleted frame and
5124 just want to do close to nothing instead. */
5126 if (FRAME_LIVE_P (f))
5128 /* restore the frame characteristics */
5130 new_current_buffer = config->current_buffer;
5131 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5132 new_current_buffer = Qnil;
5135 * Assumed precondition: w->config_mark = 0 for all w
5136 * This procedure should ensure this is true by the time it exits
5137 * to ensure the precondition for future calls.
5139 * We use w->config_mark to know whether we're modifying a
5140 * window that is currently visible on the frame (#### we
5141 * should just be able to check whether the window is dead
5142 * or not, but this way is safer?). As we process each
5143 * window, we set its config_mark to 0. At the end, we
5144 * go through all the windows that used to be on the frame,
5145 * set each one's config_mark to 0 (to maintain the
5146 * assumed precondition) and delete each one that's no
5149 * #### Using a window-configuration to keep track of
5150 * the current windows is wasteful. All we need is the
5151 * list of windows, so we could just use a dynarr.
5153 old_window_config = Fcurrent_window_configuration (frame);
5155 /* If the new configuration is already equal to the old, then stop
5156 right here. This saves the work below and it also saves
5157 triggering a full redisplay of this window. This is a huge win
5158 when using the mouse since the mode motion code uses
5159 save-window-excursion extensively but will rarely cause the
5160 configuration to actually change. */
5161 if (window_config_equal (configuration, old_window_config))
5163 free_window_configuration (old_window_config);
5168 /* We can't quit or even check for quit because that may cause
5169 investigation of the frame state, which may crash if the frame is
5170 in an inconsistent state. */
5171 begin_dont_check_for_quit ();
5172 record_unwind_protect (free_window_configuration, old_window_config);
5174 mark_windows_in_use (f, 1);
5177 /* JV: This is bogus,
5178 First of all, the units are inconsistent. The frame sizes are measured
5179 in characters but the window sizes are stored in pixels. So if a
5180 font size change happened between saving and restoring, the
5181 frame "sizes" maybe equal but the windows still should be
5182 resized. This is tickled alot by the new "character size
5183 stays constant" policy in 21.0. It leads to very wierd
5184 glitches (and possibly crashes when asserts are tickled).
5186 Just changing the units doens't help because changing the
5187 toolbar configuration can also change the pixel positions.
5188 Luckily there is a much simpler way of doing this, see below.
5190 previous_frame_width = FRAME_WIDTH (f);
5191 previous_frame_height = FRAME_HEIGHT (f);
5192 /* If the frame has been resized since this window configuration was
5193 made, we change the frame to the size specified in the
5194 configuration, restore the configuration, and then resize it
5195 back. We keep track of the prevailing height in these variables. */
5196 if (config->frame_height != FRAME_HEIGHT (f)
5197 || config->frame_width != FRAME_WIDTH (f))
5198 change_frame_size (f, config->frame_height, config->frame_width, 0);
5201 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5202 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5203 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5204 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5206 /* remember some properties of the minibuffer */
5208 default_face_height_and_width (frame, &real_font_height, 0);
5209 assert(real_font_height > 0);
5211 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5213 previous_minibuf_height
5214 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5215 previous_minibuf_top
5216 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5217 previous_minibuf_width
5218 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5222 previous_minibuf_height = 0;
5223 previous_minibuf_top = 0;
5224 previous_minibuf_width = 0;
5226 converted_minibuf_height =
5227 (previous_minibuf_height % real_font_height) == 0 ?
5228 - (previous_minibuf_height / real_font_height ) : /* lines */
5229 previous_minibuf_height; /* pixels */
5231 /* Temporarily avoid any problems with windows that are smaller
5232 than they are supposed to be. */
5233 window_min_height = 1;
5234 window_min_width = 1;
5236 /* OK, now restore all the windows in the window config.
5237 This may involve "undeleting" windows, since the
5238 windows in the window config may be deleted.
5240 for (k = 0; k < config->saved_windows_count; k++)
5242 p = SAVED_WINDOW_N (config, k);
5243 w = XWINDOW (p->window);
5246 /* The window might be dead. In this case, its redisplay
5247 structures were freed, so we need to reallocate them. */
5248 if (!w->face_cachels)
5250 w->face_cachels = Dynarr_new (face_cachel);
5251 reset_face_cachels (w);
5253 if (!w->glyph_cachels)
5254 w->glyph_cachels = Dynarr_new (glyph_cachel);
5255 if (!w->line_start_cache)
5256 w->line_start_cache = Dynarr_new (line_start_cache);
5257 w->gutter_extent_modiff[0] = 0;
5258 w->gutter_extent_modiff[1] = 0;
5259 w->gutter_extent_modiff[2] = 0;
5260 w->gutter_extent_modiff[3] = 0;
5263 if (p->parent_index >= 0)
5264 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5268 if (p->prev_index >= 0)
5270 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5272 /* This is true for a minibuffer-only frame. */
5273 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5276 XWINDOW (w->prev)->next = p->window;
5281 if (!NILP (w->parent))
5283 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5285 XWINDOW (w->parent)->vchild = p->window;
5286 XWINDOW (w->parent)->hchild = Qnil;
5290 XWINDOW (w->parent)->hchild = p->window;
5291 XWINDOW (w->parent)->vchild = Qnil;
5295 if (!w->config_mark)
5297 /* #### This should be equivalent to the window previously
5298 having been dead. If we're brave, we'll put in an
5299 assertion to this effect. */
5300 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5302 else /* if (!EQ (w->buffer, p->buffer)) */
5304 /* With the new redisplay we let it know that a change has
5305 been made and it will take care of the rest. If we don't
5306 tell it something has possibly changed it could lead to
5307 incorrect display. */
5308 MARK_WINDOWS_CHANGED (w);
5311 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5312 WINDOW_TOP (w) = WINDOW_TOP (p);
5313 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5314 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5315 w->hscroll = p->hscroll;
5316 w->modeline_hscroll = p->modeline_hscroll;
5317 w->line_cache_last_updated = Qzero;
5318 SET_LAST_MODIFIED (w, 1);
5319 SET_LAST_FACECHANGE (w);
5322 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5323 #include "winslots.h"
5325 /* Reinstall the saved buffer and pointers into it. */
5326 if (NILP (p->buffer))
5327 w->buffer = p->buffer;
5330 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5331 /* If saved buffer is alive, install it. */
5333 w->buffer = p->buffer;
5334 w->start_at_line_beg = p->start_at_line_beg;
5335 set_marker_restricted (w->start[CURRENT_DISP],
5336 Fmarker_position (p->start),
5338 set_marker_restricted (w->pointm[CURRENT_DISP],
5339 Fmarker_position (p->pointm),
5341 set_marker_restricted (w->sb_point,
5342 Fmarker_position (p->sb_point),
5344 Fset_marker (XBUFFER (w->buffer)->mark,
5345 Fmarker_position (p->mark), w->buffer);
5347 /* As documented in Fcurrent_window_configuration, don't
5348 save the location of point in the buffer which was current
5349 when the window configuration was recorded. */
5350 if (!EQ (p->buffer, new_current_buffer) &&
5351 XBUFFER (p->buffer) == current_buffer)
5352 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5354 else if (NILP (w->buffer) ||
5355 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5356 /* Else if window's old buffer is dead too, get a live one. */
5358 /* #### The following line makes me nervous... */
5359 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5360 w->buffer = Fget_buffer_create (QSscratch);
5361 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5362 /* This will set the markers to beginning of visible
5364 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5365 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5367 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5368 w->start_at_line_beg = 1;
5371 /* Keeping window's old buffer; make sure the markers
5374 /* Set window markers at start of visible range. */
5375 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5376 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5378 if (XMARKER (w->sb_point)->buffer == 0)
5379 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5380 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5381 set_marker_restricted (w->pointm[CURRENT_DISP],
5383 (BUF_PT (XBUFFER (w->buffer))),
5385 w->start_at_line_beg = 1;
5390 FRAME_ROOT_WINDOW (f) = config->root_window;
5391 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5392 then calls do_switch_frame() below to select the frame that was
5393 recorded in the window config as being selected.
5395 Instead, we don't ever change the selected frame, and either
5396 call Fselect_window() below if the window config's frame is
5397 currently selected, or just set the selected window of the
5398 window config's frame. */
5401 /* Set the frame height to the value it had before this function. */
5402 if (previous_frame_height != FRAME_HEIGHT (f)
5403 || previous_frame_width != FRAME_WIDTH (f))
5404 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5406 /* We just reset the size and position of the minibuffer, to its old
5407 value, which needn't be valid. So we do some magic to see which value
5408 to actually take. Then we set it.
5411 We take the old value if is in the same units but differs from the
5414 #### Now we get more cases correct then ever before, but
5415 are we treating all? For instance what if the frames minibuf window
5416 is no longer the same one?
5418 target_minibuf_height = previous_minibuf_height;
5419 if (converted_minibuf_height &&
5420 (converted_minibuf_height * config->minibuf_height) > 0 &&
5421 (converted_minibuf_height != config->minibuf_height))
5423 target_minibuf_height = config->minibuf_height < 0 ?
5424 - (config->minibuf_height * real_font_height) :
5425 config->minibuf_height;
5426 target_minibuf_height =
5427 max(target_minibuf_height,real_font_height);
5429 if (previous_minibuf_height)
5431 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5432 = previous_minibuf_top -
5433 (target_minibuf_height - previous_minibuf_height);
5434 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5435 target_minibuf_height, 0);
5436 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5437 previous_minibuf_width, 0);
5440 /* This is a better way to deal with frame resizing, etc.
5441 What we _actually_ want is for the old (just restored)
5443 into the place of the new one. So we just do that. Simple! */
5444 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5445 /* Note that this function also updates the subwindow
5447 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5448 previous_pixel_height -
5449 (target_minibuf_height - previous_minibuf_height), 0);
5450 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5451 /* Note that this function also updates the subwindow
5453 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5455 /* If restoring in the current frame make the window current,
5456 otherwise just update the frame selected_window slot to be
5457 the restored current_window. */
5458 if (f == selected_frame ())
5461 /* When using `pop-window-configuration', often the minibuffer
5462 ends up as the selected window even though it's not active ...
5463 I really don't know the cause of this, but it should never
5464 happen. This kludge should fix it.
5466 #### Find out why this is really going wrong. */
5467 if (!minibuf_level &&
5468 MINI_WINDOW_P (XWINDOW (config->current_window)))
5469 window_to_select = Fnext_window (config->current_window,
5472 window_to_select = config->current_window;
5474 /* Do this last so that buffer stacking is calculated
5476 Fselect_window (config->current_window, Qnil);
5478 if (!NILP (new_current_buffer))
5480 Fset_buffer (new_current_buffer);
5481 Frecord_buffer (new_current_buffer);
5485 Fset_buffer (XWINDOW (config->current_window)->buffer);
5486 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5490 set_frame_selected_window (f, config->current_window);
5493 old_window_config = Qnil; /* Warning suppression */
5495 /* Restore the minimum heights recorded in the configuration. */
5496 window_min_height = config->min_height;
5497 window_min_width = config->min_width;
5500 /* see above comment */
5501 /* Fselect_window will have made f the selected frame, so we
5502 reselect the proper frame here. Fhandle_switch_frame will change the
5503 selected window too, but that doesn't make the call to
5504 Fselect_window above totally superfluous; it still sets f's
5506 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5507 do_switch_frame (config->selected_frame, Qnil, 0);
5510 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5512 if (FRAME_LIVE_P (f))
5514 /* Do this before calling recompute_all_cached_specifiers_in_window()
5515 so that things like redisplay_redraw_cursor() won't abort due
5516 to no window mirror present. */
5517 f->mirror_dirty = 1;
5519 config = XWINDOW_CONFIGURATION (old_window_config);
5520 for (k = 0; k < config->saved_windows_count; k++)
5522 p = SAVED_WINDOW_N (config, k);
5523 w = XWINDOW (p->window);
5524 /* Remember, we set w->config_mark on all currently visible
5525 windows, and reset it on all newly visible windows.
5526 Any windows still marked need to be deleted. */
5529 mark_window_as_deleted (w);
5534 /* We just potentially changed the window's buffer and
5535 potentially turned a dead window into a live one,
5536 so we need to recompute the cached specifier values. */
5537 recompute_all_cached_specifiers_in_window (w);
5542 /* Now restore things, when everything else if OK. */
5544 unbind_to (specpdl_count, Qnil);
5551 /* Mark all subwindows of a window as deleted. The argument
5552 W is actually the subwindow tree of the window in question. */
5555 delete_all_subwindows (struct window *w)
5557 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5558 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5559 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5561 mark_window_as_deleted (w);
5566 count_windows (struct window *window)
5569 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5570 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5571 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5575 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5578 for (j = 0; j < lim; j++)
5580 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5584 return 0; /* suppress compiler warning */
5588 save_window_save (Lisp_Object window, struct window_config *config, int i)
5592 for (; !NILP (window); window = w->next)
5594 struct saved_window *p = SAVED_WINDOW_N (config, i);
5596 w = XWINDOW (window);
5599 p->buffer = w->buffer;
5600 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5601 WINDOW_TOP (p) = WINDOW_TOP (w);
5602 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5603 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5604 p->hscroll = w->hscroll;
5605 p->modeline_hscroll = w->modeline_hscroll;
5607 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5608 #include "winslots.h"
5610 if (!NILP (w->buffer))
5612 /* Save w's value of point in the window configuration.
5613 If w is the selected window, then get the value of point
5614 from the buffer; pointm is garbage in the selected window. */
5615 if (EQ (window, Fselected_window (Qnil)))
5617 p->pointm = noseeum_make_marker ();
5618 Fset_marker (p->pointm,
5619 make_int (BUF_PT (XBUFFER (w->buffer))),
5623 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5625 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5626 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5627 p->start_at_line_beg = w->start_at_line_beg;
5629 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5637 p->start_at_line_beg = 0;
5640 if (NILP (w->parent))
5641 p->parent_index = -1;
5643 p->parent_index = saved_window_index (w->parent, config, i);
5647 p->prev_index = saved_window_index (w->prev, config, i);
5648 if (!NILP (w->vchild))
5649 i = save_window_save (w->vchild, config, i);
5650 if (!NILP (w->hchild))
5651 i = save_window_save (w->hchild, config, i);
5658 /* Added to doc string:
5660 This also records the currently selected frame, and FRAME's focus
5661 redirection (see `redirect-frame-focus').
5666 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5667 Return an object representing the current window configuration of FRAME.
5668 If FRAME is nil or omitted, use the selected frame.
5669 This describes the number of windows, their sizes and current buffers,
5670 and for each displayed buffer, where display starts, and the positions of
5671 point and mark. An exception is made for point in the current buffer:
5672 its value is -not- saved.
5677 struct frame *f = decode_frame (frame);
5678 struct window_config *config;
5679 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5681 int real_font_height;
5683 if (n_windows <= countof (Vwindow_configuration_free_list))
5684 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5685 (Vwindow_configuration_free_list
5688 /* More than ten windows; just allocate directly */
5689 config = (struct window_config *)
5690 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5691 &lrecord_window_configuration);
5692 XSETWINDOW_CONFIGURATION (result, config);
5694 config->frame_width = FRAME_WIDTH (f);
5695 config->frame_height = FRAME_HEIGHT (f); */
5696 /* When using `push-window-configuration', often the minibuffer ends
5697 up as the selected window because functions run as the result of
5698 user interaction e.g. hyper-apropros. It seems to me the sensible
5699 thing to do is not record the minibuffer here. */
5700 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5701 config->current_window = FRAME_SELECTED_WINDOW (f);
5703 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5704 XSETBUFFER (config->current_buffer, current_buffer);
5705 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5706 config->root_window = FRAME_ROOT_WINDOW (f);
5707 config->min_height = window_min_height;
5708 config->min_width = window_min_width;
5709 config->saved_windows_count = n_windows;
5710 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5712 /* save the minibuffer height using the heuristics from
5713 change_frame_size_1 */
5715 XSETFRAME (frame, f); /* frame could have been nil ! */
5716 default_face_height_and_width (frame, &real_font_height, 0);
5717 assert(real_font_height > 0);
5719 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5720 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5723 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5724 - (minibuf_height / real_font_height ) : /* lines */
5725 minibuf_height; /* pixels */
5731 save_window_excursion_unwind (Lisp_Object window_config)
5733 Lisp_Object val = Fset_window_configuration (window_config);
5734 free_window_configuration (window_config);
5738 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5739 Execute body, preserving window sizes and contents.
5740 Restores which buffer appears in which window, where display starts,
5741 as well as the current buffer.
5742 Does not restore the value of point in current buffer.
5746 /* This function can GC */
5748 int speccount = specpdl_depth ();
5750 record_unwind_protect (save_window_excursion_unwind,
5751 Fcurrent_window_configuration (Qnil));
5752 val = Fprogn (args);
5753 return unbind_to (speccount, val);
5756 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5757 Return the horizontal pixel position of POS in window.
5758 Beginning of line is column 0. This is calculated using the redisplay
5759 display tables. If WINDOW is nil, the current window is assumed.
5760 If POS is nil, point is assumed. Note that POS must be visible for
5761 a non-nil result to be returned.
5765 struct window* w = decode_window (window);
5766 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5768 struct display_line *dl = 0;
5769 struct display_block *db = 0;
5770 struct rune* rb = 0;
5771 int y = w->last_point_y[CURRENT_DISP];
5772 int x = w->last_point_x[CURRENT_DISP];
5774 if (MINI_WINDOW_P (w))
5777 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5783 pos = Fwindow_point (window);
5788 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5793 for (i = first_line; i < Dynarr_length (dla); i++)
5795 dl = Dynarr_atp (dla, i);
5796 /* find the vertical location first */
5797 if (point >= dl->bufpos && point <= dl->end_bufpos)
5799 db = get_display_block_from_line (dl, TEXT);
5800 for (i = 0; i < Dynarr_length (db->runes); i++)
5802 rb = Dynarr_atp (db->runes, i);
5803 if (point <= rb->bufpos)
5815 /* optimised case */
5816 dl = Dynarr_atp (dla, y);
5817 db = get_display_block_from_line (dl, TEXT);
5819 if (x >= Dynarr_length (db->runes))
5822 rb = Dynarr_atp (db->runes, x);
5825 return make_int (rb->xpos - WINDOW_LEFT (w));
5830 /* This is short and simple in elisp, but... it was written to debug
5831 problems purely on the C side. That is where we need to call it so
5834 debug_print_window (Lisp_Object window, int level)
5837 Lisp_Object child = Fwindow_first_vchild (window);
5840 child = Fwindow_first_hchild (window);
5842 for (i = level; i > 0; i--)
5845 stderr_out ("#<window");
5847 Lisp_Object buffer = XWINDOW (window)->buffer;
5848 if (!NILP (buffer) && BUFFERP (buffer))
5849 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5851 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
5853 while (!NILP (child))
5855 debug_print_window (child, level + 1);
5856 child = Fwindow_next_child (child);
5860 void debug_print_windows (struct frame *f);
5862 debug_print_windows (struct frame *f)
5864 debug_print_window (f->root_window, 0);
5865 putc ('\n', stderr);
5867 #endif /* DEBUG_XEMACS */
5870 /************************************************************************/
5871 /* initialization */
5872 /************************************************************************/
5875 syms_of_window (void)
5877 INIT_LRECORD_IMPLEMENTATION (window);
5878 INIT_LRECORD_IMPLEMENTATION (window_configuration);
5880 defsymbol (&Qwindowp, "windowp");
5881 defsymbol (&Qwindow_live_p, "window-live-p");
5882 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5883 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5884 defsymbol (&Qdisplay_buffer, "display-buffer");
5886 #ifdef MEMORY_USAGE_STATS
5887 defsymbol (&Qface_cache, "face-cache");
5888 defsymbol (&Qglyph_cache, "glyph-cache");
5889 defsymbol (&Qline_start_cache, "line-start-cache");
5890 #ifdef HAVE_SCROLLBARS
5891 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5893 defsymbol (&Qother_redisplay, "other-redisplay");
5894 /* Qother in general.c */
5897 DEFSUBR (Fselected_window);
5898 DEFSUBR (Flast_nonminibuf_window);
5899 DEFSUBR (Fminibuffer_window);
5900 DEFSUBR (Fwindow_minibuffer_p);
5902 DEFSUBR (Fwindow_live_p);
5903 DEFSUBR (Fwindow_first_hchild);
5904 DEFSUBR (Fwindow_first_vchild);
5905 DEFSUBR (Fwindow_next_child);
5906 DEFSUBR (Fwindow_previous_child);
5907 DEFSUBR (Fwindow_parent);
5908 DEFSUBR (Fwindow_lowest_p);
5909 DEFSUBR (Fwindow_truncated_p);
5910 DEFSUBR (Fwindow_highest_p);
5911 DEFSUBR (Fwindow_leftmost_p);
5912 DEFSUBR (Fwindow_rightmost_p);
5913 DEFSUBR (Fpos_visible_in_window_p);
5914 DEFSUBR (Fwindow_buffer);
5915 DEFSUBR (Fwindow_frame);
5916 DEFSUBR (Fwindow_height);
5917 DEFSUBR (Fwindow_displayed_height);
5918 DEFSUBR (Fwindow_width);
5919 DEFSUBR (Fwindow_full_width);
5920 DEFSUBR (Fwindow_pixel_height);
5921 DEFSUBR (Fwindow_pixel_width);
5922 DEFSUBR (Fwindow_text_area_height);
5923 DEFSUBR (Fwindow_text_area_pixel_height);
5924 DEFSUBR (Fwindow_displayed_text_pixel_height);
5925 DEFSUBR (Fwindow_text_area_pixel_width);
5926 DEFSUBR (Fwindow_hscroll);
5927 DEFSUBR (Fset_window_hscroll);
5928 DEFSUBR (Fmodeline_hscroll);
5929 DEFSUBR (Fset_modeline_hscroll);
5930 #if 0 /* bogus FSF crock */
5931 DEFSUBR (Fwindow_redisplay_end_trigger);
5932 DEFSUBR (Fset_window_redisplay_end_trigger);
5934 DEFSUBR (Fwindow_pixel_edges);
5935 DEFSUBR (Fwindow_text_area_pixel_edges);
5936 DEFSUBR (Fwindow_point);
5937 DEFSUBR (Fwindow_start);
5938 DEFSUBR (Fwindow_end);
5939 DEFSUBR (Fwindow_last_line_visible_height);
5940 DEFSUBR (Fset_window_point);
5941 DEFSUBR (Fset_window_start);
5942 DEFSUBR (Fwindow_dedicated_p);
5943 DEFSUBR (Fset_window_dedicated_p);
5944 DEFSUBR (Fnext_window);
5945 DEFSUBR (Fprevious_window);
5946 DEFSUBR (Fnext_vertical_window);
5947 DEFSUBR (Fother_window);
5948 DEFSUBR (Fget_lru_window);
5949 DEFSUBR (Fget_largest_window);
5950 DEFSUBR (Fget_buffer_window);
5951 DEFSUBR (Fwindow_left_margin_pixel_width);
5952 DEFSUBR (Fwindow_right_margin_pixel_width);
5953 DEFSUBR (Fdelete_other_windows);
5954 DEFSUBR (Fdelete_windows_on);
5955 DEFSUBR (Freplace_buffer_in_windows);
5956 DEFSUBR (Fdelete_window);
5957 DEFSUBR (Fset_window_buffer);
5958 DEFSUBR (Fselect_window);
5959 DEFSUBR (Fsplit_window);
5960 DEFSUBR (Fenlarge_window);
5961 DEFSUBR (Fenlarge_window_pixels);
5962 DEFSUBR (Fshrink_window);
5963 DEFSUBR (Fshrink_window_pixels);
5964 DEFSUBR (Fscroll_up);
5965 DEFSUBR (Fscroll_down);
5966 DEFSUBR (Fscroll_left);
5967 DEFSUBR (Fscroll_right);
5968 DEFSUBR (Fother_window_for_scrolling);
5969 DEFSUBR (Fscroll_other_window);
5970 DEFSUBR (Fcenter_to_window_line);
5971 DEFSUBR (Fmove_to_window_line);
5972 #ifdef MEMORY_USAGE_STATS
5973 DEFSUBR (Fwindow_memory_usage);
5975 DEFSUBR (Fwindow_configuration_p);
5976 DEFSUBR (Fset_window_configuration);
5977 DEFSUBR (Fcurrent_window_configuration);
5978 DEFSUBR (Fsave_window_excursion);
5979 DEFSUBR (Fcurrent_pixel_column);
5983 reinit_vars_of_window (void)
5986 /* Make sure all windows get marked */
5987 minibuf_window = Qnil;
5988 staticpro_nodump (&minibuf_window);
5990 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5992 Vwindow_configuration_free_list[i] =
5993 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5994 &lrecord_window_configuration);
5995 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6000 vars_of_window (void)
6002 reinit_vars_of_window ();
6004 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6005 *Non-nil means to scroll if point lands on a line which is clipped.
6007 scroll_on_clipped_lines = 1;
6009 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6010 See `temp-buffer-show-function'.
6012 Vtemp_buffer_show_hook = Qnil;
6014 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6015 Non-nil means call as function to display a help buffer.
6016 The function is called with one argument, the buffer to be displayed.
6017 Used by `with-output-to-temp-buffer'.
6018 If this function is used, then it must do the entire job of showing
6019 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6021 Vtemp_buffer_show_function = Qnil;
6023 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6024 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6026 Vminibuffer_scroll_window = Qnil;
6028 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6029 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6031 Vother_window_scroll_buffer = Qnil;
6033 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6034 *Number of pixels to scroll by per requested line.
6035 If nil then normal line scrolling occurs regardless of line height.
6036 If t then scrolling is done in increments equal to the height of the default face.
6038 Vwindow_pixel_scroll_increment = Qt;
6040 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6041 *Number of lines of continuity when scrolling by screenfuls.
6043 next_screen_context_lines = 2;
6045 DEFVAR_INT ("window-min-height", &window_min_height /*
6046 *Delete any window less than this tall (including its modeline).
6048 window_min_height = 4;
6050 DEFVAR_INT ("window-min-width", &window_min_width /*
6051 *Delete any window less than this wide.
6053 window_min_width = 10;
6057 specifier_vars_of_window (void)
6059 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6060 *How thick to draw 3D shadows around modelines.
6061 If this is set to 0, modelines will be the traditional 2D. Sizes above
6062 10 will be accepted but the maximum thickness that will be drawn is 10.
6063 This is a specifier; use `set-specifier' to change it.
6065 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6066 /* The initial value for modeline-shadow-thickness is 2, but if the
6067 user removes all specifications we provide a fallback value of 0,
6068 which is probably what was expected. */
6069 set_specifier_fallback (Vmodeline_shadow_thickness,
6070 list1 (Fcons (Qnil, Qzero)));
6071 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6073 set_specifier_caching (Vmodeline_shadow_thickness,
6074 offsetof (struct window, modeline_shadow_thickness),
6075 modeline_shadow_thickness_changed,
6078 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6079 *Whether the modeline should be displayed.
6080 This is a specifier; use `set-specifier' to change it.
6082 Vhas_modeline_p = Fmake_specifier (Qboolean);
6083 set_specifier_fallback (Vhas_modeline_p,
6084 list1 (Fcons (Qnil, Qt)));
6085 set_specifier_caching (Vhas_modeline_p,
6086 offsetof (struct window, has_modeline_p),
6087 /* #### It's strange that we need a special
6088 flag to indicate that the shadow-thickness
6089 has changed, but not one to indicate that
6090 the modeline has been turned off or on. */
6091 some_window_value_changed,
6094 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6095 &Vvertical_divider_always_visible_p /*
6096 *Should XEmacs always display vertical dividers between windows.
6098 When this is non-nil, vertical dividers are always shown, and are
6099 draggable. When it is nil, vertical dividers are shown only when
6100 there are no scrollbars in between windows, and are not draggable.
6102 This is a specifier; use `set-specifier' to change it.
6104 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6105 set_specifier_fallback (Vvertical_divider_always_visible_p,
6106 list1 (Fcons (Qnil, Qt)));
6107 set_specifier_caching (Vvertical_divider_always_visible_p,
6108 offsetof (struct window,
6109 vertical_divider_always_visible_p),
6110 vertical_divider_changed_in_window,
6113 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6114 *How thick to draw 3D shadows around vertical dividers.
6115 This is a specifier; use `set-specifier' to change it.
6117 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6118 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6119 list1 (Fcons (Qnil, Qzero)));
6120 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6122 set_specifier_caching (Vvertical_divider_shadow_thickness,
6123 offsetof (struct window,
6124 vertical_divider_shadow_thickness),
6125 vertical_divider_changed_in_window,
6127 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6128 *The width of the vertical dividers, not including shadows.
6130 For TTY windows, divider line is always one character wide. When
6131 instance of this specifier is zero in a TTY window, no divider is
6132 drawn at all between windows. When non-zero, a one character wide
6133 divider is displayed.
6135 This is a specifier; use `set-specifier' to change it.
6138 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6140 Lisp_Object fb = Qnil;
6142 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6144 #ifdef HAVE_X_WINDOWS
6145 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6147 #ifdef HAVE_MS_WINDOWS
6148 /* #### This should be made magic and made to obey system settings */
6149 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6151 set_specifier_fallback (Vvertical_divider_line_width, fb);
6153 set_specifier_caching (Vvertical_divider_line_width,
6154 offsetof (struct window,
6155 vertical_divider_line_width),
6156 vertical_divider_changed_in_window,
6159 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6160 *How much space to leave around the vertical dividers.
6162 In TTY windows, spacing is always zero, and the value of this
6163 specifier is ignored.
6165 This is a specifier; use `set-specifier' to change it.
6167 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6169 Lisp_Object fb = Qnil;
6171 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6173 #ifdef HAVE_X_WINDOWS
6174 /* #### 3D dividers look great on MS Windows with spacing = 0.
6175 Should not the same value be the fallback under X? - kkm */
6176 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6178 #ifdef HAVE_MS_WINDOWS
6179 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6181 set_specifier_fallback (Vvertical_divider_spacing, fb);
6183 set_specifier_caching (Vvertical_divider_spacing,
6184 offsetof (struct window, vertical_divider_spacing),
6185 vertical_divider_changed_in_window,