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 edge of divider border and window edge */
86 Lisp_Object Vvertical_divider_spacing;
88 /* How much to scroll by per-line. */
89 Lisp_Object Vwindow_pixel_scroll_increment;
91 /* Scroll if point lands on the bottom line and that line is partially
93 int scroll_on_clipped_lines;
95 /* The minibuffer window of the selected frame.
96 Note that you cannot test for minibufferness of an arbitrary window
97 by comparing against this; but you can test for minibufferness of
98 the selected window. */
99 Lisp_Object minibuf_window;
101 /* Non-nil means it is the window for C-M-v to scroll
102 when the minibuffer is selected. */
103 Lisp_Object Vminibuffer_scroll_window;
105 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
106 Lisp_Object Vother_window_scroll_buffer;
108 /* Non-nil means it's the function to call to display temp buffers. */
109 Lisp_Object Vtemp_buffer_show_function;
111 Lisp_Object Vtemp_buffer_show_hook;
113 /* If a window gets smaller than either of these, it is removed. */
114 int window_min_height;
115 int window_min_width;
117 /* Hook run at end of temp_output_buffer_show. */
118 Lisp_Object Qtemp_buffer_show_hook;
120 /* Number of lines of continuity in scrolling by screenfuls. */
121 int next_screen_context_lines;
123 /* List of freed window configurations with 1 - 10 windows. */
124 static Lisp_Object Vwindow_configuration_free_list[10];
126 #define SET_LAST_MODIFIED(w, cache_too) \
128 (w)->last_modified[CURRENT_DISP] = Qzero; \
129 (w)->last_modified[DESIRED_DISP] = Qzero; \
130 (w)->last_modified[CMOTION_DISP] = Qzero; \
132 (w)->line_cache_last_updated = Qzero; \
135 #define SET_LAST_FACECHANGE(w) \
137 (w)->last_facechange[CURRENT_DISP] = Qzero; \
138 (w)->last_facechange[DESIRED_DISP] = Qzero; \
139 (w)->last_facechange[CMOTION_DISP] = Qzero; \
143 #define MARK_DISP_VARIABLE(field) \
144 mark_object (window->field[CURRENT_DISP]); \
145 mark_object (window->field[DESIRED_DISP]); \
146 mark_object (window->field[CMOTION_DISP]);
149 mark_window (Lisp_Object obj)
151 struct window *window = XWINDOW (obj);
152 mark_object (window->frame);
153 mark_object (window->mini_p);
154 mark_object (window->next);
155 mark_object (window->prev);
156 mark_object (window->hchild);
157 mark_object (window->vchild);
158 mark_object (window->parent);
159 mark_object (window->buffer);
160 MARK_DISP_VARIABLE (start);
161 MARK_DISP_VARIABLE (pointm);
162 mark_object (window->sb_point); /* #### move to scrollbar.c? */
163 mark_object (window->use_time);
164 MARK_DISP_VARIABLE (last_modified);
165 MARK_DISP_VARIABLE (last_point);
166 MARK_DISP_VARIABLE (last_start);
167 MARK_DISP_VARIABLE (last_facechange);
168 mark_object (window->line_cache_last_updated);
169 mark_object (window->redisplay_end_trigger);
170 mark_object (window->subwindow_instance_cache);
172 mark_face_cachels (window->face_cachels);
173 mark_glyph_cachels (window->glyph_cachels);
175 #define WINDOW_SLOT(slot, compare) mark_object (window->slot)
176 #include "winslots.h"
182 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
187 error ("printing unreadable object #<window 0x%x>",
188 XWINDOW (obj)->header.uid);
190 write_c_string ("#<window", printcharfun);
191 if (!NILP (XWINDOW (obj)->buffer))
193 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
194 write_c_string (" on ", printcharfun);
195 print_internal (name, printcharfun, 1);
197 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
198 write_c_string (buf, printcharfun);
202 finalize_window (void *header, int for_disksave)
204 struct window *w = (struct window *) header;
206 if (w->line_start_cache)
208 Dynarr_free (w->line_start_cache);
209 w->line_start_cache = 0;
216 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
218 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
219 if (cachel->merged_faces)
221 Dynarr_free (cachel->merged_faces);
222 cachel->merged_faces = 0;
225 Dynarr_free (w->face_cachels);
229 if (w->glyph_cachels)
231 Dynarr_free (w->glyph_cachels);
232 w->glyph_cachels = 0;
236 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
237 mark_window, print_window, finalize_window,
238 0, 0, 0, struct window);
241 #define INIT_DISP_VARIABLE(field, initialization) \
242 p->field[CURRENT_DISP] = initialization; \
243 p->field[DESIRED_DISP] = initialization; \
244 p->field[CMOTION_DISP] = initialization;
246 /* We have an implicit assertion that the first two elements (default
247 and modeline faces) are always present in the face_element_cache.
248 Normally redisplay ensures this. However, it is possible for a
249 window to get created and functions which reference these values
250 called before redisplay works with the window for the first time.
251 All callers of allocate_window should therefore call
252 reset_face_cachels on the created window. We can't do it
253 here because the window must have its frame pointer set or
254 reset_face_cachels will fail. */
256 allocate_window (void)
259 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
273 INIT_DISP_VARIABLE (start, Fmake_marker ());
274 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
275 p->sb_point = Fmake_marker ();
277 INIT_DISP_VARIABLE (last_modified, Qzero);
278 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
279 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
280 INIT_DISP_VARIABLE (last_facechange, Qzero);
281 p->face_cachels = Dynarr_new (face_cachel);
282 p->glyph_cachels = Dynarr_new (glyph_cachel);
283 p->line_start_cache = Dynarr_new (line_start_cache);
284 p->subwindow_instance_cache = make_lisp_hash_table (30,
285 HASH_TABLE_KEY_VALUE_WEAK,
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 amount 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 amount 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);
1606 struct frame *f = XFRAME (w->frame);
1609 w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
1611 w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
1613 return list4 (make_int (left),
1615 make_int (left + w->pixel_width),
1616 make_int (top + w->pixel_height));
1619 DEFUN ("window-text-area-pixel-edges",
1620 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1621 Return a list of the pixel edge coordinates of the text area of WINDOW.
1622 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1623 top left corner of the window.
1627 struct window *w = decode_window (window);
1629 int left = window_left_gutter_width (w, /* modeline = */ 0);
1630 int top = window_top_gutter_height (w);
1631 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1632 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1634 return list4 (make_int (left),
1640 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1641 Return current value of point in WINDOW.
1642 For a non-selected window, this is the value point would have
1643 if that window were selected.
1645 Note that, when WINDOW is the selected window and its buffer
1646 is also currently selected, the value returned is the same as (point).
1647 It would be more strictly correct to return the `top-level' value
1648 of point, outside of any save-excursion forms.
1649 But that is hard to define.
1653 struct window *w = decode_window (window);
1655 /* The special check for current buffer is necessary for this
1656 function to work as defined when called within an excursion. */
1657 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1658 && current_buffer == XBUFFER (w->buffer))
1659 return Fpoint (Qnil);
1660 return Fmarker_position (w->pointm[CURRENT_DISP]);
1663 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1664 Return position at which display currently starts in WINDOW.
1665 This is updated by redisplay or by calling `set-window-start'.
1669 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1672 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1673 Return position at which display currently ends in WINDOW.
1674 This is updated by redisplay, when it runs to completion.
1675 Simply changing the buffer text or setting `window-start'
1676 does not update this value.
1677 If GUARANTEE is non-nil, then the return value is guaranteed to be
1678 the value of window-end at the end of the next full redisplay assuming
1679 nothing else changes in the meantime. This function is potentially much
1680 slower with this flag set.
1682 (window, guarantee))
1684 struct window *w = decode_window (window);
1686 if (NILP (guarantee))
1691 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1695 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1696 return make_int (end_of_last_line (w, startp));
1700 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1701 Return pixel height of visible part of last window line if it is clipped.
1702 If the last line is not clipped, return nil.
1706 struct window *w = decode_window (window);
1707 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1708 int num_lines = Dynarr_length (dla);
1709 struct display_line *dl;
1711 /* No lines - no clipped lines */
1712 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
1715 dl = Dynarr_atp (dla, num_lines - 1);
1719 return make_int (dl->ascent + dl->descent - dl->clip);
1722 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1723 Make point value in WINDOW be at position POS in WINDOW's buffer.
1727 struct window *w = decode_window (window);
1729 CHECK_INT_COERCE_MARKER (pos);
1730 if (w == XWINDOW (Fselected_window (Qnil)))
1731 Fgoto_char (pos, Qnil);
1733 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1739 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1740 Make display in WINDOW start at position POS in WINDOW's buffer.
1741 Optional third arg NOFORCE non-nil inhibits next redisplay
1742 from overriding motion of point in order to display at this exact start.
1744 (window, pos, noforce))
1746 struct window *w = decode_window (window);
1748 CHECK_INT_COERCE_MARKER (pos);
1749 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1750 /* this is not right, but much easier than doing what is right. */
1751 /* w->start_at_line_beg = 0; */
1752 /* WTF is the above supposed to mean? GE */
1753 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1754 marker_position (w->start[CURRENT_DISP]));
1757 w->redo_modeline = 1;
1758 SET_LAST_MODIFIED (w, 0);
1759 SET_LAST_FACECHANGE (w);
1761 MARK_WINDOWS_CHANGED (w);
1766 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1767 Return WINDOW's dedicated object, usually t or nil.
1768 See also `set-window-dedicated-p'.
1772 return decode_window (window)->dedicated;
1775 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1776 Control whether WINDOW is dedicated to the buffer it displays.
1777 If it is dedicated, Emacs will not automatically change
1778 which buffer appears in it.
1779 The second argument is the new value for the dedication flag;
1784 struct window *w = decode_window (window);
1786 w->dedicated = NILP (arg) ? Qnil : Qt;
1788 return w->dedicated;
1791 /* FSFmacs has window-display-table here. We have display table as a
1795 /* Record info on buffer window w is displaying
1796 when it is about to cease to display that buffer. */
1798 unshow_buffer (struct window *w)
1800 Lisp_Object buf = w->buffer;
1802 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1805 /* FSF disables this check, so I'll do it too. I hope it won't
1806 break things. --ben */
1808 if (w == XWINDOW (Fselected_window (Qnil))
1809 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1810 /* Do this except when the selected window's buffer
1811 is being removed from some other window. */
1813 /* last_window_start records the start position that this buffer
1814 had in the last window to be disconnected from it.
1815 Now that this statement is unconditional,
1816 it is possible for the buffer to be displayed in the
1817 selected window, while last_window_start reflects another
1818 window which was recently showing the same buffer.
1819 Some people might say that might be a good thing. Let's see. */
1820 XBUFFER (buf)->last_window_start =
1821 marker_position (w->start[CURRENT_DISP]);
1823 /* Point in the selected window's buffer
1824 is actually stored in that buffer, and the window's pointm isn't used.
1825 So don't clobber point in that buffer. */
1826 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1828 struct buffer *b= XBUFFER (buf);
1829 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1830 marker_position (w->pointm[CURRENT_DISP]),
1835 /* Put REPLACEMENT into the window structure in place of OLD. */
1837 replace_window (Lisp_Object old, Lisp_Object replacement)
1840 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1842 /* If OLD is its frame's root_window, then replacement is the new
1843 root_window for that frame. */
1845 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1846 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1848 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1849 WINDOW_TOP (p) = WINDOW_TOP (o);
1850 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1851 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1853 p->next = tem = o->next;
1855 XWINDOW (tem)->prev = replacement;
1857 p->prev = tem = o->prev;
1859 XWINDOW (tem)->next = replacement;
1861 p->parent = tem = o->parent;
1864 if (EQ (XWINDOW (tem)->vchild, old))
1865 XWINDOW (tem)->vchild = replacement;
1866 if (EQ (XWINDOW (tem)->hchild, old))
1867 XWINDOW (tem)->hchild = replacement;
1870 /* #### Here, if replacement is a vertical combination
1871 and so is its new parent, we should make replacement's
1872 children be children of that parent instead. */
1874 ERROR_CHECK_SUBWINDOW_CACHE (p);
1878 window_unmap_subwindows (struct window* w)
1880 assert (!NILP (w->subwindow_instance_cache));
1881 elisp_maphash (unmap_subwindow_instance_cache_mapper,
1882 w->subwindow_instance_cache, (void*)1);
1885 /* we're deleting W; set the structure of W to indicate this. */
1888 mark_window_as_deleted (struct window *w)
1890 /* The window instance cache is going away now, so need to get the
1891 cachels reset by redisplay. */
1892 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
1894 /* The cache is going away. If we leave unmapping to
1895 reset_subwindow_cachels then we get in a situation where the
1896 domain (the window) has been deleted but we still need access to
1897 its attributes in order to unmap windows properly. Since the
1898 subwindows are going to get GC'd anyway as a result of the domain
1899 going away, it is safer to just unmap them all while we know the
1900 domain is still valid. */
1901 ERROR_CHECK_SUBWINDOW_CACHE (w);
1902 window_unmap_subwindows (w);
1905 (while t (split-window) (delete-window))
1906 we end up with a tree of deleted windows which are all connected
1907 through the `next' slot. This might not seem so bad, as they're
1908 deleted, and will presumably be GCed - but if even *one* of those
1909 windows is still being pointed to, by the user, or by a window
1910 configuration, then *all* of those windows stick around.
1912 Since the window-configuration code doesn't need any of the
1913 pointers to other windows (they are all recreated from the
1914 window-config data), we set them all to nil so that we
1915 are able to collect more actual garbage. */
1921 w->subwindow_instance_cache = Qnil;
1925 /* Free the extra data structures attached to windows immediately so
1926 they don't sit around consuming excess space. They will be
1927 reinitialized by the window-configuration code as necessary. */
1928 finalize_window ((void *) w, 0);
1931 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1932 Remove WINDOW from the display. Default is selected window.
1933 If window is the only one on the frame, the frame is destroyed.
1934 Normally, you cannot delete the last non-minibuffer-only frame (you must
1935 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1936 second argument FORCE is non-nil, you can delete the last frame. (This
1937 will automatically call `save-buffers-kill-emacs'.)
1941 /* This function can GC if this is the only window in the frame */
1949 /* Note: this function is called by other C code on non-leaf
1952 /* Do the equivalent of decode_window() but don't error out on
1953 deleted window; it's OK to delete an already-deleted window. */
1955 window = Fselected_window (Qnil);
1957 CHECK_WINDOW (window);
1959 w = XWINDOW (window);
1961 /* It's okay to delete an already-deleted window. */
1962 if (! WINDOW_LIVE_P (w))
1965 frame = WINDOW_FRAME (w);
1967 d = XDEVICE (FRAME_DEVICE (f));
1969 if (TOP_LEVEL_WINDOW_P (w))
1971 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1972 /* this frame isn't fully initialized yet; don't blow up. */
1975 if (MINI_WINDOW_P (XWINDOW (window)))
1976 error ("Attempt to delete the minibuffer window");
1978 /* It has been suggested that it's a good thing for C-x 0 to have this
1979 behavior, but not such a good idea for #'delete-window to have it.
1980 Maybe C-x 0 should be bound to something else, or maybe frame
1981 deletion should only happen when this is called interactively.
1983 delete_frame_internal (f, !NILP (force), 0, 0);
1987 /* At this point, we know the window has a parent. */
1989 par = XWINDOW (parent);
1991 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1992 /* It's quite likely that deleting a window will result in
1993 subwindows needing to be deleted also (since they are cached
1994 per-window). So we mark them as changed, so that the cachels will
1995 get reset by redisplay and thus deleted subwindows can get
1997 MARK_FRAME_SUBWINDOWS_CHANGED (f);
1999 /* Are we trying to delete any frame's selected window?
2000 Note that we could be dealing with a non-leaf window
2001 where the selected window is one of our children.
2002 So, we check by scanning all the ancestors of the
2003 frame's selected window and comparing each one with
2006 Lisp_Object pwindow;
2008 pwindow = FRAME_SELECTED_WINDOW (f);
2010 while (!NILP (pwindow))
2012 if (EQ (window, pwindow))
2014 pwindow = XWINDOW (pwindow)->parent;
2017 if (EQ (window, pwindow))
2019 /* OK, we found it. */
2020 Lisp_Object alternative;
2021 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
2023 /* If we're about to delete the selected window on the
2024 selected frame, then we should use Fselect_window to select
2025 the new window. On the other hand, if we're about to
2026 delete the selected window on any other frame, we shouldn't do
2027 anything but set the frame's selected_window slot. */
2028 if (EQ (frame, Fselected_frame (Qnil)))
2029 Fselect_window (alternative, Qnil);
2031 set_frame_selected_window (f, alternative);
2035 /* w->buffer is nil in a non-leaf window; in this case,
2036 get rid of the markers we maintain that point into that buffer. */
2037 if (!NILP (w->buffer))
2040 unchain_marker (w->pointm[CURRENT_DISP]);
2041 unchain_marker (w->pointm[DESIRED_DISP]);
2042 unchain_marker (w->pointm[CMOTION_DISP]);
2043 unchain_marker (w->start[CURRENT_DISP]);
2044 unchain_marker (w->start[DESIRED_DISP]);
2045 unchain_marker (w->start[CMOTION_DISP]);
2046 unchain_marker (w->sb_point);
2047 /* This breaks set-window-configuration if windows in the saved
2048 configuration get deleted and multiple frames are in use. */
2049 /* w->buffer = Qnil; */
2052 /* close up the hole in the sibling list */
2053 if (!NILP (w->next))
2054 XWINDOW (w->next)->prev = w->prev;
2055 if (!NILP (w->prev))
2056 XWINDOW (w->prev)->next = w->next;
2057 if (EQ (window, par->hchild))
2058 par->hchild = w->next;
2059 if (EQ (window, par->vchild))
2060 par->vchild = w->next;
2062 /* Find one of our siblings to give our space to. */
2064 Lisp_Object sib = w->prev;
2067 /* If w gives its space to its next sibling, that sibling needs
2068 to have its top/left side pulled back to where w's is.
2069 set_window_{height,width} will re-position the sibling's
2072 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
2073 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
2076 /* Stretch that sibling. */
2077 if (!NILP (par->vchild))
2078 set_window_pixheight
2079 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
2080 if (!NILP (par->hchild))
2082 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
2085 /* If parent now has only one child,
2086 put the child into the parent's place. */
2088 Lisp_Object parchild = par->hchild;
2089 if (NILP (parchild))
2090 parchild = par->vchild;
2091 if (NILP (XWINDOW (parchild)->next))
2093 replace_window (parent, parchild);
2094 mark_window_as_deleted (XWINDOW (parent));
2098 /* Since we may be deleting combination windows, we must make sure that
2099 not only W but all its children have been marked as deleted. */
2100 if (!NILP (w->hchild))
2101 delete_all_subwindows (XWINDOW (w->hchild));
2102 else if (!NILP (w->vchild))
2103 delete_all_subwindows (XWINDOW (w->vchild));
2105 mark_window_as_deleted (w);
2107 f->mirror_dirty = 1;
2112 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2113 Return the next window after WINDOW in the canonical ordering of windows.
2114 If omitted, WINDOW defaults to the selected window.
2116 Optional second arg MINIBUF t means count the minibuffer window even
2117 if not active. MINIBUF nil or omitted means count the minibuffer iff
2118 it is active. MINIBUF neither t nor nil means not to count the
2119 minibuffer even if it is active.
2121 Several frames may share a single minibuffer; if the minibuffer
2122 counts, all windows on all frames that share that minibuffer count
2123 too. Therefore, `next-window' can be used to iterate through the
2124 set of windows even when the minibuffer is on another frame. If the
2125 minibuffer does not count, only windows from WINDOW's frame count.
2127 Optional third arg ALL-FRAMES t means include windows on all frames.
2128 ALL-FRAMES nil or omitted means cycle within the frames as specified
2129 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2130 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2131 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2132 Anything else means restrict to WINDOW's frame.
2134 Optional fourth arg CONSOLE controls which consoles or devices the
2135 returned window may be on. If CONSOLE is a console, return windows only
2136 on that console. If CONSOLE is a device, return windows only on that
2137 device. If CONSOLE is a console type, return windows only on consoles
2138 of that type. If CONSOLE is 'window-system, return any windows on any
2139 window-system consoles. If CONSOLE is nil or omitted, return windows only
2140 on WINDOW's console. Otherwise, all windows are considered.
2142 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2143 can use `next-window' to iterate through the entire cycle of acceptable
2144 windows, eventually ending up back at the window you started with.
2145 `previous-window' traverses the same cycle, in the reverse order.
2147 (window, minibuf, all_frames, console))
2150 Lisp_Object start_window;
2153 window = Fselected_window (Qnil);
2155 CHECK_LIVE_WINDOW (window);
2157 start_window = window;
2159 /* minibuf == nil may or may not include minibuffers.
2160 Decide if it does. */
2162 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2163 else if (! EQ (minibuf, Qt))
2165 /* Now `minibuf' is one of:
2166 t => count all minibuffer windows
2167 lambda => count none of them
2168 or a specific minibuffer window (the active one) to count. */
2170 /* all_frames == nil doesn't specify which frames to include. */
2171 if (NILP (all_frames))
2172 all_frames = (! EQ (minibuf, Qlambda)
2173 ? (FRAME_MINIBUF_WINDOW
2176 (XWINDOW (window)))))
2178 else if (EQ (all_frames, Qvisible))
2180 else if (ZEROP (all_frames))
2182 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2183 /* If all_frames is a frame and window arg isn't on that frame, just
2184 return the first window on the frame. */
2185 return frame_first_window (XFRAME (all_frames));
2186 else if (! EQ (all_frames, Qt))
2188 /* Now `all_frames' is one of:
2189 t => search all frames
2190 nil => search just the current frame
2191 visible => search just visible frames
2192 0 => search visible and iconified frames
2193 a window => search the frame that window belongs to. */
2195 /* Do this loop at least once, to get the next window, and perhaps
2196 again, if we hit the minibuffer and that is not acceptable. */
2199 /* Find a window that actually has a next one. This loop
2200 climbs up the tree. */
2201 while (tem = XWINDOW (window)->next, NILP (tem))
2202 if (tem = XWINDOW (window)->parent, !NILP (tem))
2204 else /* window must be minibuffer window now */
2206 /* We've reached the end of this frame.
2207 Which other frames are acceptable? */
2208 tem = WINDOW_FRAME (XWINDOW (window));
2210 if (! NILP (all_frames))
2212 Lisp_Object tem1 = tem;
2213 tem = next_frame (tem, all_frames, console);
2215 /* In the case where the minibuffer is active,
2216 and we include its frame as well as the selected one,
2217 next_frame may get stuck in that frame.
2218 If that happens, go back to the selected frame
2219 so we can complete the cycle. */
2221 XSETFRAME (tem, selected_frame ());
2224 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2230 /* If we're in a combination window, find its first child and
2231 recurse on that. Otherwise, we've found the window we want. */
2234 if (!NILP (XWINDOW (window)->hchild))
2235 window = XWINDOW (window)->hchild;
2236 else if (!NILP (XWINDOW (window)->vchild))
2237 window = XWINDOW (window)->vchild;
2241 /* Which windows are acceptable?
2242 Exit the loop and accept this window if
2243 this isn't a minibuffer window,
2244 or we're accepting all minibuffer windows,
2245 or this is the active minibuffer and we are accepting that one, or
2246 we've come all the way around and we're back at the original window. */
2247 while (MINI_WINDOW_P (XWINDOW (window))
2248 && ! EQ (minibuf, Qt)
2249 && ! EQ (minibuf, window)
2250 && ! EQ (window, start_window));
2255 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2256 Return the window preceding WINDOW in the canonical ordering of windows.
2257 If omitted, WINDOW defaults to the selected window.
2259 Optional second arg MINIBUF t means count the minibuffer window even
2260 if not active. MINIBUF nil or omitted means count the minibuffer iff
2261 it is active. MINIBUF neither t nor nil means not to count the
2262 minibuffer even if it is active.
2264 Several frames may share a single minibuffer; if the minibuffer
2265 counts, all windows on all frames that share that minibuffer count
2266 too. Therefore, `previous-window' can be used to iterate through
2267 the set of windows even when the minibuffer is on another frame. If
2268 the minibuffer does not count, only windows from WINDOW's frame count.
2270 Optional third arg ALL-FRAMES t means include windows on all frames.
2271 ALL-FRAMES nil or omitted means cycle within the frames as specified
2272 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2273 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2274 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2275 Anything else means restrict to WINDOW's frame.
2277 Optional fourth arg CONSOLE controls which consoles or devices the
2278 returned window may be on. If CONSOLE is a console, return windows only
2279 on that console. If CONSOLE is a device, return windows only on that
2280 device. If CONSOLE is a console type, return windows only on consoles
2281 of that type. If CONSOLE is 'window-system, return any windows on any
2282 window-system consoles. If CONSOLE is nil or omitted, return windows only
2283 on WINDOW's console. Otherwise, all windows are considered.
2285 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2286 can use `previous-window' to iterate through the entire cycle of acceptable
2287 windows, eventually ending up back at the window you started with.
2288 `next-window' traverses the same cycle, in the reverse order.
2290 (window, minibuf, all_frames, console))
2293 Lisp_Object start_window;
2296 window = Fselected_window (Qnil);
2298 CHECK_LIVE_WINDOW (window);
2300 start_window = window;
2302 /* minibuf == nil may or may not include minibuffers.
2303 Decide if it does. */
2305 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2306 else if (! EQ (minibuf, Qt))
2308 /* Now `minibuf' is one of:
2309 t => count all minibuffer windows
2310 lambda => count none of them
2311 or a specific minibuffer window (the active one) to count. */
2313 /* all_frames == nil doesn't specify which frames to include.
2314 Decide which frames it includes. */
2315 if (NILP (all_frames))
2316 all_frames = (! EQ (minibuf, Qlambda)
2317 ? (FRAME_MINIBUF_WINDOW
2320 (XWINDOW (window)))))
2322 else if (EQ (all_frames, Qvisible))
2324 else if (ZEROP (all_frames))
2326 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2327 /* If all_frames is a frame and window arg isn't on that frame, just
2328 return the first window on the frame. */
2329 return frame_first_window (XFRAME (all_frames));
2330 else if (! EQ (all_frames, Qt))
2332 /* Now `all_frames' is one of:
2333 t => search all frames
2334 nil => search just the current frame
2335 visible => search just visible frames
2336 0 => search visible and iconified frames
2337 a window => search the frame that window belongs to. */
2339 /* Do this loop at least once, to get the next window, and perhaps
2340 again, if we hit the minibuffer and that is not acceptable. */
2343 /* Find a window that actually has a next one. This loop
2344 climbs up the tree. */
2345 while (tem = XWINDOW (window)->prev, NILP (tem))
2346 if (tem = XWINDOW (window)->parent, !NILP (tem))
2348 else /* window must be minibuffer window now */
2350 /* We have found the top window on the frame.
2351 Which frames are acceptable? */
2352 tem = WINDOW_FRAME (XWINDOW (window));
2354 if (! NILP (all_frames))
2355 /* It's actually important that we use previous_frame here,
2356 rather than next_frame. All the windows acceptable
2357 according to the given parameters should form a ring;
2358 Fnext_window and Fprevious_window should go back and
2359 forth around the ring. If we use next_frame here,
2360 then Fnext_window and Fprevious_window take different
2361 paths through the set of acceptable windows.
2362 window_loop assumes that these `ring' requirement are
2365 Lisp_Object tem1 = tem;
2366 tem = previous_frame (tem, all_frames, console);
2367 /* In the case where the minibuffer is active,
2368 and we include its frame as well as the selected one,
2369 next_frame may get stuck in that frame.
2370 If that happens, go back to the selected frame
2371 so we can complete the cycle. */
2373 XSETFRAME (tem, selected_frame ());
2376 /* If this frame has a minibuffer, find that window first,
2377 because it is conceptually the last window in that frame. */
2378 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2379 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2381 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2388 /* If we're in a combination window, find its first child and
2389 recurse on that. Otherwise, we've found the window we want. */
2392 if (!NILP (XWINDOW (window)->hchild))
2393 window = XWINDOW (window)->hchild;
2394 else if (!NILP (XWINDOW (window)->vchild))
2395 window = XWINDOW (window)->vchild;
2397 while (tem = XWINDOW (window)->next, !NILP (tem))
2401 /* Which windows are acceptable?
2402 Exit the loop and accept this window if
2403 this isn't a minibuffer window,
2404 or we're accepting all minibuffer windows,
2405 or this is the active minibuffer and we are accepting that one, or
2406 we've come all the way around and we're back at the original window. */
2407 while (MINI_WINDOW_P (XWINDOW (window))
2408 && ! EQ (minibuf, Qt)
2409 && ! EQ (minibuf, window)
2410 && ! EQ (window, start_window));
2415 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2416 Return the next window which is vertically after WINDOW.
2421 struct window *w = decode_window (window);
2422 XSETWINDOW (window, w);
2424 if (MINI_WINDOW_P (XWINDOW (window)))
2427 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2429 if (EQ (window, root))
2432 if (!NILP (XWINDOW (window)->hchild))
2433 window = XWINDOW (window)->hchild;
2434 else if (!NILP (XWINDOW (window)->vchild))
2435 window = XWINDOW (window)->vchild;
2442 if (!NILP (XWINDOW (window)->parent) &&
2443 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2445 if (!NILP (XWINDOW (window)->next))
2446 return XWINDOW (window)->next;
2448 window = XWINDOW (window)->parent;
2451 window = XWINDOW (window)->parent;
2453 while (!EQ (window, root));
2456 if (!NILP (XWINDOW (window)->hchild))
2457 window = XWINDOW (window)->hchild;
2458 else if (!NILP (XWINDOW (window)->vchild))
2459 window = XWINDOW (window)->vchild;
2464 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2465 Select the N'th different window on this frame.
2466 All windows on current frame are arranged in a cyclic order.
2467 This command selects the window N steps away in that order.
2468 A negative N moves in the opposite order.
2470 If optional argument FRAME is `visible', search all visible frames.
2471 If FRAME is 0, search all visible and iconified frames.
2472 If FRAME is t, search all frames.
2473 If FRAME is nil, search only the selected frame.
2474 If FRAME is a frame, search only that frame.
2476 Optional third argument CONSOLE controls which consoles or devices the
2477 returned window may be on. If CONSOLE is a console, return windows only
2478 on that console. If CONSOLE is a device, return windows only on that
2479 device. If CONSOLE is a console type, return windows only on consoles
2480 of that type. If CONSOLE is 'window-system, return any windows on any
2481 window-system consoles. If CONSOLE is nil or omitted, return windows only
2482 on FRAME'S console, or on the selected console if FRAME is not a frame.
2483 Otherwise, all windows are considered.
2485 (n, frame, console))
2491 w = Fselected_window (Qnil);
2496 w = Fnext_window (w, Qnil, frame, console);
2501 w = Fprevious_window (w, Qnil, frame, console);
2504 Fselect_window (w, Qnil);
2509 /* Look at all windows, performing an operation specified by TYPE
2512 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2513 frame. If FRAMES is a frame, just look at windows on that frame.
2514 If MINI is non-zero, perform the operation on minibuffer windows too.
2520 GET_BUFFER_WINDOW, /* Arg is buffer */
2521 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2522 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2523 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2525 UNSHOW_BUFFER, /* Arg is buffer */
2526 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2527 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2531 window_loop (enum window_loop type,
2536 Lisp_Object console)
2538 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2540 Lisp_Object best_window = Qnil;
2541 Lisp_Object next_window;
2542 Lisp_Object last_window;
2543 struct frame *frame;
2544 Lisp_Object frame_arg = Qt;
2545 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2546 /* #### I think the change of "precomputing" last_window and next_window
2547 * #### catch the lossage this is meant(?) to punt on...
2550 Lisp_Object devcons, concons;
2552 /* If we're only looping through windows on a particular frame,
2553 FRAME points to that frame. If we're looping through windows
2554 on all frames, FRAME is 0. */
2555 if (FRAMEP (frames))
2556 frame = XFRAME (frames);
2557 else if (NILP (frames))
2558 frame = selected_frame ();
2562 /* FRAME_ARG is Qlambda to stick to one frame,
2563 Qvisible to consider all visible frames,
2566 frame_arg = Qlambda;
2567 else if (ZEROP (frames))
2569 else if (EQ (frames, Qvisible))
2572 DEVICE_LOOP_NO_BREAK (devcons, concons)
2574 Lisp_Object device = XCAR (devcons);
2575 Lisp_Object the_frame;
2578 XSETFRAME (the_frame, frame);
2580 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2582 if (NILP (the_frame))
2585 if (!device_matches_console_spec (device,
2587 FRAME_CONSOLE (XFRAME (the_frame)) :
2591 /* Pick a window to start with. */
2595 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2597 /* Figure out the last window we're going to mess with. Since
2598 Fnext_window, given the same options, is guaranteed to go in a
2599 ring, we can just use Fprevious_window to find the last one.
2601 We can't just wait until we hit the first window again,
2602 because it might be deleted. */
2604 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2609 struct window *p = XWINDOW (w);
2610 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2612 /* Pick the next window now, since some operations will delete
2613 the current window. */
2614 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
2616 /* #### Still needed ?? */
2617 /* Given the outstanding quality of the rest of this code,
2618 I feel no shame about putting this piece of shit in. */
2619 if (++lose_lose >= 500)
2622 /* Note that we do not pay attention here to whether
2623 the frame is visible, since Fnext_window skips non-visible frames
2624 if that is desired, under the control of frame_arg. */
2625 if (! MINI_WINDOW_P (p)
2626 || (mini && minibuf_level > 0))
2629 case GET_BUFFER_WINDOW:
2631 if (XBUFFER (p->buffer) == XBUFFER (obj))
2636 case GET_BUFFER_WINDOW_COUNT:
2638 if (XBUFFER (p->buffer) == XBUFFER (obj))
2643 case GET_LRU_WINDOW:
2645 /* t as arg means consider only full-width windows */
2647 && !window_full_width_p (p))
2649 /* Ignore dedicated windows and minibuffers. */
2650 if (MINI_WINDOW_P (p)
2651 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2653 if (NILP (best_window)
2654 || (XINT (XWINDOW (best_window)->use_time)
2655 > XINT (p->use_time)))
2660 case GET_BUFFER_MRU_WINDOW:
2662 /* #### what about the first check in GET_LRU_WINDOW? */
2663 /* Ignore dedicated windows and minibuffers. */
2664 if (MINI_WINDOW_P (p)
2665 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2668 if (XBUFFER (p->buffer) == XBUFFER (obj))
2670 if (NILP (best_window)
2671 || (XINT (XWINDOW (best_window)->use_time)
2672 < XINT (p->use_time)))
2678 case DELETE_OTHER_WINDOWS:
2680 /* Don't delete the last window on a frame; this can
2681 happen when the minibuffer is selected, and would
2682 cause the frame to be deleted. */
2683 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2684 Fdelete_window (w, Qnil);
2688 case DELETE_BUFFER_WINDOWS:
2690 if (EQ (p->buffer, obj))
2692 struct frame *f = XFRAME (WINDOW_FRAME (p));
2694 /* If this window is dedicated, and in a frame
2695 of its own, kill the frame. */
2696 if (EQ (w, FRAME_ROOT_WINDOW (f))
2697 && !NILP (p->dedicated)
2698 && other_visible_frames (f))
2700 /* Skip the other windows on this frame.
2701 There might be one, the minibuffer! */
2702 if (! EQ (w, last_window))
2703 while (f == XFRAME (WINDOW_FRAME
2704 (XWINDOW (next_window))))
2706 /* As we go, check for the end of the
2707 loop. We mustn't start going
2708 around a second time. */
2709 if (EQ (next_window, last_window))
2714 next_window = Fnext_window (next_window,
2718 /* Now we can safely delete the frame. */
2719 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2722 /* If we're deleting the buffer displayed in
2723 the only window on the frame, find a new
2724 buffer to display there. */
2725 if (NILP (p->parent))
2727 Lisp_Object new_buffer;
2728 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2729 if (NILP (new_buffer))
2730 new_buffer = Fget_buffer_create (QSscratch);
2731 Fset_window_buffer (w, new_buffer, Qnil);
2732 if (EQ (w, Fselected_window (Qnil)))
2733 Fset_buffer (p->buffer);
2736 Fdelete_window (w, Qnil);
2741 case GET_LARGEST_WINDOW:
2743 /* Ignore dedicated windows and minibuffers. */
2744 if (MINI_WINDOW_P (p)
2745 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2748 /* write the check as follows to avoid tripping
2749 error_check_window() --ben */
2750 struct window *b = NILP (best_window) ? 0 :
2751 XWINDOW (best_window);
2752 if (NILP (best_window)
2753 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2754 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2762 if (EQ (p->buffer, obj))
2764 /* Find another buffer to show in this window. */
2765 Lisp_Object another_buffer =
2766 Fother_buffer (obj, Qnil, Qnil);
2767 if (NILP (another_buffer))
2769 = Fget_buffer_create (QSscratch);
2770 /* If this window is dedicated, and in a frame
2771 of its own, kill the frame. */
2772 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2773 && !NILP (p->dedicated)
2774 && other_visible_frames (w_frame))
2776 /* Skip the other windows on this frame.
2777 There might be one, the minibuffer! */
2778 if (! EQ (w, last_window))
2779 while (w_frame == XFRAME (WINDOW_FRAME
2780 (XWINDOW (next_window))))
2782 /* As we go, check for the end of the
2783 loop. We mustn't start going
2784 around a second time. */
2785 if (EQ (next_window, last_window))
2790 next_window = Fnext_window (next_window,
2794 /* Now we can safely delete the frame. */
2795 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2800 /* Otherwise show a different buffer in the
2802 p->dedicated = Qnil;
2803 Fset_window_buffer (w, another_buffer, Qnil);
2804 if (EQ (w, Fselected_window (Qnil)))
2805 Fset_buffer (p->buffer);
2815 if (EQ (w, last_window))
2822 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2825 #if 0 /* not currently used */
2828 buffer_window_count (struct buffer *b, struct frame *f)
2830 Lisp_Object buffer, frame;
2832 XSETFRAME (frame, f);
2833 XSETBUFFER (buffer, b);
2835 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2840 buffer_window_mru (struct window *w)
2842 Lisp_Object window =
2843 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2847 else if (XWINDOW (window) == w)
2856 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2857 Return the window least recently selected or used for display.
2858 If optional argument FRAME is `visible', search all visible frames.
2859 If FRAME is 0, search all visible and iconified frames.
2860 If FRAME is t, search all frames.
2861 If FRAME is nil, search only the selected frame.
2862 If FRAME is a frame, search only that frame.
2864 Optional second argument CONSOLE controls which consoles or devices the
2865 returned window may be on. If CONSOLE is a console, return windows only
2866 on that console. If CONSOLE is a device, return windows only on that
2867 device. If CONSOLE is a console type, return windows only on consoles
2868 of that type. If CONSOLE is 'window-system, return any windows on any
2869 window-system consoles. If CONSOLE is nil or omitted, return windows only
2870 on FRAME'S console, or on the selected console if FRAME is not a frame.
2871 Otherwise, all windows are considered.
2876 /* First try for a non-dedicated window that is full-width */
2877 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2878 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2881 /* Then try for any non-dedicated window */
2882 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2883 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2887 /* FSFmacs never returns a dedicated window here. If we do,
2888 it makes `display-buffer' not work right. #### All of this
2889 shit is so disgusting and awful that it needs to be rethought
2891 /* then try for a dedicated window that is full-width */
2892 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2893 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2896 /* If none of them, then all windows, dedicated or not. */
2897 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2899 /* At this point we damn well better have found something. */
2900 if (NILP (w)) abort ();
2906 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2907 Return the window largest in area.
2908 If optional argument FRAME is `visible', search all visible frames.
2909 If FRAME is 0, search all visible and iconified frames.
2910 If FRAME is t, search all frames.
2911 If FRAME is nil, search only the selected frame.
2912 If FRAME is a frame, search only that frame.
2914 Optional second argument CONSOLE controls which consoles or devices the
2915 returned window may be on. If CONSOLE is a console, return windows only
2916 on that console. If CONSOLE is a device, return windows only on that
2917 device. If CONSOLE is a console type, return windows only on consoles
2918 of that type. If CONSOLE is 'window-system, return any windows on any
2919 window-system consoles. If CONSOLE is nil or omitted, return windows only
2920 on FRAME'S console, or on the selected console if FRAME is not a frame.
2921 Otherwise, all windows are considered.
2925 /* Don't search dedicated windows because FSFmacs doesn't.
2926 This stuff is all black magic so don't try to apply common
2928 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2931 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2932 Return a window currently displaying BUFFER, or nil if none.
2933 If optional argument FRAME is `visible', search all visible frames.
2934 If optional argument FRAME is 0, search all visible and iconified frames.
2935 If FRAME is t, search all frames.
2936 If FRAME is nil, search only the selected frame.
2937 If FRAME is a frame, search only that frame.
2939 Optional third argument CONSOLE controls which consoles or devices the
2940 returned window may be on. If CONSOLE is a console, return windows only
2941 on that console. If CONSOLE is a device, return windows only on that
2942 device. If CONSOLE is a console type, return windows only on consoles
2943 of that type. If CONSOLE is 'window-system, return any windows on any
2944 window-system consoles. If CONSOLE is nil or omitted, return windows only
2945 on FRAME'S console, or on the selected console if FRAME is not a frame.
2946 Otherwise, all windows are considered.
2948 (buffer, frame, console))
2950 buffer = Fget_buffer (buffer);
2951 if (BUFFERP (buffer))
2952 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2953 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2958 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2959 but there is no sensible way to implement those functions, since
2960 you can't in general derive a window from a buffer. */
2962 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2964 Return the width in pixels of the left outside margin of window WINDOW.
2965 If WINDOW is nil, the selected window is assumed.
2969 return make_int (window_left_margin_width (decode_window (window)));
2972 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2974 Return the width in pixels of the right outside margin of window WINDOW.
2975 If WINDOW is nil, the selected window is assumed.
2979 return make_int (window_right_margin_width (decode_window (window)));
2982 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2983 Make WINDOW (or the selected window) fill its frame.
2984 Only the frame WINDOW is on is affected.
2985 This function tries to reduce display jumps
2986 by keeping the text previously visible in WINDOW
2987 in the same place on the frame. Doing this depends on
2988 the value of (window-start WINDOW), so if calling this function
2989 in a program gives strange scrolling, make sure the window-start
2990 value is reasonable when this function is called.
2994 struct window *w = decode_window (window);
2995 struct buffer *b = XBUFFER (w->buffer);
2997 int old_top = WINDOW_TOP (w);
2999 XSETWINDOW (window, w);
3001 if (MINI_WINDOW_P (w) && old_top > 0)
3002 error ("Can't expand minibuffer to full frame");
3004 /* Ignore dedicated windows. */
3005 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3007 start_pos = marker_position (w->start[CURRENT_DISP]);
3009 /* Try to minimize scrolling, by setting the window start to the
3010 point which will cause the text at the old window start to be at
3011 the same place on the frame. But don't try to do this if the
3012 window start is outside the visible portion (as might happen when
3013 the display is not current, due to typeahead). */
3014 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
3015 && !MINI_WINDOW_P (w))
3017 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
3019 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
3021 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
3023 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3025 /* We need to do this, so that the window-scroll-functions
3033 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3034 "bDelete windows on (buffer): ", /*
3035 Delete all windows showing BUFFER.
3036 Optional second argument FRAME controls which frames are affected.
3037 If nil or omitted, delete all windows showing BUFFER in any frame.
3038 If t, delete only windows showing BUFFER in the selected frame.
3039 If `visible', delete all windows showing BUFFER in any visible frame.
3040 If a frame, delete only windows showing BUFFER in that frame.
3042 Optional third argument CONSOLE controls which consoles or devices the
3043 returned window may be on. If CONSOLE is a console, return windows only
3044 on that console. If CONSOLE is a device, return windows only on that
3045 device. If CONSOLE is a console type, return windows only on consoles
3046 of that type. If CONSOLE is 'window-system, return any windows on any
3047 window-system consoles. If CONSOLE is nil or omitted, return windows only
3048 on FRAME'S console, or on the selected console if FRAME is not a frame.
3049 Otherwise, all windows are considered.
3051 (buffer, frame, console))
3053 /* This function can GC */
3054 /* FRAME uses t and nil to mean the opposite of what window_loop
3056 if (!FRAMEP (frame))
3057 frame = NILP (frame) ? Qt : Qnil;
3061 buffer = Fget_buffer (buffer);
3062 CHECK_BUFFER (buffer);
3063 /* Ignore dedicated windows. */
3064 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
3069 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
3070 "bReplace buffer in windows: ", /*
3071 Replace BUFFER with some other buffer in all windows showing it.
3075 /* This function can GC */
3078 buffer = Fget_buffer (buffer);
3079 CHECK_BUFFER (buffer);
3080 /* Ignore dedicated windows. */
3081 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
3086 /* The smallest acceptable dimensions for a window. Anything smaller
3087 might crash Emacs. */
3088 #define MIN_SAFE_WINDOW_WIDTH (2)
3089 #define MIN_SAFE_WINDOW_HEIGHT (2)
3091 /* Make sure that window_min_height and window_min_width are
3092 not too small; if they are, set them to safe minima. */
3095 check_min_window_sizes (void)
3097 /* Smaller values might permit a crash. */
3098 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3099 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3100 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3101 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3105 frame_min_height (struct frame *frame)
3107 /* For height, we have to see whether the frame has a minibuffer, and
3108 whether it wants a modeline. */
3109 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3110 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3111 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3114 /* Return non-zero if both frame sizes are less than or equal to
3115 minimal allowed values. ROWS and COLS are in characters */
3117 frame_size_valid_p (struct frame *frame, int rows, int cols)
3119 return (rows >= frame_min_height (frame)
3120 && cols >= MIN_SAFE_WINDOW_WIDTH);
3123 /* Return non-zero if both frame sizes are less than or equal to
3124 minimal allowed values. WIDTH and HEIGHT are in pixels */
3126 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3129 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3130 return frame_size_valid_p (frame, rows, cols);
3133 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3134 minimum allowable size. */
3136 check_frame_size (struct frame *frame, int *rows, int *cols)
3138 int min_height = frame_min_height (frame);
3140 if (*rows < min_height)
3142 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3143 *cols = MIN_SAFE_WINDOW_WIDTH;
3146 /* Normally the window is deleted if it gets too small.
3147 nodelete nonzero means do not do this.
3148 (The caller should check later and do so if appropriate) */
3150 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3153 struct window *w = XWINDOW (window);
3154 struct frame *f = XFRAME (w->frame);
3156 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3157 Lisp_Object child, minor_kid, major_kid;
3160 int defheight, defwidth;
3162 /* #### This is very likely incorrect and instead the char_to_pixel_
3163 functions should be called. */
3164 default_face_height_and_width (window, &defheight, &defwidth);
3165 line_size = (set_height ? defheight : defwidth);
3167 check_min_window_sizes ();
3169 minsize = (set_height ? window_min_height : window_min_width);
3170 minsize *= line_size;
3173 && !TOP_LEVEL_WINDOW_P (w)
3174 && new_pixsize < minsize)
3176 Fdelete_window (window, Qnil);
3180 SET_LAST_MODIFIED (w, 0);
3181 SET_LAST_FACECHANGE (w);
3182 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3185 WINDOW_HEIGHT (w) = new_pixsize;
3186 major_kid = w->vchild;
3187 minor_kid = w->hchild;
3191 WINDOW_WIDTH (w) = new_pixsize;
3192 major_kid = w->hchild;
3193 minor_kid = w->vchild;
3196 if (!NILP (minor_kid))
3198 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3201 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3203 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3205 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3208 else if (!NILP (major_kid))
3210 int last_pos, last_old_pos, pos, old_pos, first;
3211 int pixel_adj_left = new_pixsize - old_pixsize;
3212 int div_val = old_pixsize << 1;
3215 * Previously we bailed out here if there was no size change.
3216 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3217 * toolbar appears or disappears, windows may not change size,
3218 * but their top and left coordinates need to be updated.
3220 * So we don't bail until after the loop below.
3223 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3226 for (child = major_kid; !NILP (child); child = c->next)
3228 c = XWINDOW (child);
3232 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3233 WINDOW_TOP (c) = last_pos;
3237 old_pos = last_old_pos + WINDOW_WIDTH (c);
3238 WINDOW_LEFT (c) = last_pos;
3241 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3242 /* All but the last window should have a height which is
3243 a multiple of the default line height. */
3244 if (!NILP (c->next))
3245 pos = (pos / line_size) * line_size;
3247 /* Avoid confusion: don't delete child if it becomes too small */
3248 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3250 last_pos = pos + first;
3251 last_old_pos = old_pos;
3254 /* Sometimes we may get called with our old size. In that case
3255 we don't need to do anything else. */
3256 if (!pixel_adj_left)
3259 /* Now delete any children that became too small. */
3261 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3264 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3266 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3271 /* Set the height of WINDOW and all its inferiors. */
3273 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3275 set_window_pixsize (window, new_pixheight, nodelete, 1);
3278 /* Recursively set width of WINDOW and its inferiors. */
3280 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3282 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3286 static int window_select_count;
3288 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3289 Make WINDOW display BUFFER as its contents.
3290 BUFFER can be a buffer or buffer name.
3292 With non-nil optional argument NORECORD, do not modify the
3293 global or per-frame buffer ordering.
3295 (window, buffer, norecord))
3298 struct window *w = decode_window (window);
3300 buffer = Fget_buffer (buffer);
3301 CHECK_BUFFER (buffer);
3303 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3304 error ("Attempt to display deleted buffer");
3308 error ("Window is deleted");
3310 /* While this seems like a logical thing to do, it causes problems
3311 because of saved window configurations. It is possible for a
3312 buffer to get restored into a window in which it is already being
3313 displayed, but start and point are actually at completely
3314 different locations. So we let this function complete fully and
3315 it will then make sure redisplay correctly updates things.
3317 #### This is a kludge. The correct approach is not to do this
3318 but to fix set-window-configuration. */
3320 else if (EQ (tem, buffer))
3323 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3324 is first being set up. */
3326 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3327 error ("Window is dedicated to buffer %s",
3328 XSTRING_DATA (XBUFFER (tem)->name));
3334 w->window_end_pos[CURRENT_DISP] = 0;
3336 w->modeline_hscroll = 0;
3337 Fset_marker (w->pointm[CURRENT_DISP],
3338 make_int (BUF_PT (XBUFFER (buffer))),
3340 set_marker_restricted (w->start[CURRENT_DISP],
3341 make_int (XBUFFER (buffer)->last_window_start),
3343 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3344 /* set start_at_line_beg correctly. GE */
3345 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3346 marker_position (w->start[CURRENT_DISP]));
3347 w->force_start = 0; /* Lucid fix */
3348 SET_LAST_MODIFIED (w, 1);
3349 SET_LAST_FACECHANGE (w);
3350 MARK_WINDOWS_CHANGED (w);
3351 recompute_all_cached_specifiers_in_window (w);
3352 if (EQ (window, Fselected_window (Qnil)))
3354 if (NILP (norecord))
3355 Frecord_buffer (buffer);
3357 Fset_buffer (buffer);
3362 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3363 Select WINDOW. Most editing will apply to WINDOW's buffer.
3364 The main editor command loop selects the buffer of the selected window
3365 before each command.
3367 With non-nil optional argument NORECORD, do not modify the
3368 global or per-frame buffer ordering.
3373 Lisp_Object old_selected_window = Fselected_window (Qnil);
3375 CHECK_LIVE_WINDOW (window);
3376 w = XWINDOW (window);
3378 /* we have already caught dead-window errors */
3379 if (!NILP (w->hchild) || !NILP (w->vchild))
3380 error ("Trying to select non-leaf window");
3382 w->use_time = make_int (++window_select_count);
3384 if (EQ (window, old_selected_window))
3387 /* deselect the old window, if it exists (it might not exist if
3388 the selected device has no frames, which occurs at startup) */
3389 if (!NILP (old_selected_window))
3391 struct window *ow = XWINDOW (old_selected_window);
3393 Fset_marker (ow->pointm[CURRENT_DISP],
3394 make_int (BUF_PT (XBUFFER (ow->buffer))),
3397 MARK_WINDOWS_CHANGED (ow);
3400 /* now select the window's frame */
3401 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3403 select_frame_1 (WINDOW_FRAME (w));
3405 /* also select the window's buffer */
3406 if (NILP (norecord))
3407 Frecord_buffer (w->buffer);
3408 Fset_buffer (w->buffer);
3410 /* Go to the point recorded in the window.
3411 This is important when the buffer is in more
3412 than one window. It also matters when
3413 redisplay_window has altered point after scrolling,
3414 because it makes the change only in the window. */
3416 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3417 if (new_point < BUF_BEGV (current_buffer))
3418 new_point = BUF_BEGV (current_buffer);
3419 else if (new_point > BUF_ZV (current_buffer))
3420 new_point = BUF_ZV (current_buffer);
3422 BUF_SET_PT (current_buffer, new_point);
3425 MARK_WINDOWS_CHANGED (w);
3431 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3432 Lisp_Object override_frame)
3434 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3438 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3440 /* This function can GC */
3443 struct buffer *b = XBUFFER (buf);
3445 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3446 widen_buffer (b, 0);
3447 BUF_SET_PT (b, BUF_BEG (b));
3449 if (!NILP (Vtemp_buffer_show_function))
3450 call1 (Vtemp_buffer_show_function, buf);
3453 window = display_buffer (buf, Qnil, same_frame);
3455 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3456 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3458 Vminibuffer_scroll_window = window;
3459 w = XWINDOW (window);
3461 w->modeline_hscroll = 0;
3462 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3463 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3464 set_marker_restricted (w->sb_point, make_int (1), buf);
3466 /* Run temp-buffer-show-hook, with the chosen window selected. */
3467 if (!preparing_for_armageddon)
3470 tem = Fboundp (Qtemp_buffer_show_hook);
3473 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3476 int count = specpdl_depth ();
3478 /* Select the window that was chosen, for running
3480 record_unwind_protect (save_window_excursion_unwind,
3481 Fcurrent_window_configuration (Qnil));
3483 Fselect_window (window, Qnil);
3484 run_hook (Qtemp_buffer_show_hook);
3485 unbind_to (count, Qnil);
3493 make_dummy_parent (Lisp_Object window)
3496 struct window *o = XWINDOW (window);
3497 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3499 XSETWINDOW (new, p);
3500 copy_lcrecord (p, o);
3502 /* Don't copy the pointers to the line start cache or the face
3504 p->line_start_cache = Dynarr_new (line_start_cache);
3505 p->face_cachels = Dynarr_new (face_cachel);
3506 p->glyph_cachels = Dynarr_new (glyph_cachel);
3507 p->subwindow_instance_cache =
3508 make_lisp_hash_table (30,
3509 HASH_TABLE_KEY_VALUE_WEAK,
3512 /* Put new into window structure in place of window */
3513 replace_window (window, new);
3521 p->start[CURRENT_DISP] = Qnil;
3522 p->start[DESIRED_DISP] = Qnil;
3523 p->start[CMOTION_DISP] = Qnil;
3524 p->pointm[CURRENT_DISP] = Qnil;
3525 p->pointm[DESIRED_DISP] = Qnil;
3526 p->pointm[CMOTION_DISP] = Qnil;
3531 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3532 Split WINDOW, putting SIZE lines in the first of the pair.
3533 WINDOW defaults to selected one and SIZE to half its size.
3534 If optional third arg HORFLAG is non-nil, split side by side
3535 and put SIZE columns in the first of the pair.
3537 (window, chsize, horflag))
3540 struct window *o, *p;
3546 window = Fselected_window (Qnil);
3548 CHECK_LIVE_WINDOW (window);
3550 o = XWINDOW (window);
3551 f = XFRAME (WINDOW_FRAME (o));
3555 if (!NILP (horflag))
3556 /* In the new scheme, we are symmetric with respect to separators
3557 so there is no need to do weird things here. */
3559 psize = WINDOW_WIDTH (o) >> 1;
3560 size = window_pixel_width_to_char_width (o, psize, 0);
3564 psize = WINDOW_HEIGHT (o) >> 1;
3565 size = window_pixel_height_to_char_height (o, psize, 1);
3571 size = XINT (chsize);
3572 if (!NILP (horflag))
3573 psize = window_char_width_to_pixel_width (o, size, 0);
3575 psize = window_char_height_to_pixel_height (o, size, 1);
3578 if (MINI_WINDOW_P (o))
3579 error ("Attempt to split minibuffer window");
3580 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3581 error ("Attempt to split unsplittable frame");
3583 check_min_window_sizes ();
3587 if (size < window_min_height)
3588 error ("Window height %d too small (after splitting)", size);
3589 if (size + window_min_height > window_char_height (o, 1))
3590 error ("Window height %d too small (after splitting)",
3591 window_char_height (o, 1) - size);
3592 if (NILP (o->parent)
3593 || NILP (XWINDOW (o->parent)->vchild))
3595 make_dummy_parent (window);
3596 reset_face_cachels (XWINDOW (window));
3598 XWINDOW (new)->vchild = window;
3599 XFRAME (o->frame)->mirror_dirty = 1;
3604 if (size < window_min_width)
3605 error ("Window width %d too small (after splitting)", size);
3606 if (size + window_min_width > window_char_width (o, 0))
3607 error ("Window width %d too small (after splitting)",
3608 window_char_width (o, 0) - size);
3609 if (NILP (o->parent)
3610 || NILP (XWINDOW (o->parent)->hchild))
3612 make_dummy_parent (window);
3613 reset_face_cachels (XWINDOW (window));
3615 XWINDOW (new)->hchild = window;
3616 XFRAME (o->frame)->mirror_dirty = 1;
3620 /* Now we know that window's parent is a vertical combination
3621 if we are dividing vertically, or a horizontal combination
3622 if we are making side-by-side windows */
3624 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3625 new = allocate_window ();
3628 p->frame = o->frame;
3630 if (!NILP (p->next))
3631 XWINDOW (p->next)->prev = new;
3634 p->parent = o->parent;
3637 reset_face_cachels (p);
3638 reset_glyph_cachels (p);
3641 /* Apportion the available frame space among the two new windows */
3643 if (!NILP (horflag))
3645 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3646 WINDOW_TOP (p) = WINDOW_TOP (o);
3647 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3648 WINDOW_WIDTH (o) = psize;
3649 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3653 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3654 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3655 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3656 WINDOW_HEIGHT (o) = psize;
3657 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3660 XFRAME (p->frame)->mirror_dirty = 1;
3661 /* do this last (after the window is completely initialized and
3662 the mirror-dirty flag is set) so that specifier recomputation
3663 caused as a result of this will work properly and not abort. */
3664 Fset_window_buffer (new, o->buffer, Qt);
3669 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3670 Make the selected window N lines bigger.
3671 From program, optional second arg SIDE non-nil means grow sideways N columns,
3672 and optional third arg WINDOW specifies the window to change instead of the
3677 struct window *w = decode_window (window);
3679 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3683 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3684 Make the selected window N pixels bigger.
3685 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3686 and optional third arg WINDOW specifies the window to change instead of the
3691 struct window *w = decode_window (window);
3693 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3697 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3698 Make the selected window N lines smaller.
3699 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3700 and optional third arg WINDOW specifies the window to change instead of the
3706 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3711 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3712 Make the selected window N pixels smaller.
3713 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3714 and optional third arg WINDOW specifies the window to change instead of the
3720 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3726 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3727 int include_gutters_p)
3730 int defheight, defwidth;
3734 XSETWINDOW (window, w);
3736 avail_height = (pixel_height -
3737 (include_gutters_p ? 0 :
3738 window_top_window_gutter_height (w) +
3739 window_bottom_window_gutter_height (w)));
3741 default_face_height_and_width (window, &defheight, &defwidth);
3743 char_height = avail_height / defheight;
3745 /* It's the calling function's responsibility to check these values
3746 and make sure they're not out of range.
3748 #### We need to go through the calling functions and actually
3750 return max (0, char_height);
3754 window_char_height_to_pixel_height (struct window *w, int char_height,
3755 int include_gutters_p)
3758 int defheight, defwidth;
3763 XSETWINDOW (window, w);
3765 default_face_height_and_width (window, &defheight, &defwidth);
3767 avail_height = char_height * defheight;
3768 pixel_height = (avail_height +
3769 (include_gutters_p ? 0 :
3770 window_top_window_gutter_height (w) +
3771 window_bottom_window_gutter_height (w)));
3773 /* It's the calling function's responsibility to check these values
3774 and make sure they're not out of range.
3776 #### We need to go through the calling functions and actually
3778 return max (0, pixel_height);
3781 /* Return number of default lines of text can fit in the window W.
3782 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3783 horizontal scrollbar) in the space that is used for the calculation.
3784 This doesn't include space used by the frame gutters.
3787 window_char_height (struct window *w, int include_gutters_p)
3789 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3794 * Return number of lines currently displayed in window w. If
3795 * end-of-buffer is displayed then the area below end-of-buffer is assume
3796 * to be blank lines of default height.
3797 * Does not include the modeline.
3800 window_displayed_height (struct window *w)
3802 struct buffer *b = XBUFFER (w->buffer);
3803 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3805 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3807 : w->window_end_pos[CURRENT_DISP]);
3809 if (!Dynarr_length (dla))
3810 return window_char_height (w, 0);
3812 num_lines = Dynarr_length (dla);
3814 /* #### Document and assert somewhere that w->window_end_pos == -1
3815 indicates that end-of-buffer is being displayed. */
3818 struct display_line *dl = Dynarr_atp (dla, 0);
3819 int ypos1 = dl->ypos + dl->descent;
3820 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3822 int defheight, defwidth;
3824 XSETWINDOW (window, w);
3830 if (Dynarr_length (dla) == 1)
3831 ypos1 = WINDOW_TEXT_TOP (w);
3834 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3835 /* If this line is clipped then we know that there is no
3836 blank room between eob and the modeline. If we are
3837 scrolling on clipped lines just know off the clipped
3839 if (scroll_on_clipped_lines && dl->clip)
3840 return num_lines - 1;
3841 ypos1 = dl->ypos + dl->descent - dl->clip;
3845 default_face_height_and_width (window, &defheight, &defwidth);
3846 /* #### This probably needs to know about the clipping area once a
3847 final definition is decided on. */
3848 num_lines += ((ypos2 - ypos1) / defheight);
3852 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3855 if (scroll_on_clipped_lines
3856 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3864 window_pixel_width (Lisp_Object window)
3866 return WINDOW_WIDTH (XWINDOW (window));
3869 /* Calculate the pixel of a window, optionally including margin space
3870 but no vertical gutters. */
3872 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3873 int include_margins_p)
3877 int defheight, defwidth;
3880 XSETWINDOW (window, w);
3882 avail_width = (pixel_width -
3883 window_left_gutter_width (w, 0) -
3884 window_right_gutter_width (w, 0) -
3885 (include_margins_p ? 0 : window_left_margin_width (w)) -
3886 (include_margins_p ? 0 : window_right_margin_width (w)));
3888 default_face_height_and_width (window, &defheight, &defwidth);
3890 char_width = (avail_width / defwidth);
3892 /* It's the calling function's responsibility to check these values
3893 and make sure they're not out of range.
3895 #### We need to go through the calling functions and actually
3897 return max (0, char_width);
3901 window_char_width_to_pixel_width (struct window *w, int char_width,
3902 int include_margins_p)
3906 int defheight, defwidth;
3909 XSETWINDOW (window, w);
3911 default_face_height_and_width (window, &defheight, &defwidth);
3913 avail_width = char_width * defwidth;
3914 pixel_width = (avail_width +
3915 window_left_window_gutter_width (w, 0) +
3916 window_right_window_gutter_width (w, 0) +
3917 (include_margins_p ? 0 : window_left_margin_width (w)) +
3918 (include_margins_p ? 0 : window_right_margin_width (w)));
3920 /* It's the calling function's responsibility to check these values
3921 and make sure they're not out of range.
3923 #### We need to go through the calling functions and actually
3925 return max (0, pixel_width);
3928 /* This returns the usable space which doesn't include space needed by
3929 scrollbars or divider lines. */
3931 window_char_width (struct window *w, int include_margins_p)
3933 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3937 #define MINSIZE(w) \
3939 ? window_min_width * defwidth \
3940 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3943 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3945 #define CURSIZE(w) \
3946 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3948 #define CURCHARSIZE(w) \
3949 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3951 #define MINCHARSIZE(window) \
3952 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3953 ? 1 : window_min_height)
3956 window_pixheight (Lisp_Object w)
3958 return window_pixel_height (XWINDOW (w));
3961 /* Unlike set_window_pixheight, this function
3962 also changes the heights of the siblings so as to
3963 keep everything consistent. */
3966 change_window_height (struct window *win, int delta, int widthflag,
3974 int (*sizefun) (Lisp_Object) = (widthflag
3975 ? window_pixel_width
3976 : window_pixheight);
3977 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3978 ? set_window_pixwidth
3979 : set_window_pixheight);
3981 int defheight, defwidth;
3986 check_min_window_sizes ();
3988 XSETWINDOW (window, win);
3989 f = XFRAME (win->frame);
3990 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3991 error ("Won't change only window");
3993 /* #### This is very likely incorrect and instead the char_to_pixel_
3994 functions should be called. */
3995 default_face_height_and_width (window, &defheight, &defwidth);
3999 w = XWINDOW (window);
4004 error ("No other window to side of this one");
4008 ? !NILP (XWINDOW (parent)->hchild)
4009 : !NILP (XWINDOW (parent)->vchild))
4014 sizep = &CURSIZE (w);
4015 dim = CURCHARSIZE (w);
4017 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4018 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4020 if (MINI_WINDOW_P (XWINDOW (window)))
4022 else if (!NILP (parent))
4024 Fdelete_window (window, Qnil);
4030 delta *= (widthflag ? defwidth : defheight);
4035 maxdelta = ((!NILP (parent))
4036 ? (*sizefun) (parent) - *sizep
4037 : ((!NILP (w->next))
4038 ? (*sizefun) (w->next) - MINSIZE (w->next)
4039 : ((!NILP (w->prev))
4040 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4041 /* This is a frame with only one window,
4042 a minibuffer-only or a minibufferless frame. */
4045 if (delta > maxdelta)
4046 /* This case traps trying to make the minibuffer
4047 the full frame, or make the only window aside from the
4048 minibuffer the full frame. */
4055 /* #### Chuck: is this correct? */
4056 if (*sizep + delta < MINSIZE (window))
4058 Fdelete_window (window);
4064 if (!NILP (w->next) &&
4065 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4067 CURBEG (XWINDOW (w->next)) += delta;
4068 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4069 (*setsizefun) (window, *sizep + delta, 0);
4071 else if (!NILP (w->prev) &&
4072 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4074 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4075 CURBEG (w) -= delta;
4076 (*setsizefun) (window, *sizep + delta, 0);
4081 int opht = (*sizefun) (parent);
4083 /* If trying to grow this window to or beyond size of the parent,
4084 make delta1 so big that, on shrinking back down,
4085 all the siblings end up with less than one line and are deleted. */
4086 if (opht <= *sizep + delta)
4087 delta1 = opht * opht * 2;
4088 /* Otherwise, make delta1 just right so that if we add delta1
4089 lines to this window and to the parent, and then shrink
4090 the parent back to its original size, the new proportional
4091 size of this window will increase by delta. */
4093 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4095 /* Add delta1 lines or columns to this window, and to the parent,
4096 keeping things consistent while not affecting siblings. */
4097 CURSIZE (XWINDOW (parent)) = opht + delta1;
4098 (*setsizefun) (window, *sizep + delta1, 0);
4100 /* Squeeze out delta1 lines or columns from our parent,
4101 shrinking this window and siblings proportionately.
4102 This brings parent back to correct size.
4103 Delta1 was calculated so this makes this window the desired size,
4104 taking it all out of the siblings. */
4105 (*setsizefun) (parent, opht, 0);
4108 SET_LAST_MODIFIED (w, 0);
4109 SET_LAST_FACECHANGE (w);
4110 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4111 /* overkill maybe, but better to be correct */
4112 MARK_FRAME_GUTTERS_CHANGED (f);
4122 /* Scroll contents of window WINDOW up N lines. If N < (top line height /
4123 average line height) then we just adjust the top clip. */
4125 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
4126 Error_behavior errb)
4128 struct window *w = XWINDOW (window);
4129 struct buffer *b = XBUFFER (w->buffer);
4130 int selected = EQ (window, Fselected_window (Qnil));
4132 Lisp_Object point, tem;
4133 display_line_dynarr *dla;
4134 int fheight, fwidth, modeline = 0;
4135 struct display_line* dl;
4138 point = make_int (BUF_PT (b));
4141 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4143 if (pos < BUF_BEGV (b))
4145 else if (pos > BUF_ZV (b))
4148 point = make_int (pos);
4151 /* Always set force_start so that redisplay_window will run
4152 the window-scroll-functions. */
4155 /* #### When the fuck does this happen? I'm so glad that history has
4156 completely documented the behavior of the scrolling functions under
4157 all circumstances. */
4158 tem = Fpos_visible_in_window_p (point, window);
4161 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4163 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4164 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4165 WINDOW_TEXT_TOP_CLIP (w) = 0;
4166 MARK_WINDOWS_CHANGED (w);
4175 n = Fprefix_numeric_value (n);
4176 value = XINT (n) * direction;
4179 return; /* someone just made a pointless call */
4183 /* If the user didn't specify how far to scroll then we have to figure it
4184 out by ourselves. */
4185 if (NILP (n) || EQ (n, Qminus))
4187 /* Going forwards is easy. If that is what we are doing then just
4188 set value and the section which handles the user specifying a
4189 positive value will work. */
4192 value = window_displayed_height (w) - next_screen_context_lines;
4193 value = (value < 1 ? 1 : value);
4196 /* Going backwards is hard. We can't use the same loop used if the
4197 user specified a negative value because we care about
4198 next_screen_context_lines. In a variable height world you don't
4199 know how many lines above you can actually be displayed and still
4200 have the context lines appear. So we leave value set to 0 and add
4201 a separate section to deal with this. */
4205 if (direction == 1 && !value)
4210 /* Determine parameters to test for partial line scrolling with. */
4211 dla = window_display_lines (w, CURRENT_DISP);
4213 if (INTP (Vwindow_pixel_scroll_increment))
4214 fheight = XINT (Vwindow_pixel_scroll_increment);
4215 else if (!NILP (Vwindow_pixel_scroll_increment))
4216 default_face_height_and_width (window, &fheight, &fwidth);
4218 if (Dynarr_length (dla) >= 1)
4219 modeline = Dynarr_atp (dla, 0)->modeline;
4221 dl = Dynarr_atp (dla, modeline);
4225 /* Go for partial display line scrolling. This just means bumping
4226 the clip by a reasonable amount and redisplaying, everything else
4227 remains unchanged. */
4228 if (!NILP (Vwindow_pixel_scroll_increment)
4230 Dynarr_length (dla) >= (1 + modeline)
4232 (dl->ascent - dl->top_clip) - fheight * value > 0)
4234 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4235 MARK_WINDOWS_CHANGED (w);
4240 Bufpos startp, old_start;
4242 if (WINDOW_TEXT_TOP_CLIP (w))
4244 WINDOW_TEXT_TOP_CLIP (w) = 0;
4245 MARK_WINDOWS_CHANGED (w);
4248 old_start = marker_position (w->start[CURRENT_DISP]);
4249 startp = vmotion (w, old_start, value, &vtarget);
4251 if (vtarget < value &&
4252 (w->window_end_pos[CURRENT_DISP] == -1
4253 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4255 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4260 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4263 w->start_at_line_beg = beginning_of_line_p (b, startp);
4264 MARK_WINDOWS_CHANGED (w);
4266 if (!point_would_be_visible (w, startp, XINT (point)))
4269 BUF_SET_PT (b, startp);
4271 set_marker_restricted (w->pointm[CURRENT_DISP],
4280 /* Go for partial display line scrolling. This just means bumping
4281 the clip by a reasonable amount and redisplaying, everything else
4282 remains unchanged. */
4283 if (!NILP (Vwindow_pixel_scroll_increment)
4285 Dynarr_length (dla) >= (1 + modeline)
4287 (dl->ascent - dl->top_clip) - fheight * value <
4288 (dl->ascent + dl->descent - dl->clip)
4290 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4292 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4293 MARK_WINDOWS_CHANGED (w);
4298 Bufpos startp, old_start;
4300 if (WINDOW_TEXT_TOP_CLIP (w))
4302 WINDOW_TEXT_TOP_CLIP (w) = 0;
4303 MARK_WINDOWS_CHANGED (w);
4306 old_start = marker_position (w->start[CURRENT_DISP]);
4307 startp = vmotion (w, old_start, value, &vtarget);
4310 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4312 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4317 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4320 w->start_at_line_beg = beginning_of_line_p (b, startp);
4321 MARK_WINDOWS_CHANGED (w);
4323 /* #### Scroll back by less than a line. This code was
4324 originally for scrolling over large pixmaps and it
4325 loses when a line being *exposed* at the top of the
4326 window is bigger than the current one. However, for
4327 pixel based scrolling in general we can guess that
4328 the line we are going to display is probably the same
4329 size as the one we are on. In that instance we can
4330 have a reasonable stab at a suitable top clip. Fixing
4331 this properly is hard (and probably slow) as we would
4332 have to call redisplay to figure out the exposed line
4334 if (!NILP (Vwindow_pixel_scroll_increment)
4335 && Dynarr_length (dla) >= (1 + modeline)
4336 && dl->ascent + fheight * value > 0)
4338 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4341 if (!point_would_be_visible (w, startp, XINT (point)))
4345 if (MINI_WINDOW_P (w))
4348 new_point = start_of_last_line (w, startp);
4351 BUF_SET_PT (b, new_point);
4353 set_marker_restricted (w->pointm[CURRENT_DISP],
4354 make_int (new_point),
4360 else /* value == 0 && direction == -1 */
4362 if (WINDOW_TEXT_TOP_CLIP (w))
4364 WINDOW_TEXT_TOP_CLIP (w) = 0;
4365 MARK_WINDOWS_CHANGED (w);
4367 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4369 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4375 int movement = next_screen_context_lines - 1;
4376 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4377 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4379 start_with_point_on_display_line (w, bottom,
4380 -1 - (movement - vtarget));
4382 if (startp >= old_startp)
4383 startp = vmotion (w, old_startp, -1, NULL);
4385 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4388 w->start_at_line_beg = beginning_of_line_p (b, startp);
4389 MARK_WINDOWS_CHANGED (w);
4391 if (!point_would_be_visible (w, startp, XINT (point)))
4393 Bufpos new_point = start_of_last_line (w, startp);
4396 BUF_SET_PT (b, new_point);
4398 set_marker_restricted (w->pointm[CURRENT_DISP],
4399 make_int (new_point),
4406 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4407 Scroll text of current window upward N lines; or near full screen if no arg.
4408 A near full screen is `next-screen-context-lines' less than a full screen.
4409 Negative N means scroll downward.
4410 When calling from a program, supply an integer as argument or nil.
4411 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4412 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4417 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4421 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4422 Scroll text of current window downward N lines; or near full screen if no arg.
4423 A near full screen is `next-screen-context-lines' less than a full screen.
4424 Negative N means scroll upward.
4425 When calling from a program, supply a number as argument or nil.
4426 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4427 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4432 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4436 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4437 Return the other window for "other window scroll" commands.
4438 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4439 specifies the window.
4440 If `other-window-scroll-buffer' is non-nil, a window
4441 showing that buffer is used.
4446 Lisp_Object selected_window = Fselected_window (Qnil);
4448 if (MINI_WINDOW_P (XWINDOW (selected_window))
4449 && !NILP (Vminibuffer_scroll_window))
4450 window = Vminibuffer_scroll_window;
4451 /* If buffer is specified, scroll that buffer. */
4452 else if (!NILP (Vother_window_scroll_buffer))
4454 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4456 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4460 /* Nothing specified; look for a neighboring window on the same
4462 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4464 if (EQ (window, selected_window))
4465 /* That didn't get us anywhere; look for a window on another
4468 window = Fnext_window (window, Qnil, Qt, Qnil);
4469 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4470 && ! EQ (window, selected_window));
4473 CHECK_LIVE_WINDOW (window);
4475 if (EQ (window, selected_window))
4476 error ("There is no other window");
4481 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4482 Scroll next window upward N lines; or near full frame if no arg.
4483 The next window is the one below the current one; or the one at the top
4484 if the current one is at the bottom. Negative N means scroll downward.
4485 When calling from a program, supply a number as argument or nil.
4487 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4488 specifies the window to scroll.
4489 If `other-window-scroll-buffer' is non-nil, scroll the window
4490 showing that buffer, popping the buffer up if necessary.
4494 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4498 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4499 Scroll selected window display N columns left.
4500 Default for N is window width minus 2.
4504 Lisp_Object window = Fselected_window (Qnil);
4505 struct window *w = XWINDOW (window);
4506 int count = (NILP (n) ?
4507 window_char_width (w, 0) - 2 :
4508 XINT (Fprefix_numeric_value (n)));
4510 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4513 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4514 Scroll selected window display N columns right.
4515 Default for N is window width minus 2.
4519 Lisp_Object window = Fselected_window (Qnil);
4520 struct window *w = XWINDOW (window);
4521 int count = (NILP (n) ?
4522 window_char_width (w, 0) - 2 :
4523 XINT (Fprefix_numeric_value (n)));
4525 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4528 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4529 Center point in WINDOW. With N, put point on line N.
4530 The desired position of point is always relative to the window.
4531 If WINDOW is nil, the selected window is used.
4535 struct window *w = decode_window (window);
4536 struct buffer *b = XBUFFER (w->buffer);
4537 Bufpos opoint = BUF_PT (b);
4541 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4544 n = Fprefix_numeric_value (n);
4546 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4549 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4551 w->start_at_line_beg = beginning_of_line_p (b, startp);
4553 MARK_WINDOWS_CHANGED (w);
4557 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4558 Position point relative to WINDOW.
4559 With no argument, position text at center of window.
4560 An argument specifies window line; zero means top of window,
4561 negative means relative to bottom of window.
4562 If WINDOW is nil, the selected window is used.
4569 Bufpos start, new_point;
4572 /* Don't use decode_window() because we need the new value of
4575 window = Fselected_window (Qnil);
4577 CHECK_LIVE_WINDOW (window);
4578 w = XWINDOW (window);
4579 b = XBUFFER (w->buffer);
4581 height = window_displayed_height (w);
4582 selected = EQ (window, Fselected_window (w->frame));
4588 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4589 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4591 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4594 BUF_SET_PT (b, new_point);
4596 Fset_window_point (window, make_int (new_point));
4598 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4602 start = marker_position (w->start[CURRENT_DISP]);
4603 if (start < BUF_BEGV (b))
4604 start = BUF_BEGV (b);
4605 else if (start > BUF_ZV (b))
4609 new_point = BUF_PT (b);
4611 new_point = marker_position (w->pointm[CURRENT_DISP]);
4613 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4616 BUF_SET_PT (b, new_point);
4618 Fset_window_point (window, make_int (new_point));
4620 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4623 return make_int (retval);
4627 /* #### Is this going to work right when at eob? */
4628 arg = Fprefix_numeric_value (arg);
4630 XSETINT (arg, XINT (arg) + height);
4633 start = marker_position (w->start[CURRENT_DISP]);
4634 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4637 new_point = BUF_PT (b);
4639 new_point = marker_position (w->pointm[CURRENT_DISP]);
4641 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4644 BUF_SET_PT (b, new_point);
4646 Fset_window_point (window, make_int (new_point));
4648 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4650 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4656 BUF_SET_PT (b, start);
4658 Fset_window_point (window, make_int (start));
4662 return Fvertical_motion (arg, window, Qnil);
4666 new_point = vmotion (XWINDOW (window),
4667 marker_position (w->pointm[CURRENT_DISP]),
4669 Fset_window_point (window, make_int (new_point));
4670 return make_int (vpos);
4676 map_windows_1 (Lisp_Object window,
4677 int (*mapfun) (struct window *w, void *closure),
4680 for (; !NILP (window); window = XWINDOW (window)->next)
4683 struct window *w = XWINDOW (window);
4685 if (!NILP (w->vchild))
4686 retval = map_windows_1 (w->vchild, mapfun, closure);
4687 else if (!NILP (w->hchild))
4688 retval = map_windows_1 (w->hchild, mapfun, closure);
4690 retval = (mapfun) (w, closure);
4699 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4700 invocation of MAPFUN. If any invocation of MAPFUN returns
4701 non-zero, the mapping is halted. Otherwise, map_windows() maps
4702 over all windows in F.
4704 If MAPFUN creates or deletes windows, the behavior is undefined. */
4707 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4711 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4714 Lisp_Object frmcons, devcons, concons;
4716 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4718 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4730 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4733 w->shadow_thickness_changed = 1;
4734 MARK_WINDOWS_CHANGED (w);
4738 vertical_divider_changed_in_window (Lisp_Object specifier,
4742 MARK_WINDOWS_CHANGED (w);
4743 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4746 /* also used in scrollbar.c */
4748 some_window_value_changed (Lisp_Object specifier, struct window *w,
4751 MARK_WINDOWS_CHANGED (w);
4754 #ifdef MEMORY_USAGE_STATS
4760 #ifdef HAVE_SCROLLBARS
4764 int other_redisplay;
4769 compute_window_mirror_usage (struct window_mirror *mir,
4770 struct window_stats *stats,
4771 struct overhead_stats *ovstats)
4775 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4777 #ifdef HAVE_SCROLLBARS
4779 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4782 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4785 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4788 #endif /* HAVE_SCROLLBARS */
4789 stats->other_redisplay +=
4790 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4791 stats->other_redisplay +=
4792 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4796 compute_window_usage (struct window *w, struct window_stats *stats,
4797 struct overhead_stats *ovstats)
4800 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4801 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4802 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4803 stats->line_start +=
4804 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4805 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4808 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4809 Return stats about the memory usage of window WINDOW.
4810 The values returned are in the form of an alist of usage types and byte
4811 counts. The byte counts attempt to encompass all the memory used
4812 by the window (separate from the memory logically associated with a
4813 buffer or frame), including internal structures and any malloc()
4814 overhead associated with them. In practice, the byte counts are
4815 underestimated because certain memory usage is very hard to determine
4816 \(e.g. the amount of memory used inside the Xt library or inside the
4817 X server) and because there is other stuff that might logically
4818 be associated with a window, buffer, or frame (e.g. window configurations,
4819 glyphs) but should not obviously be included in the usage counts.
4821 Multiple slices of the total memory usage may be returned, separated
4822 by a nil. Each slice represents a particular view of the memory, a
4823 particular way of partitioning it into groups. Within a slice, there
4824 is no overlap between the groups of memory, and each slice collectively
4825 represents all the memory concerned.
4829 struct window_stats stats;
4830 struct overhead_stats ovstats;
4831 Lisp_Object val = Qnil;
4833 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4835 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4837 val = acons (Qface_cache, make_int (stats.face), val);
4838 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4839 #ifdef HAVE_SCROLLBARS
4840 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4842 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4843 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4844 val = acons (Qother, make_int (stats.other), val);
4845 val = Fcons (Qnil, val);
4846 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4847 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4848 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4850 return Fnreverse (val);
4853 #endif /* MEMORY_USAGE_STATS */
4856 /************************************************************************/
4857 /* Window configurations */
4858 /************************************************************************/
4860 /* #### This window configuration stuff has had serious bugs lurking in it
4861 for years; it would be a -huge- win if this was reimplemented in lisp.
4864 /* If you add anything to this structure make sure saved_window_equal
4868 Lisp_Object window; /* window */
4869 Lisp_Object buffer; /* buffer */
4870 Lisp_Object start; /* copied marker */
4871 Lisp_Object pointm; /* copied marker */
4872 Lisp_Object sb_point; /* copied marker */
4873 Lisp_Object mark; /* copied marker */
4879 Charcount modeline_hscroll;
4880 int parent_index; /* index into saved_windows */
4881 int prev_index; /* index into saved_windows */
4882 char start_at_line_beg; /* boolean */
4884 #define WINDOW_SLOT_DECLARATION
4885 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4886 #include "winslots.h"
4889 /* If you add anything to this structure make sure window_config_equal
4891 struct window_config
4893 struct lcrecord_header header;
4894 /* int frame_width; No longer needed, JV
4895 int frame_height; */
4897 Lisp_Object selected_frame;
4899 Lisp_Object current_window;
4900 Lisp_Object current_buffer;
4901 Lisp_Object minibuffer_scroll_window;
4902 Lisp_Object root_window;
4903 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4904 /* Record the values of window-min-width and window-min-height
4905 so that window sizes remain consistent with them. */
4906 int min_width, min_height;
4907 int saved_windows_count;
4908 /* Zero-sized arrays aren't ANSI C */
4909 struct saved_window saved_windows[1];
4912 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4913 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4914 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4915 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4916 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4919 mark_window_config (Lisp_Object obj)
4921 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4923 mark_object (config->current_window);
4924 mark_object (config->current_buffer);
4925 mark_object (config->minibuffer_scroll_window);
4926 mark_object (config->root_window);
4928 for (i = 0; i < config->saved_windows_count; i++)
4930 struct saved_window *s = SAVED_WINDOW_N (config, i);
4931 mark_object (s->window);
4932 mark_object (s->buffer);
4933 mark_object (s->start);
4934 mark_object (s->pointm);
4935 mark_object (s->sb_point);
4936 mark_object (s->mark);
4938 /* #### This looked like this. I do not see why specifier cached
4939 values should not be marked, as such specifiers as toolbars
4940 might have GC-able instances. Freed configs are not marked,
4941 aren't they? -- kkm */
4942 mark_object (s->dedicated);
4944 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
4945 #include "winslots.h"
4952 sizeof_window_config_for_n_windows (int n)
4954 return (sizeof (struct window_config) +
4955 /* n - 1 because zero-sized arrays aren't ANSI C */
4956 (n - 1) *sizeof (struct saved_window));
4960 sizeof_window_config (const void *h)
4962 const struct window_config *c = (const struct window_config *) h;
4963 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4967 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4969 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4972 error ("printing unreadable object #<window-configuration 0x%x>",
4973 config->header.uid);
4974 write_c_string ("#<window-configuration ", printcharfun);
4975 sprintf (buf, "0x%x>", config->header.uid);
4976 write_c_string (buf, printcharfun);
4979 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4980 window_configuration,
4982 print_window_config,
4983 0, 0, 0, 0, sizeof_window_config,
4984 struct window_config);
4987 /* Returns a boolean indicating whether the two saved windows are
4990 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4992 #define WINDOW_SLOT(slot, compare) \
4993 if (!compare (win1->slot, win2->slot)) \
4995 #include "winslots.h"
4998 EQ (win1->window, win2->window) &&
4999 EQ (win1->buffer, win2->buffer) &&
5000 internal_equal (win1->start, win2->start, 0) &&
5001 internal_equal (win1->pointm, win2->pointm, 0) &&
5002 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5003 internal_equal (win1->mark, win2->mark, 0) &&
5004 win1->pixel_left == win2->pixel_left &&
5005 win1->pixel_top == win2->pixel_top &&
5006 win1->pixel_width == win2->pixel_width &&
5007 win1->pixel_height == win2->pixel_height &&
5008 win1->hscroll == win2->hscroll &&
5009 win1->modeline_hscroll == win2->modeline_hscroll &&
5010 win1->parent_index == win2->parent_index &&
5011 win1->prev_index == win2->prev_index &&
5012 win1->start_at_line_beg == win2->start_at_line_beg;
5015 /* Returns a boolean indicating whether the two given configurations
5018 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5020 struct window_config *fig1, *fig2;
5023 /* First check if they are truly the same. */
5024 if (EQ (conf1, conf2))
5027 fig1 = XWINDOW_CONFIGURATION (conf1);
5028 fig2 = XWINDOW_CONFIGURATION (conf2);
5030 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5031 EQ (fig1->current_window, fig2->current_window) &&
5032 EQ (fig1->current_buffer, fig2->current_buffer) &&
5033 EQ (fig1->root_window, fig2->root_window) &&
5034 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5036 fig1->frame_width == fig2->frame_width &&
5037 fig1->frame_height == fig2->frame_height)) */
5040 for (i = 0; i < fig1->saved_windows_count; i++)
5042 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5043 SAVED_WINDOW_N (fig2, i)))
5050 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5051 Return t if OBJECT is a window-configuration object.
5055 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
5059 mark_windows_in_use_closure (struct window *w, void *closure)
5061 int mark = *(int *)closure;
5062 w->config_mark = mark;
5067 mark_windows_in_use (struct frame *f, int mark)
5069 map_windows (f, mark_windows_in_use_closure, &mark);
5072 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5074 free_window_configuration (Lisp_Object window_config)
5077 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5079 /* Free all the markers. It's not completely necessary that
5080 we do this (window configs sitting in a free list aren't
5081 marked normally so the markers wouldn't be marked anyway)
5082 but it's more efficient. */
5083 for (i = 0; i < config->saved_windows_count; i++)
5085 struct saved_window *p = SAVED_WINDOW_N (config, i);
5087 if (!NILP (p->pointm))
5089 free_marker (XMARKER (p->pointm));
5092 if (!NILP (p->start))
5094 free_marker (XMARKER (p->start));
5097 if (!NILP (p->sb_point))
5099 free_marker (XMARKER (p->sb_point));
5102 if (!NILP (p->mark))
5104 free_marker (XMARKER (p->mark));
5109 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5110 free_managed_lcrecord (Vwindow_configuration_free_list
5111 [config->saved_windows_count - 1],
5117 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5118 Set the configuration of windows and buffers as specified by CONFIGURATION.
5119 CONFIGURATION must be a value previously returned
5120 by `current-window-configuration' (which see).
5125 struct window_config *config;
5126 struct saved_window *p;
5127 Lisp_Object new_current_buffer;
5131 struct gcpro gcpro1;
5132 Lisp_Object old_window_config;
5133 /* int previous_frame_height;
5134 int previous_frame_width;*/
5135 int previous_pixel_top;
5136 int previous_pixel_height;
5137 int previous_pixel_left;
5138 int previous_pixel_width;
5139 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5140 int real_font_height;
5141 int converted_minibuf_height,target_minibuf_height;
5142 int specpdl_count = specpdl_depth ();
5144 GCPRO1 (configuration);
5146 CHECK_WINDOW_CONFIGURATION (configuration);
5147 config = XWINDOW_CONFIGURATION (configuration);
5149 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5152 /* Do not signal an error here if the frame was deleted. There are
5153 reasonable cases where we could get here with a deleted frame and
5154 just want to do close to nothing instead. */
5156 if (FRAME_LIVE_P (f))
5158 /* restore the frame characteristics */
5160 new_current_buffer = config->current_buffer;
5161 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5162 new_current_buffer = Qnil;
5165 * Assumed precondition: w->config_mark = 0 for all w
5166 * This procedure should ensure this is true by the time it exits
5167 * to ensure the precondition for future calls.
5169 * We use w->config_mark to know whether we're modifying a
5170 * window that is currently visible on the frame (#### we
5171 * should just be able to check whether the window is dead
5172 * or not, but this way is safer?). As we process each
5173 * window, we set its config_mark to 0. At the end, we
5174 * go through all the windows that used to be on the frame,
5175 * set each one's config_mark to 0 (to maintain the
5176 * assumed precondition) and delete each one that's no
5179 * #### Using a window-configuration to keep track of
5180 * the current windows is wasteful. All we need is the
5181 * list of windows, so we could just use a dynarr.
5183 old_window_config = Fcurrent_window_configuration (frame);
5185 /* If the new configuration is already equal to the old, then stop
5186 right here. This saves the work below and it also saves
5187 triggering a full redisplay of this window. This is a huge win
5188 when using the mouse since the mode motion code uses
5189 save-window-excursion extensively but will rarely cause the
5190 configuration to actually change. */
5191 if (window_config_equal (configuration, old_window_config))
5193 free_window_configuration (old_window_config);
5198 /* We can't quit or even check for quit because that may cause
5199 investigation of the frame state, which may crash if the frame is
5200 in an inconsistent state. */
5201 begin_dont_check_for_quit ();
5202 record_unwind_protect (free_window_configuration, old_window_config);
5204 mark_windows_in_use (f, 1);
5205 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5206 /* Force subwindows to be remapped. This is overkill but saves
5207 us having to rely on the redisplay code to unmap any extant
5210 #### It does cause some extra flashing though which we could
5211 possibly avoid. So consider trying to get redisplay to work
5214 Removing the instances from the frame cache is wrong because
5215 an instance is only put in the frame cache when it is
5216 instantiated. So if we do this there is a chance that stuff
5217 will never get put back in the frame cache. */
5218 reset_frame_subwindow_instance_cache (f);
5221 /* JV: This is bogus,
5222 First of all, the units are inconsistent. The frame sizes are measured
5223 in characters but the window sizes are stored in pixels. So if a
5224 font size change happened between saving and restoring, the
5225 frame "sizes" maybe equal but the windows still should be
5226 resized. This is tickled a lot by the new "character size
5227 stays constant" policy in 21.0. It leads to very weird
5228 glitches (and possibly crashes when asserts are tickled).
5230 Just changing the units doesn't help because changing the
5231 toolbar configuration can also change the pixel positions.
5232 Luckily there is a much simpler way of doing this, see below.
5234 previous_frame_width = FRAME_WIDTH (f);
5235 previous_frame_height = FRAME_HEIGHT (f);
5236 /* If the frame has been resized since this window configuration was
5237 made, we change the frame to the size specified in the
5238 configuration, restore the configuration, and then resize it
5239 back. We keep track of the prevailing height in these variables. */
5240 if (config->frame_height != FRAME_HEIGHT (f)
5241 || config->frame_width != FRAME_WIDTH (f))
5242 change_frame_size (f, config->frame_height, config->frame_width, 0);
5245 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5246 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5247 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5248 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5250 /* remember some properties of the minibuffer */
5252 default_face_height_and_width (frame, &real_font_height, 0);
5253 assert(real_font_height > 0);
5255 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5257 previous_minibuf_height
5258 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5259 previous_minibuf_top
5260 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5261 previous_minibuf_width
5262 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5266 previous_minibuf_height = 0;
5267 previous_minibuf_top = 0;
5268 previous_minibuf_width = 0;
5270 converted_minibuf_height =
5271 (previous_minibuf_height % real_font_height) == 0 ?
5272 - (previous_minibuf_height / real_font_height ) : /* lines */
5273 previous_minibuf_height; /* pixels */
5275 /* Temporarily avoid any problems with windows that are smaller
5276 than they are supposed to be. */
5277 window_min_height = 1;
5278 window_min_width = 1;
5280 /* OK, now restore all the windows in the window config.
5281 This may involve "undeleting" windows, since the
5282 windows in the window config may be deleted.
5284 for (k = 0; k < config->saved_windows_count; k++)
5286 p = SAVED_WINDOW_N (config, k);
5287 w = XWINDOW (p->window);
5290 /* The window might be dead. In this case, its redisplay
5291 structures were freed, so we need to reallocate them. */
5292 if (!w->face_cachels)
5294 w->face_cachels = Dynarr_new (face_cachel);
5295 reset_face_cachels (w);
5297 if (!w->glyph_cachels)
5298 w->glyph_cachels = Dynarr_new (glyph_cachel);
5299 if (!w->line_start_cache)
5300 w->line_start_cache = Dynarr_new (line_start_cache);
5301 w->gutter_extent_modiff[0] = 0;
5302 w->gutter_extent_modiff[1] = 0;
5303 w->gutter_extent_modiff[2] = 0;
5304 w->gutter_extent_modiff[3] = 0;
5307 if (p->parent_index >= 0)
5308 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5312 if (p->prev_index >= 0)
5314 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5316 /* This is true for a minibuffer-only frame. */
5317 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5320 XWINDOW (w->prev)->next = p->window;
5325 if (!NILP (w->parent))
5327 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5329 XWINDOW (w->parent)->vchild = p->window;
5330 XWINDOW (w->parent)->hchild = Qnil;
5334 XWINDOW (w->parent)->hchild = p->window;
5335 XWINDOW (w->parent)->vchild = Qnil;
5339 if (!w->config_mark)
5341 /* #### This should be equivalent to the window previously
5342 having been dead. If we're brave, we'll put in an
5343 assertion to this effect. */
5344 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5346 else /* if (!EQ (w->buffer, p->buffer)) */
5348 /* With the new redisplay we let it know that a change has
5349 been made and it will take care of the rest. If we don't
5350 tell it something has possibly changed it could lead to
5351 incorrect display. */
5352 MARK_WINDOWS_CHANGED (w);
5355 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5356 WINDOW_TOP (w) = WINDOW_TOP (p);
5357 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5358 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5359 w->hscroll = p->hscroll;
5360 w->modeline_hscroll = p->modeline_hscroll;
5361 w->line_cache_last_updated = Qzero;
5362 /* When we restore a window's configuration, the identity of
5363 the window hasn't actually changed - so there is no
5364 reason why we shouldn't preserve the instance cache for
5365 it - unless it was originally deleted. This will often
5366 buy us something as we will not have to re-instantiate
5367 all the instances. This is because this is an instance
5368 cache - not a display cache. Preserving the display cache
5369 would definitely be wrong.
5371 We specifically want to do this for tabs, since for some
5372 reason finding a file will cause the configuration to be
5374 if (NILP (w->subwindow_instance_cache))
5375 w->subwindow_instance_cache =
5376 make_lisp_hash_table (30,
5377 HASH_TABLE_KEY_VALUE_WEAK,
5379 SET_LAST_MODIFIED (w, 1);
5380 SET_LAST_FACECHANGE (w);
5383 /* #### Consider making the instance cache a winslot. */
5384 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5385 #include "winslots.h"
5387 /* Reinstall the saved buffer and pointers into it. */
5388 if (NILP (p->buffer))
5389 w->buffer = p->buffer;
5392 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5393 /* If saved buffer is alive, install it. */
5395 w->buffer = p->buffer;
5396 w->start_at_line_beg = p->start_at_line_beg;
5397 set_marker_restricted (w->start[CURRENT_DISP],
5398 Fmarker_position (p->start),
5400 set_marker_restricted (w->pointm[CURRENT_DISP],
5401 Fmarker_position (p->pointm),
5403 set_marker_restricted (w->sb_point,
5404 Fmarker_position (p->sb_point),
5406 Fset_marker (XBUFFER (w->buffer)->mark,
5407 Fmarker_position (p->mark), w->buffer);
5409 /* As documented in Fcurrent_window_configuration, don't
5410 save the location of point in the buffer which was current
5411 when the window configuration was recorded. */
5412 if (!EQ (p->buffer, new_current_buffer) &&
5413 XBUFFER (p->buffer) == current_buffer)
5414 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5416 else if (NILP (w->buffer) ||
5417 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5418 /* Else if window's old buffer is dead too, get a live one. */
5420 /* #### The following line makes me nervous... */
5421 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5422 w->buffer = Fget_buffer_create (QSscratch);
5423 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5424 /* This will set the markers to beginning of visible
5426 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5427 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5429 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5430 w->start_at_line_beg = 1;
5433 /* Keeping window's old buffer; make sure the markers
5436 /* Set window markers at start of visible range. */
5437 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5438 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5440 if (XMARKER (w->sb_point)->buffer == 0)
5441 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5442 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5443 set_marker_restricted (w->pointm[CURRENT_DISP],
5445 (BUF_PT (XBUFFER (w->buffer))),
5447 w->start_at_line_beg = 1;
5452 FRAME_ROOT_WINDOW (f) = config->root_window;
5453 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5454 then calls do_switch_frame() below to select the frame that was
5455 recorded in the window config as being selected.
5457 Instead, we don't ever change the selected frame, and either
5458 call Fselect_window() below if the window config's frame is
5459 currently selected, or just set the selected window of the
5460 window config's frame. */
5463 /* Set the frame height to the value it had before this function. */
5464 if (previous_frame_height != FRAME_HEIGHT (f)
5465 || previous_frame_width != FRAME_WIDTH (f))
5466 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5468 /* We just reset the size and position of the minibuffer, to its old
5469 value, which needn't be valid. So we do some magic to see which value
5470 to actually take. Then we set it.
5473 We take the old value if is in the same units but differs from the
5476 #### Now we get more cases correct then ever before, but
5477 are we treating all? For instance what if the frames minibuf window
5478 is no longer the same one?
5480 target_minibuf_height = previous_minibuf_height;
5481 if (converted_minibuf_height &&
5482 (converted_minibuf_height * config->minibuf_height) > 0 &&
5483 (converted_minibuf_height != config->minibuf_height))
5485 target_minibuf_height = config->minibuf_height < 0 ?
5486 - (config->minibuf_height * real_font_height) :
5487 config->minibuf_height;
5488 target_minibuf_height =
5489 max(target_minibuf_height,real_font_height);
5491 if (previous_minibuf_height)
5493 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5494 = previous_minibuf_top -
5495 (target_minibuf_height - previous_minibuf_height);
5496 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5497 target_minibuf_height, 0);
5498 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5499 previous_minibuf_width, 0);
5502 /* This is a better way to deal with frame resizing, etc.
5503 What we _actually_ want is for the old (just restored)
5505 into the place of the new one. So we just do that. Simple! */
5506 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5507 /* Note that this function also updates the subwindow
5509 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5510 previous_pixel_height -
5511 (target_minibuf_height - previous_minibuf_height), 0);
5512 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5513 /* Note that this function also updates the subwindow
5515 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5517 /* If restoring in the current frame make the window current,
5518 otherwise just update the frame selected_window slot to be
5519 the restored current_window. */
5520 if (f == selected_frame ())
5523 /* When using `pop-window-configuration', often the minibuffer
5524 ends up as the selected window even though it's not active ...
5525 I really don't know the cause of this, but it should never
5526 happen. This kludge should fix it.
5528 #### Find out why this is really going wrong. */
5529 if (!minibuf_level &&
5530 MINI_WINDOW_P (XWINDOW (config->current_window)))
5531 window_to_select = Fnext_window (config->current_window,
5534 window_to_select = config->current_window;
5536 /* Do this last so that buffer stacking is calculated
5538 Fselect_window (config->current_window, Qnil);
5540 if (!NILP (new_current_buffer))
5542 Fset_buffer (new_current_buffer);
5543 Frecord_buffer (new_current_buffer);
5547 Fset_buffer (XWINDOW (config->current_window)->buffer);
5548 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5552 set_frame_selected_window (f, config->current_window);
5555 old_window_config = Qnil; /* Warning suppression */
5557 /* Restore the minimum heights recorded in the configuration. */
5558 window_min_height = config->min_height;
5559 window_min_width = config->min_width;
5562 /* see above comment */
5563 /* Fselect_window will have made f the selected frame, so we
5564 reselect the proper frame here. Fhandle_switch_frame will change the
5565 selected window too, but that doesn't make the call to
5566 Fselect_window above totally superfluous; it still sets f's
5568 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5569 do_switch_frame (config->selected_frame, Qnil, 0);
5572 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5574 if (FRAME_LIVE_P (f))
5576 /* Do this before calling recompute_all_cached_specifiers_in_window()
5577 so that things like redisplay_redraw_cursor() won't abort due
5578 to no window mirror present. */
5579 f->mirror_dirty = 1;
5581 config = XWINDOW_CONFIGURATION (old_window_config);
5582 for (k = 0; k < config->saved_windows_count; k++)
5584 p = SAVED_WINDOW_N (config, k);
5585 w = XWINDOW (p->window);
5586 /* Remember, we set w->config_mark on all currently visible
5587 windows, and reset it on all newly visible windows.
5588 Any windows still marked need to be deleted. */
5591 mark_window_as_deleted (w);
5596 /* We just potentially changed the window's buffer and
5597 potentially turned a dead window into a live one,
5598 so we need to recompute the cached specifier values. */
5599 recompute_all_cached_specifiers_in_window (w);
5604 /* Now restore things, when everything else if OK. */
5606 unbind_to (specpdl_count, Qnil);
5613 /* Mark all subwindows of a window as deleted. The argument
5614 W is actually the subwindow tree of the window in question. */
5617 delete_all_subwindows (struct window *w)
5619 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5620 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5621 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5623 mark_window_as_deleted (w);
5628 count_windows (struct window *window)
5631 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5632 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5633 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5637 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5640 for (j = 0; j < lim; j++)
5642 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5646 return 0; /* suppress compiler warning */
5650 save_window_save (Lisp_Object window, struct window_config *config, int i)
5654 for (; !NILP (window); window = w->next)
5656 struct saved_window *p = SAVED_WINDOW_N (config, i);
5658 w = XWINDOW (window);
5661 p->buffer = w->buffer;
5662 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5663 WINDOW_TOP (p) = WINDOW_TOP (w);
5664 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5665 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5666 p->hscroll = w->hscroll;
5667 p->modeline_hscroll = w->modeline_hscroll;
5669 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5670 #include "winslots.h"
5672 if (!NILP (w->buffer))
5674 /* Save w's value of point in the window configuration.
5675 If w is the selected window, then get the value of point
5676 from the buffer; pointm is garbage in the selected window. */
5677 if (EQ (window, Fselected_window (Qnil)))
5679 p->pointm = noseeum_make_marker ();
5680 Fset_marker (p->pointm,
5681 make_int (BUF_PT (XBUFFER (w->buffer))),
5685 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5687 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5688 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5689 p->start_at_line_beg = w->start_at_line_beg;
5691 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5699 p->start_at_line_beg = 0;
5702 if (NILP (w->parent))
5703 p->parent_index = -1;
5705 p->parent_index = saved_window_index (w->parent, config, i);
5709 p->prev_index = saved_window_index (w->prev, config, i);
5710 if (!NILP (w->vchild))
5711 i = save_window_save (w->vchild, config, i);
5712 if (!NILP (w->hchild))
5713 i = save_window_save (w->hchild, config, i);
5720 /* Added to doc string:
5722 This also records the currently selected frame, and FRAME's focus
5723 redirection (see `redirect-frame-focus').
5728 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5729 Return an object representing the current window configuration of FRAME.
5730 If FRAME is nil or omitted, use the selected frame.
5731 This describes the number of windows, their sizes and current buffers,
5732 and for each displayed buffer, where display starts, and the positions of
5733 point and mark. An exception is made for point in the current buffer:
5734 its value is -not- saved.
5739 struct frame *f = decode_frame (frame);
5740 struct window_config *config;
5741 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5743 int real_font_height;
5745 if (n_windows <= countof (Vwindow_configuration_free_list))
5746 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5747 (Vwindow_configuration_free_list
5750 /* More than ten windows; just allocate directly */
5751 config = (struct window_config *)
5752 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5753 &lrecord_window_configuration);
5754 XSETWINDOW_CONFIGURATION (result, config);
5756 config->frame_width = FRAME_WIDTH (f);
5757 config->frame_height = FRAME_HEIGHT (f); */
5758 /* When using `push-window-configuration', often the minibuffer ends
5759 up as the selected window because functions run as the result of
5760 user interaction e.g. hyper-apropos. It seems to me the sensible
5761 thing to do is not record the minibuffer here. */
5762 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5763 config->current_window = FRAME_SELECTED_WINDOW (f);
5765 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5766 XSETBUFFER (config->current_buffer, current_buffer);
5767 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5768 config->root_window = FRAME_ROOT_WINDOW (f);
5769 config->min_height = window_min_height;
5770 config->min_width = window_min_width;
5771 config->saved_windows_count = n_windows;
5772 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5774 /* save the minibuffer height using the heuristics from
5775 change_frame_size_1 */
5777 XSETFRAME (frame, f); /* frame could have been nil ! */
5778 default_face_height_and_width (frame, &real_font_height, 0);
5779 assert(real_font_height > 0);
5781 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5782 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5785 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5786 - (minibuf_height / real_font_height ) : /* lines */
5787 minibuf_height; /* pixels */
5793 save_window_excursion_unwind (Lisp_Object window_config)
5795 Lisp_Object val = Fset_window_configuration (window_config);
5796 free_window_configuration (window_config);
5800 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5801 Execute body, preserving window sizes and contents.
5802 Restores which buffer appears in which window, where display starts,
5803 as well as the current buffer.
5804 Does not restore the value of point in current buffer.
5808 /* This function can GC */
5810 int speccount = specpdl_depth ();
5812 record_unwind_protect (save_window_excursion_unwind,
5813 Fcurrent_window_configuration (Qnil));
5814 val = Fprogn (args);
5815 return unbind_to (speccount, val);
5818 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5819 Return the horizontal pixel position of POS in window.
5820 Beginning of line is column 0. This is calculated using the redisplay
5821 display tables. If WINDOW is nil, the current window is assumed.
5822 If POS is nil, point is assumed. Note that POS must be visible for
5823 a non-nil result to be returned.
5827 struct window* w = decode_window (window);
5828 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5830 struct display_line *dl = 0;
5831 struct display_block *db = 0;
5832 struct rune* rb = 0;
5833 int y = w->last_point_y[CURRENT_DISP];
5834 int x = w->last_point_x[CURRENT_DISP];
5836 if (MINI_WINDOW_P (w))
5839 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5845 pos = Fwindow_point (window);
5850 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5855 for (i = first_line; i < Dynarr_length (dla); i++)
5857 dl = Dynarr_atp (dla, i);
5858 /* find the vertical location first */
5859 if (point >= dl->bufpos && point <= dl->end_bufpos)
5861 db = get_display_block_from_line (dl, TEXT);
5862 for (i = 0; i < Dynarr_length (db->runes); i++)
5864 rb = Dynarr_atp (db->runes, i);
5865 if (point <= rb->bufpos)
5877 /* optimized case */
5878 dl = Dynarr_atp (dla, y);
5879 db = get_display_block_from_line (dl, TEXT);
5881 if (x >= Dynarr_length (db->runes))
5884 rb = Dynarr_atp (db->runes, x);
5887 return make_int (rb->xpos - WINDOW_LEFT (w));
5892 /* This is short and simple in elisp, but... it was written to debug
5893 problems purely on the C side. That is where we need to call it so
5896 debug_print_window (Lisp_Object window, int level)
5899 Lisp_Object child = Fwindow_first_vchild (window);
5902 child = Fwindow_first_hchild (window);
5904 for (i = level; i > 0; i--)
5907 stderr_out ("#<window");
5909 Lisp_Object buffer = XWINDOW (window)->buffer;
5910 if (!NILP (buffer) && BUFFERP (buffer))
5911 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5913 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
5915 while (!NILP (child))
5917 debug_print_window (child, level + 1);
5918 child = Fwindow_next_child (child);
5922 void debug_print_windows (struct frame *f);
5924 debug_print_windows (struct frame *f)
5926 debug_print_window (f->root_window, 0);
5927 putc ('\n', stderr);
5929 #endif /* DEBUG_XEMACS */
5932 /************************************************************************/
5933 /* initialization */
5934 /************************************************************************/
5937 syms_of_window (void)
5939 INIT_LRECORD_IMPLEMENTATION (window);
5940 INIT_LRECORD_IMPLEMENTATION (window_configuration);
5942 defsymbol (&Qwindowp, "windowp");
5943 defsymbol (&Qwindow_live_p, "window-live-p");
5944 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5945 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5946 defsymbol (&Qdisplay_buffer, "display-buffer");
5948 #ifdef MEMORY_USAGE_STATS
5949 defsymbol (&Qface_cache, "face-cache");
5950 defsymbol (&Qglyph_cache, "glyph-cache");
5951 defsymbol (&Qline_start_cache, "line-start-cache");
5952 #ifdef HAVE_SCROLLBARS
5953 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5955 defsymbol (&Qother_redisplay, "other-redisplay");
5956 /* Qother in general.c */
5959 DEFSUBR (Fselected_window);
5960 DEFSUBR (Flast_nonminibuf_window);
5961 DEFSUBR (Fminibuffer_window);
5962 DEFSUBR (Fwindow_minibuffer_p);
5964 DEFSUBR (Fwindow_live_p);
5965 DEFSUBR (Fwindow_first_hchild);
5966 DEFSUBR (Fwindow_first_vchild);
5967 DEFSUBR (Fwindow_next_child);
5968 DEFSUBR (Fwindow_previous_child);
5969 DEFSUBR (Fwindow_parent);
5970 DEFSUBR (Fwindow_lowest_p);
5971 DEFSUBR (Fwindow_truncated_p);
5972 DEFSUBR (Fwindow_highest_p);
5973 DEFSUBR (Fwindow_leftmost_p);
5974 DEFSUBR (Fwindow_rightmost_p);
5975 DEFSUBR (Fpos_visible_in_window_p);
5976 DEFSUBR (Fwindow_buffer);
5977 DEFSUBR (Fwindow_frame);
5978 DEFSUBR (Fwindow_height);
5979 DEFSUBR (Fwindow_displayed_height);
5980 DEFSUBR (Fwindow_width);
5981 DEFSUBR (Fwindow_full_width);
5982 DEFSUBR (Fwindow_pixel_height);
5983 DEFSUBR (Fwindow_pixel_width);
5984 DEFSUBR (Fwindow_text_area_height);
5985 DEFSUBR (Fwindow_text_area_pixel_height);
5986 DEFSUBR (Fwindow_displayed_text_pixel_height);
5987 DEFSUBR (Fwindow_text_area_pixel_width);
5988 DEFSUBR (Fwindow_hscroll);
5989 DEFSUBR (Fset_window_hscroll);
5990 DEFSUBR (Fmodeline_hscroll);
5991 DEFSUBR (Fset_modeline_hscroll);
5992 #if 0 /* bogus FSF crock */
5993 DEFSUBR (Fwindow_redisplay_end_trigger);
5994 DEFSUBR (Fset_window_redisplay_end_trigger);
5996 DEFSUBR (Fwindow_pixel_edges);
5997 DEFSUBR (Fwindow_text_area_pixel_edges);
5998 DEFSUBR (Fwindow_point);
5999 DEFSUBR (Fwindow_start);
6000 DEFSUBR (Fwindow_end);
6001 DEFSUBR (Fwindow_last_line_visible_height);
6002 DEFSUBR (Fset_window_point);
6003 DEFSUBR (Fset_window_start);
6004 DEFSUBR (Fwindow_dedicated_p);
6005 DEFSUBR (Fset_window_dedicated_p);
6006 DEFSUBR (Fnext_window);
6007 DEFSUBR (Fprevious_window);
6008 DEFSUBR (Fnext_vertical_window);
6009 DEFSUBR (Fother_window);
6010 DEFSUBR (Fget_lru_window);
6011 DEFSUBR (Fget_largest_window);
6012 DEFSUBR (Fget_buffer_window);
6013 DEFSUBR (Fwindow_left_margin_pixel_width);
6014 DEFSUBR (Fwindow_right_margin_pixel_width);
6015 DEFSUBR (Fdelete_other_windows);
6016 DEFSUBR (Fdelete_windows_on);
6017 DEFSUBR (Freplace_buffer_in_windows);
6018 DEFSUBR (Fdelete_window);
6019 DEFSUBR (Fset_window_buffer);
6020 DEFSUBR (Fselect_window);
6021 DEFSUBR (Fsplit_window);
6022 DEFSUBR (Fenlarge_window);
6023 DEFSUBR (Fenlarge_window_pixels);
6024 DEFSUBR (Fshrink_window);
6025 DEFSUBR (Fshrink_window_pixels);
6026 DEFSUBR (Fscroll_up);
6027 DEFSUBR (Fscroll_down);
6028 DEFSUBR (Fscroll_left);
6029 DEFSUBR (Fscroll_right);
6030 DEFSUBR (Fother_window_for_scrolling);
6031 DEFSUBR (Fscroll_other_window);
6032 DEFSUBR (Fcenter_to_window_line);
6033 DEFSUBR (Fmove_to_window_line);
6034 #ifdef MEMORY_USAGE_STATS
6035 DEFSUBR (Fwindow_memory_usage);
6037 DEFSUBR (Fwindow_configuration_p);
6038 DEFSUBR (Fset_window_configuration);
6039 DEFSUBR (Fcurrent_window_configuration);
6040 DEFSUBR (Fsave_window_excursion);
6041 DEFSUBR (Fcurrent_pixel_column);
6045 reinit_vars_of_window (void)
6048 /* Make sure all windows get marked */
6049 minibuf_window = Qnil;
6050 staticpro_nodump (&minibuf_window);
6052 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6054 Vwindow_configuration_free_list[i] =
6055 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6056 &lrecord_window_configuration);
6057 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6062 vars_of_window (void)
6064 reinit_vars_of_window ();
6066 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6067 *Non-nil means to scroll if point lands on a line which is clipped.
6069 scroll_on_clipped_lines = 1;
6071 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6072 See `temp-buffer-show-function'.
6074 Vtemp_buffer_show_hook = Qnil;
6076 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6077 Non-nil means call as function to display a help buffer.
6078 The function is called with one argument, the buffer to be displayed.
6079 Used by `with-output-to-temp-buffer'.
6080 If this function is used, then it must do the entire job of showing
6081 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6082 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6084 Vtemp_buffer_show_function = Qnil;
6086 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6087 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6089 Vminibuffer_scroll_window = Qnil;
6091 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6092 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6094 Vother_window_scroll_buffer = Qnil;
6096 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6097 *Number of pixels to scroll by per requested line.
6098 If nil then normal line scrolling occurs regardless of line height.
6099 If t then scrolling is done in increments equal to the height of the default face.
6101 Vwindow_pixel_scroll_increment = Qt;
6103 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6104 *Number of lines of continuity when scrolling by screenfuls.
6106 next_screen_context_lines = 2;
6108 DEFVAR_INT ("window-min-height", &window_min_height /*
6109 *Delete any window less than this tall (including its modeline).
6111 window_min_height = 4;
6113 DEFVAR_INT ("window-min-width", &window_min_width /*
6114 *Delete any window less than this wide.
6116 window_min_width = 10;
6120 specifier_vars_of_window (void)
6122 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6123 *How thick to draw 3D shadows around modelines.
6124 If this is set to 0, modelines will be the traditional 2D. Sizes above
6125 10 will be accepted but the maximum thickness that will be drawn is 10.
6126 This is a specifier; use `set-specifier' to change it.
6128 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6129 /* The initial value for modeline-shadow-thickness is 2, but if the
6130 user removes all specifications we provide a fallback value of 0,
6131 which is probably what was expected. */
6132 set_specifier_fallback (Vmodeline_shadow_thickness,
6133 list1 (Fcons (Qnil, Qzero)));
6134 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6136 set_specifier_caching (Vmodeline_shadow_thickness,
6137 offsetof (struct window, modeline_shadow_thickness),
6138 modeline_shadow_thickness_changed,
6141 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6142 *Whether the modeline should be displayed.
6143 This is a specifier; use `set-specifier' to change it.
6145 Vhas_modeline_p = Fmake_specifier (Qboolean);
6146 set_specifier_fallback (Vhas_modeline_p,
6147 list1 (Fcons (Qnil, Qt)));
6148 set_specifier_caching (Vhas_modeline_p,
6149 offsetof (struct window, has_modeline_p),
6150 /* #### It's strange that we need a special
6151 flag to indicate that the shadow-thickness
6152 has changed, but not one to indicate that
6153 the modeline has been turned off or on. */
6154 some_window_value_changed,
6157 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6158 &Vvertical_divider_always_visible_p /*
6159 *Should XEmacs always display vertical dividers between windows.
6161 When this is non-nil, vertical dividers are always shown, and are
6162 draggable. When it is nil, vertical dividers are shown only when
6163 there are no scrollbars in between windows, and are not draggable.
6165 This is a specifier; use `set-specifier' to change it.
6167 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6168 set_specifier_fallback (Vvertical_divider_always_visible_p,
6169 list1 (Fcons (Qnil, Qt)));
6170 set_specifier_caching (Vvertical_divider_always_visible_p,
6171 offsetof (struct window,
6172 vertical_divider_always_visible_p),
6173 vertical_divider_changed_in_window,
6176 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6177 *How thick to draw 3D shadows around vertical dividers.
6178 This is a specifier; use `set-specifier' to change it.
6180 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6181 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6182 list1 (Fcons (Qnil, Qzero)));
6183 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6185 set_specifier_caching (Vvertical_divider_shadow_thickness,
6186 offsetof (struct window,
6187 vertical_divider_shadow_thickness),
6188 vertical_divider_changed_in_window,
6190 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6191 *The width of the vertical dividers, not including shadows.
6193 For TTY windows, divider line is always one character wide. When
6194 instance of this specifier is zero in a TTY window, no divider is
6195 drawn at all between windows. When non-zero, a one character wide
6196 divider is displayed.
6198 This is a specifier; use `set-specifier' to change it.
6201 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6203 Lisp_Object fb = Qnil;
6205 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6207 #ifdef HAVE_X_WINDOWS
6208 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6210 #ifdef HAVE_MS_WINDOWS
6211 /* #### This should be made magic and made to obey system settings */
6212 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6214 set_specifier_fallback (Vvertical_divider_line_width, fb);
6216 set_specifier_caching (Vvertical_divider_line_width,
6217 offsetof (struct window,
6218 vertical_divider_line_width),
6219 vertical_divider_changed_in_window,
6222 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6223 *How much space to leave around the vertical dividers.
6225 In TTY windows, spacing is always zero, and the value of this
6226 specifier is ignored.
6228 This is a specifier; use `set-specifier' to change it.
6230 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6232 Lisp_Object fb = Qnil;
6234 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6236 #ifdef HAVE_X_WINDOWS
6237 /* #### 3D dividers look great on MS Windows with spacing = 0.
6238 Should not the same value be the fallback under X? - kkm */
6239 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6241 #ifdef HAVE_MS_WINDOWS
6242 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6244 set_specifier_fallback (Vvertical_divider_spacing, fb);
6246 set_specifier_caching (Vvertical_divider_spacing,
6247 offsetof (struct window, vertical_divider_spacing),
6248 vertical_divider_changed_in_window,