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 extern int allow_deletion_of_last_visible_frame;
55 EXFUN (Fnext_window, 4);
57 static int window_pixel_width_to_char_width (struct window *w,
59 int include_margins_p);
60 static int window_char_width_to_pixel_width (struct window *w,
62 int include_margins_p);
63 static int window_pixel_height_to_char_height (struct window *w,
65 int include_gutters_p);
66 static int window_char_height_to_pixel_height (struct window *w,
68 int include_gutters_p);
69 static void change_window_height (Lisp_Object window, int delta,
70 Lisp_Object horizontalp, int inpixels);
72 /* Thickness of shadow border around 3d modelines. */
73 Lisp_Object Vmodeline_shadow_thickness;
75 /* Whether vertical dividers are draggable and displayed */
76 Lisp_Object Vvertical_divider_always_visible_p;
78 /* Whether a modeline should be displayed. */
79 Lisp_Object Vhas_modeline_p;
81 /* Thickness of shadow border around vertical dividers. */
82 Lisp_Object Vvertical_divider_shadow_thickness;
84 /* Divider surface width (not counting 3-d borders) */
85 Lisp_Object Vvertical_divider_line_width;
87 /* Spacing between outer edge of divider border and window edge */
88 Lisp_Object Vvertical_divider_spacing;
90 /* How much to scroll by per-line. */
91 Lisp_Object Vwindow_pixel_scroll_increment;
93 /* Scroll if point lands on the bottom line and that line is partially
95 int scroll_on_clipped_lines;
97 /* The minibuffer window of the selected frame.
98 Note that you cannot test for minibufferness of an arbitrary window
99 by comparing against this; but you can test for minibufferness of
100 the selected window. */
101 Lisp_Object minibuf_window;
103 /* Non-nil means it is the window for C-M-v to scroll
104 when the minibuffer is selected. */
105 Lisp_Object Vminibuffer_scroll_window;
107 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
108 Lisp_Object Vother_window_scroll_buffer;
110 /* Non-nil means it's the function to call to display temp buffers. */
111 Lisp_Object Vtemp_buffer_show_function;
113 Lisp_Object Vtemp_buffer_show_hook;
115 /* If a window gets smaller than either of these, it is removed. */
116 Fixnum window_min_height;
117 Fixnum window_min_width;
119 /* Hook run at end of temp_output_buffer_show. */
120 Lisp_Object Qtemp_buffer_show_hook;
122 /* Number of lines of continuity in scrolling by screenfuls. */
123 Fixnum next_screen_context_lines;
125 /* List of freed window configurations with 1 - 10 windows. */
126 static Lisp_Object Vwindow_configuration_free_list[10];
128 Lisp_Object Qtruncate_partial_width_windows;
130 #define SET_LAST_MODIFIED(w, cache_too) \
132 (w)->last_modified[CURRENT_DISP] = Qzero; \
133 (w)->last_modified[DESIRED_DISP] = Qzero; \
134 (w)->last_modified[CMOTION_DISP] = Qzero; \
136 (w)->line_cache_last_updated = Qzero; \
139 #define SET_LAST_FACECHANGE(w) \
141 (w)->last_facechange[CURRENT_DISP] = Qzero; \
142 (w)->last_facechange[DESIRED_DISP] = Qzero; \
143 (w)->last_facechange[CMOTION_DISP] = Qzero; \
147 #define MARK_DISP_VARIABLE(field) \
148 mark_object (window->field[CURRENT_DISP]); \
149 mark_object (window->field[DESIRED_DISP]); \
150 mark_object (window->field[CMOTION_DISP]);
153 mark_window (Lisp_Object obj)
155 struct window *window = XWINDOW (obj);
156 mark_object (window->frame);
157 mark_object (window->mini_p);
158 mark_object (window->next);
159 mark_object (window->prev);
160 mark_object (window->hchild);
161 mark_object (window->vchild);
162 mark_object (window->parent);
163 mark_object (window->buffer);
164 MARK_DISP_VARIABLE (start);
165 MARK_DISP_VARIABLE (pointm);
166 mark_object (window->sb_point); /* #### move to scrollbar.c? */
167 mark_object (window->use_time);
168 MARK_DISP_VARIABLE (last_modified);
169 MARK_DISP_VARIABLE (last_point);
170 MARK_DISP_VARIABLE (last_start);
171 MARK_DISP_VARIABLE (last_facechange);
172 mark_object (window->line_cache_last_updated);
173 mark_object (window->redisplay_end_trigger);
174 mark_object (window->subwindow_instance_cache);
176 mark_face_cachels (window->face_cachels);
177 mark_glyph_cachels (window->glyph_cachels);
179 #define WINDOW_SLOT(slot, compare) mark_object (window->slot)
180 #include "winslots.h"
186 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
191 error ("printing unreadable object #<window 0x%x>",
192 XWINDOW (obj)->header.uid);
194 write_c_string ("#<window", printcharfun);
195 if (!NILP (XWINDOW (obj)->buffer))
197 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
198 write_c_string (" on ", printcharfun);
199 print_internal (name, printcharfun, 1);
201 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
202 write_c_string (buf, printcharfun);
206 finalize_window (void *header, int for_disksave)
208 struct window *w = (struct window *) header;
210 if (w->line_start_cache)
212 Dynarr_free (w->line_start_cache);
213 w->line_start_cache = 0;
220 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
222 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
223 if (cachel->merged_faces)
225 Dynarr_free (cachel->merged_faces);
226 cachel->merged_faces = 0;
229 Dynarr_free (w->face_cachels);
233 if (w->glyph_cachels)
235 Dynarr_free (w->glyph_cachels);
236 w->glyph_cachels = 0;
240 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
241 mark_window, print_window, finalize_window,
242 0, 0, 0, struct window);
245 #define INIT_DISP_VARIABLE(field, initialization) \
246 p->field[CURRENT_DISP] = initialization; \
247 p->field[DESIRED_DISP] = initialization; \
248 p->field[CMOTION_DISP] = initialization;
250 /* We have an implicit assertion that the first two elements (default
251 and modeline faces) are always present in the face_element_cache.
252 Normally redisplay ensures this. However, it is possible for a
253 window to get created and functions which reference these values
254 called before redisplay works with the window for the first time.
255 All callers of allocate_window should therefore call
256 reset_face_cachels on the created window. We can't do it
257 here because the window must have its frame pointer set or
258 reset_face_cachels will fail. */
260 allocate_window (void)
263 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
277 INIT_DISP_VARIABLE (start, Fmake_marker ());
278 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
279 p->sb_point = Fmake_marker ();
281 INIT_DISP_VARIABLE (last_modified, Qzero);
282 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
283 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
284 INIT_DISP_VARIABLE (last_facechange, Qzero);
285 p->face_cachels = Dynarr_new (face_cachel);
286 p->glyph_cachels = Dynarr_new (glyph_cachel);
287 p->line_start_cache = Dynarr_new (line_start_cache);
288 p->subwindow_instance_cache = make_image_instance_cache_hash_table ();
290 p->line_cache_last_updated = Qzero;
291 INIT_DISP_VARIABLE (last_point_x, 0);
292 INIT_DISP_VARIABLE (last_point_y, 0);
293 INIT_DISP_VARIABLE (window_end_pos, 0);
294 p->redisplay_end_trigger = Qnil;
296 p->gutter_extent_modiff[0] = 0;
297 p->gutter_extent_modiff[1] = 0;
298 p->gutter_extent_modiff[2] = 0;
299 p->gutter_extent_modiff[3] = 0;
301 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
302 #include "winslots.h"
304 p->windows_changed = 1;
305 p->shadow_thickness_changed = 1;
309 #undef INIT_DISP_VARIABLE
312 * The redisplay structures used to be stored with each window. While
313 * they are logically something associated with frames they can't be
314 * stored there with a redisplay which handles variable height lines.
315 * Lines in horizontally split windows might not line up. So they get
316 * stored with the windows.
318 * The problem with this is window configurations. When restoring a
319 * window configuration it now becomes problematic to do an
320 * incremental redisplay. The solution is to store the redisplay
321 * structures with the frame as they should be but laid out in the
322 * same manner as the window structure. Thus is born the window
325 * It also becomes a convenient place to stick scrollbar instances
326 * since they extrapolate out to having the same problem described for
327 * the display structures.
330 /* Create a new window mirror structure and associated redisplay
332 static struct window_mirror *
333 new_window_mirror (struct frame *f)
335 struct window_mirror *t = xnew_and_zero (struct window_mirror);
339 t->current_display_lines = Dynarr_new (display_line);
340 t->desired_display_lines = Dynarr_new (display_line);
343 #ifdef HAVE_SCROLLBARS
344 t->scrollbar_vertical_instance = NULL;
345 t->scrollbar_horizontal_instance = NULL;
351 /* Synchronize the mirror structure with a given window structure.
352 This is normally called from update_frame_window_mirror with a
353 starting window of f->root_window. */
354 static struct window_mirror *
355 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
361 free_window_mirror (mir);
368 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
370 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
371 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
372 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
375 * If the redisplay structs are not empty and the mirror has
376 * children, then this mirror structure was formerly being used for
377 * display but is no longer. Reset its current display structs so
378 * that redisplay doesn't accidentally think they are accurate if it
379 * is later used for display purposes once again. Also, mark the
380 * scrollbar instance as not active.
382 if (mir->vchild || mir->hchild)
384 /* The redisplay structures are big. Leaving them around in
385 non-leaf windows can add up to a lot of wasted space. So
387 free_display_structs (mir);
388 mir->current_display_lines = Dynarr_new (display_line);
389 mir->desired_display_lines = Dynarr_new (display_line);
391 #ifdef HAVE_SCROLLBARS
392 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
400 /* Given a window mirror, determine which real window it contains the
401 redisplay structures for. */
403 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
404 struct window_mirror *mir)
406 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
410 if (!NILP (XWINDOW (win)->vchild))
413 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
417 if (!NILP (XWINDOW (win)->hchild))
420 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
429 /* Given a real window, find the mirror structure which contains its
430 redisplay structures. */
431 static struct window_mirror *
432 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
435 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
437 if (w == XWINDOW (win))
440 if (!NILP (XWINDOW (win)->vchild))
442 struct window_mirror *retval =
443 find_window_mirror_internal (XWINDOW (win)->vchild,
445 if (retval) return retval;
448 if (!NILP (XWINDOW (win)->hchild))
450 struct window_mirror *retval =
451 find_window_mirror_internal (XWINDOW (win)->hchild,
453 if (retval) return retval;
460 /* Update the mirror structure for the given frame. */
462 update_frame_window_mirror (struct frame *f)
464 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
468 /* Free a given mirror structure along with all of its children as
469 well as their associated display structures. */
471 free_window_mirror (struct window_mirror *mir)
475 struct window_mirror *prev = mir;
476 if (mir->hchild) free_window_mirror (mir->hchild);
477 if (mir->vchild) free_window_mirror (mir->vchild);
478 #ifdef HAVE_SCROLLBARS
479 release_window_mirror_scrollbars (mir);
481 free_display_structs (mir);
487 /* Given a mirror structure, return the window it mirrors. Calls
488 real_window_internal to do most of the work. */
490 real_window (struct window_mirror *mir, int no_abort)
492 Lisp_Object retval = real_window_internal (mir->frame->root_window,
493 mir->frame->root_mirror, mir);
494 if (NILP (retval) && !no_abort)
500 /* Given a real window, return its mirror structure. Calls
501 find_window_mirror_internal to do all of the work. */
502 struct window_mirror *
503 find_window_mirror (struct window *w)
505 struct frame *f = XFRAME (w->frame);
507 update_frame_window_mirror (f);
508 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
511 /*****************************************************************************
512 find_window_by_pixel_pos
514 Given a pixel position relative to a frame, find the window at that
516 ****************************************************************************/
518 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
523 for (; !NILP (win); win = XWINDOW (win)->next)
527 if (!NILP (XWINDOW (win)->vchild))
529 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
532 if (!NILP (XWINDOW (win)->hchild))
534 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
538 if (pix_x >= WINDOW_LEFT (w)
539 && pix_x <= WINDOW_RIGHT (w)
540 && pix_y >= WINDOW_TOP (w)
541 && pix_y <= WINDOW_BOTTOM (w))
547 /* Return a pointer to the display structures for the given window. */
548 display_line_dynarr *
549 window_display_lines (struct window *w, int which)
551 struct window_mirror *t;
553 if (XFRAME (w->frame)->mirror_dirty)
554 update_frame_window_mirror (XFRAME (w->frame));
555 t = find_window_mirror (w);
559 if (which == CURRENT_DISP)
560 return t->current_display_lines;
561 else if (which == DESIRED_DISP)
562 return t->desired_display_lines;
563 else if (which == CMOTION_DISP)
564 /* The CMOTION_DISP display lines are global. */
565 return cmotion_display_lines;
569 return 0; /* shut up compiler */
573 window_display_buffer (struct window *w)
575 struct window_mirror *t;
577 if (XFRAME (w->frame)->mirror_dirty)
578 update_frame_window_mirror (XFRAME (w->frame));
579 t = find_window_mirror (w);
587 set_window_display_buffer (struct window *w, struct buffer *b)
589 struct window_mirror *t;
591 if (XFRAME (w->frame)->mirror_dirty)
592 update_frame_window_mirror (XFRAME (w->frame));
593 t = find_window_mirror (w);
601 /* Determining a window's position based solely on its pixel
602 positioning doesn't work. Instead, we do it the intelligent way,
603 by checking its positioning in the window hierarchy. */
605 window_is_leftmost (struct window *w)
607 Lisp_Object parent, current_ancestor, window;
609 XSETWINDOW (window, w);
611 parent = XWINDOW (window)->parent;
612 current_ancestor = window;
614 while (!NILP (parent))
616 if (!NILP (XWINDOW (parent)->hchild) &&
617 !EQ (XWINDOW (parent)->hchild, current_ancestor))
620 current_ancestor = parent;
621 parent = XWINDOW (parent)->parent;
628 window_is_rightmost (struct window *w)
630 Lisp_Object parent, current_ancestor, window;
632 XSETWINDOW (window, w);
634 parent = XWINDOW (window)->parent;
635 current_ancestor = window;
637 while (!NILP (parent))
639 if (!NILP (XWINDOW (parent)->hchild)
640 && !NILP (XWINDOW (current_ancestor)->next))
643 current_ancestor = parent;
644 parent = XWINDOW (parent)->parent;
651 window_full_width_p (struct window *w)
653 return window_is_leftmost (w) && window_is_rightmost (w);
657 window_is_highest (struct window *w)
659 Lisp_Object parent, current_ancestor, window;
661 XSETWINDOW (window, w);
663 parent = XWINDOW (window)->parent;
664 current_ancestor = window;
666 while (!NILP (parent))
668 if (!NILP (XWINDOW (parent)->vchild) &&
669 !EQ (XWINDOW (parent)->vchild, current_ancestor))
672 current_ancestor = parent;
673 parent = XWINDOW (parent)->parent;
676 /* This is really to catch the minibuffer but we make it generic in
677 case we ever change things around to let the minibuffer be on top. */
678 if (NILP (XWINDOW (current_ancestor)->prev))
685 window_is_lowest (struct window *w)
687 Lisp_Object parent, current_ancestor, window;
689 XSETWINDOW (window, w);
691 parent = XWINDOW (window)->parent;
692 current_ancestor = window;
694 while (!NILP (parent))
696 if (!NILP (XWINDOW (parent)->vchild)
697 && !NILP (XWINDOW (current_ancestor)->next))
700 current_ancestor = parent;
701 parent = XWINDOW (parent)->parent;
707 #if 0 /* not currently used */
710 window_full_height_p (struct window *w)
712 return window_is_highest (w) && window_is_lowest (w);
718 window_truncation_on (struct window *w)
720 /* Minibuffer windows are never truncated.
721 #### is this the right way ? */
722 if (MINI_WINDOW_P (w))
725 /* Horizontally scrolled windows are truncated. */
729 /* If truncate_partial_width_windows is true and the window is not
730 the full width of the frame it is truncated. */
731 if (!NILP (symbol_value_in_buffer (Qtruncate_partial_width_windows,
733 && !(window_is_leftmost (w) && window_is_rightmost (w)))
736 /* If the window's buffer's value of truncate_lines is non-nil, then
737 the window is truncated. */
738 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
744 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
745 Returns non-nil if text in the window is truncated.
749 struct window *w = decode_window (window);
751 return window_truncation_on (w) ? Qt : Qnil;
756 have_undivided_common_edge (struct window *w_right, void *closure)
758 struct window *w_left = (struct window *) closure;
759 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
760 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
761 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
762 #ifdef HAVE_SCROLLBARS
763 && (NILP (w_right->scrollbar_on_left_p)
764 || NILP (w_right->vertical_scrollbar_visible_p)
765 || ZEROP (w_right->scrollbar_width))
771 window_needs_vertical_divider_1 (struct window *w)
773 /* Never if we're on the right */
774 if (window_is_rightmost (w))
777 /* Always if draggable */
778 if (!NILP (w->vertical_divider_always_visible_p))
781 #ifdef HAVE_SCROLLBARS
782 /* Our right scrollbar is enough to separate us at the right */
783 if (NILP (w->scrollbar_on_left_p)
784 && !NILP (w->vertical_scrollbar_visible_p)
785 && !ZEROP (w->scrollbar_width))
789 /* Ok. to determine whether we need a divider on the left, we must
790 check that our right neighbor windows have scrollbars on their
791 left sides. We must check all such windows which have common
792 left edge with our window's right edge. */
793 return map_windows (XFRAME (WINDOW_FRAME (w)),
794 have_undivided_common_edge, (void*)w);
798 window_needs_vertical_divider (struct window *w)
800 if (!w->need_vertical_divider_valid_p)
802 w->need_vertical_divider_p =
803 window_needs_vertical_divider_1 (w);
804 w->need_vertical_divider_valid_p = 1;
806 return w->need_vertical_divider_p;
809 /* Called from invalidate_vertical_divider_cache_in_frame */
811 invalidate_vertical_divider_cache_in_window (struct window *w,
814 w->need_vertical_divider_valid_p = 0;
818 /* Calculate width of vertical divider, including its shadows
819 and spacing. The returned value is effectively the distance
820 between adjacent window edges. This function does not check
821 whether a window needs a vertical divider, so the returned
822 value is a "theoretical" one */
824 window_divider_width (struct window *w)
826 /* the shadow thickness can be negative. This means that the divider
827 will have a depressed look */
829 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
831 XINT (w->vertical_divider_line_width)
832 + 2 * XINT (w->vertical_divider_spacing)
833 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
835 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
839 window_scrollbar_width (struct window *w)
841 #ifdef HAVE_SCROLLBARS
842 if (!WINDOW_WIN_P (w)
845 || NILP (w->vertical_scrollbar_visible_p))
846 /* #### when does NILP (w->buffer) happen? */
849 return XINT (w->scrollbar_width);
852 #endif /* HAVE_SCROLLBARS */
855 /* Horizontal scrollbars are only active on windows with truncation
858 window_scrollbar_height (struct window *w)
860 #ifdef HAVE_SCROLLBARS
861 if (!WINDOW_WIN_P (w)
864 || NILP (w->horizontal_scrollbar_visible_p)
865 || !window_truncation_on (w))
868 return XINT (w->scrollbar_height);
871 #endif /* HAVE_SCROLLBARS */
875 window_modeline_height (struct window *w)
877 struct frame *f = XFRAME (w->frame);
880 if (MINI_WINDOW_P (w) || NILP (w->buffer))
884 else if (!WINDOW_HAS_MODELINE_P (w))
886 if (window_scrollbar_height (w))
890 modeline_height = FRAMEMETH (f, divider_height, ());
892 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
893 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
902 display_line_dynarr *dla;
904 /* We don't force a regeneration of the modeline here.
905 Instead it is now a precondition that any function calling
906 this should make sure that one of these structures is
907 up-to-date. In practice this only affects two internal
908 redisplay functions, regenerate_window and
909 regenerate_window_point_center. */
910 /* We check DESIRED_DISP because if it is valid it is more
911 up-to-date than CURRENT_DISP. For calls to this outside
912 of redisplay it doesn't matter which structure we check
913 since there is a redisplay condition that these
914 structures be identical outside of redisplay. */
915 dla = window_display_lines (w, DESIRED_DISP);
916 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
917 modeline_height = (Dynarr_atp (dla, 0)->ascent +
918 Dynarr_atp (dla, 0)->descent);
921 dla = window_display_lines (w, CURRENT_DISP);
922 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
923 modeline_height = (Dynarr_atp (dla, 0)->ascent +
924 Dynarr_atp (dla, 0)->descent);
926 /* This should be an ABORT except I'm not yet 100%
927 confident that it won't ever get hit (though I
928 haven't been able to trigger it). It is extremely
929 unlikely to cause any noticeable problem and even if
930 it does it will be a minor display glitch. */
931 /* #### Bullshit alert. It does get hit and it causes
932 noticeable glitches. real_current_modeline_height
933 is a kludge to fix this for 19.14. */
934 modeline_height = real_current_modeline_height (w);
937 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
938 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
942 return modeline_height;
945 /*****************************************************************************
946 margin_width_internal
948 For a given window, return the width in pixels of the specified margin.
949 ****************************************************************************/
951 margin_width_internal (struct window *w, int left_margin)
954 int window_cwidth = window_char_width (w, 1);
959 /* We might be getting called on a non-leaf. */
960 if (NILP (w->buffer))
963 /* The minibuffer never has margins. */
964 if (MINI_WINDOW_P (w))
967 XSETWINDOW (window, w);
968 b = XBUFFER (w->buffer);
969 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
970 XINT (w->right_margin_width));
972 default_face_height_and_width (window, 0, &font_width);
974 /* The left margin takes precedence over the right margin so we
975 subtract its width from the space available for the right
978 window_cwidth -= XINT (w->left_margin_width);
980 /* The margin cannot be wider than the window is. We allow the
981 value to be bigger since it is possible for the user to enlarge
982 the window such that the left margin value would no longer be too
983 big, but we won't return a value that is larger. */
984 if (margin_cwidth > window_cwidth)
985 margin_cwidth = window_cwidth;
987 /* At the user level the margin is always specified in characters.
988 Internally however it is manipulated in terms of pixels. */
989 return margin_cwidth * font_width;
993 window_left_margin_width (struct window *w)
995 return margin_width_internal (w, 1);
999 window_right_margin_width (struct window *w)
1001 return margin_width_internal (w, 0);
1004 /*****************************************************************************
1007 The gutters of a window are those areas in the boundary defined by
1008 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1009 do not contain text. Items which may be in the gutters include
1010 scrollbars, toolbars and modelines. The margin areas are not
1011 included. This is an exception made because redisplay special cases
1012 the handling of those areas in many places in such a way that
1013 including them in the gutter area would make life difficult.
1015 The size functions refer to height for the bottom and top gutters and
1016 width for the left and right gutters. The starting position
1017 functions refer to the Y coord for bottom and top gutters and the X
1018 coord for left and right gutters. All starting positions are
1019 relative to the frame, not the window.
1020 ****************************************************************************/
1023 window_top_window_gutter_height (struct window *w)
1025 if (!NILP (w->hchild) || !NILP (w->vchild))
1028 #ifdef HAVE_SCROLLBARS
1029 if (!NILP (w->scrollbar_on_top_p))
1030 return window_scrollbar_height (w);
1037 window_top_gutter_height (struct window *w)
1039 return window_top_window_gutter_height (w);
1043 window_bottom_window_gutter_height (struct window *w)
1047 if (!NILP (w->hchild) || !NILP (w->vchild))
1050 gutter = window_modeline_height (w);
1052 #ifdef HAVE_SCROLLBARS
1053 if (NILP (w->scrollbar_on_top_p))
1054 return window_scrollbar_height (w) + gutter;
1061 window_bottom_gutter_height (struct window *w)
1063 return window_bottom_window_gutter_height (w);
1067 window_left_window_gutter_width (struct window *w, int modeline)
1069 if (!NILP (w->hchild) || !NILP (w->vchild))
1072 #ifdef HAVE_SCROLLBARS
1073 if (!modeline && !NILP (w->scrollbar_on_left_p))
1074 return window_scrollbar_width (w);
1081 window_left_gutter_width (struct window *w, int modeline)
1083 return window_left_window_gutter_width (w, modeline);
1087 window_right_window_gutter_width (struct window *w, int modeline)
1091 if (!NILP (w->hchild) || !NILP (w->vchild))
1094 #ifdef HAVE_SCROLLBARS
1095 if (!modeline && NILP (w->scrollbar_on_left_p))
1096 gutter += window_scrollbar_width (w);
1099 if (window_needs_vertical_divider (w))
1100 gutter += window_divider_width (w);
1106 window_right_gutter_width (struct window *w, int modeline)
1108 return window_right_window_gutter_width (w, modeline);
1112 window_pixel_height (struct window* w)
1114 return WINDOW_HEIGHT (w);
1118 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1119 Return t if OBJECT is a window.
1123 return WINDOWP (object) ? Qt : Qnil;
1126 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1127 Return t if OBJECT is a window which is currently visible.
1131 return WINDOWP (object) && WINDOW_LIVE_P (XWINDOW (object))
1135 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1136 Return the window that the cursor now appears in and commands apply to.
1137 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1138 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1139 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1140 is a console, the selected frame on that console's selected device will
1141 be used. Otherwise, the selected frame is used.
1145 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1146 return Qnil; /* happens at startup */
1149 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1150 return FRAME_SELECTED_WINDOW (f);
1154 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1155 Return the last selected window that is not a minibuffer window.
1156 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1157 return the last non-minibuffer window used by that frame. If
1158 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1159 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1160 that console's selected device will be used. Otherwise, the selected
1165 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1166 return Qnil; /* happens at startup */
1169 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1170 return FRAME_LAST_NONMINIBUF_WINDOW (f);
1174 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1175 Return the window used now for minibuffers.
1176 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1177 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1178 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1179 is a console, the selected frame on that console's selected device will
1180 be used. Otherwise, the selected frame is used.
1184 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1187 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1188 Return non-nil if WINDOW is a minibuffer window.
1192 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1195 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1196 Return the first horizontal child of WINDOW, or nil.
1200 return decode_window (window)->hchild;
1203 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1204 Return the first vertical child of WINDOW, or nil.
1208 return decode_window (window)->vchild;
1211 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1212 Return the next window on the same level as WINDOW, or nil.
1216 return decode_window (window)->next;
1219 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1220 Return the previous window on the same level as WINDOW, or nil.
1224 return decode_window (window)->prev;
1227 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1228 Return the parent of WINDOW, or nil.
1232 return decode_window (window)->parent;
1235 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1236 Return non-nil if WINDOW is along the bottom of its frame.
1240 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1243 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1244 Return non-nil if WINDOW is along the top of its frame.
1248 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1251 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1252 Return non-nil if WINDOW is along the left edge of its frame.
1256 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1259 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1260 Return non-nil if WINDOW is along the right edge of its frame.
1264 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1267 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1268 Return t if position POS is currently on the frame in WINDOW.
1269 Returns nil if that position is scrolled vertically out of view.
1270 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1274 struct window *w = decode_window (window);
1275 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1277 struct buffer *buf = XBUFFER (w->buffer);
1280 posint = BUF_PT (buf);
1283 CHECK_INT_COERCE_MARKER (pos);
1284 posint = XINT (pos);
1287 if (posint < top || posint > BUF_ZV (buf))
1290 /* w->start can be out of range. If it is, do something reasonable. */
1291 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1294 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1299 decode_window (Lisp_Object window)
1302 return XWINDOW (Fselected_window (Qnil));
1304 CHECK_LIVE_WINDOW (window);
1305 return XWINDOW (window);
1308 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1309 Return the buffer that WINDOW is displaying.
1313 return decode_window (window)->buffer;
1316 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1317 Return the frame that window WINDOW is on.
1321 return decode_window (window)->frame;
1324 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1325 Return the number of default lines in WINDOW.
1326 This actually works by dividing the window's pixel height (including
1327 the modeline and horizontal scrollbar, if any) by the height of the
1328 default font; therefore, the number of displayed lines will probably
1330 Use `window-height' to get consistent results in geometry calculations.
1331 Use `window-displayed-height' to get the actual number of lines
1332 currently displayed in a window.
1334 The names are somewhat confusing; here's a table to help out:
1337 -------------------------------------------------------------------------
1339 (rows/columns) window-width window-text-area-height
1340 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1343 (rows/columns) window-full-width window-height
1344 (pixels) window-pixel-width window-pixel-height
1347 (rows/columns) ---- window-displayed-height
1348 (pixels) ---- window-displayed-text-pixel-height
1352 return make_int (window_char_height (decode_window (window), 1));
1355 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1356 Return the number of lines currently displayed in WINDOW.
1357 This counts the actual number of lines displayed in WINDOW
1358 \(as opposed to `window-height'). The modeline and horizontal
1359 scrollbar do not count as lines. If there is some blank space
1360 between the end of the buffer and the end of the window, this
1361 function pretends that there are lines of text in the default
1366 return make_int (window_displayed_height (decode_window (window)));
1369 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1370 Return the height of WINDOW in pixels. Defaults to current window.
1371 This includes the window's modeline and horizontal scrollbar (if any).
1375 return make_int (window_pixel_height (decode_window (window)));
1378 DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1379 Return the number of default lines in the text area of WINDOW.
1380 This actually works by dividing the window's text area pixel height (i.e.
1381 excluding the modeline and horizontal scrollbar, if any) by the height of the
1382 default font; therefore, the number of displayed lines will probably
1384 See also `window-height' and `window-displayed-height'.
1388 return make_int (window_char_height (decode_window (window), 0));
1391 DEFUN ("window-text-area-pixel-height",
1392 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1393 Return the height in pixels of the text-displaying portion of WINDOW.
1394 Unlike `window-pixel-height', the space occupied by the modeline and
1395 horizontal scrollbar, if any, is not counted.
1399 struct window *w = decode_window (window);
1401 return make_int (WINDOW_TEXT_HEIGHT (w));
1404 DEFUN ("window-displayed-text-pixel-height",
1405 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1406 Return the height in pixels of the text displayed in WINDOW.
1407 Unlike `window-text-area-pixel-height', any blank space below the
1408 end of the buffer is not included. If optional argument NOCLIPPED
1409 is non-nil, do not include space occupied by clipped lines.
1411 (window, noclipped))
1414 Bufpos start, eobuf;
1416 int hlimit, height, prev_height = -1;
1420 line_start_cache_dynarr *cache;
1423 window = Fselected_window (Qnil);
1425 CHECK_LIVE_WINDOW (window);
1426 w = XWINDOW (window);
1428 start = marker_position (w->start[CURRENT_DISP]);
1429 hlimit = WINDOW_TEXT_HEIGHT (w);
1430 eobuf = BUF_ZV (XBUFFER (w->buffer));
1432 default_face_height_and_width (window, &defheight, NULL);
1434 /* guess lines needed in line start cache + a few extra */
1435 needed = (hlimit + defheight-1) / defheight + 3;
1438 elt = point_in_line_start_cache (w, start, needed);
1439 assert (elt >= 0); /* in the cache */
1441 cache = w->line_start_cache;
1442 nelt = Dynarr_length (cache);
1445 for (i = elt; i < nelt; i++) {
1446 line = Dynarr_atp (cache, i)->height;
1448 if (height + line > hlimit)
1449 return make_int (!NILP (noclipped) ? height : hlimit);
1453 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1454 return make_int (height);
1457 /* get here => need more cache lines. try again. */
1458 assert(height > prev_height); /* progress? */
1459 prev_height = height;
1461 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1464 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1467 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1468 Return the number of display columns in WINDOW.
1469 This is the width that is usable columns available for text in WINDOW,
1470 and does not include vertical scrollbars, dividers, or the like. See also
1471 `window-full-width' and `window-height'.
1475 return make_int (window_char_width (decode_window (window), 0));
1478 DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1479 Return the total number of columns in WINDOW.
1480 This is like `window-width' but includes vertical scrollbars, dividers,
1485 return make_int (window_char_width (decode_window (window), 1));
1488 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1489 Return the width of WINDOW in pixels. Defaults to current window.
1493 return make_int (decode_window (window)->pixel_width);
1496 DEFUN ("window-text-area-pixel-width",
1497 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1498 Return the width in pixels of the text-displaying portion of WINDOW.
1499 Unlike `window-pixel-width', the space occupied by the vertical
1500 scrollbar or divider, if any, is not counted.
1504 struct window *w = decode_window (window);
1506 return make_int (WINDOW_TEXT_WIDTH (w));
1509 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1510 Return the number of columns by which WINDOW is scrolled from left margin.
1514 return make_int (decode_window (window)->hscroll);
1517 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1518 Return the horizontal scrolling amount of WINDOW's modeline.
1519 If the window has no modeline, return nil.
1523 struct window *w = decode_window (window);
1525 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
1529 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1530 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1531 If NCOL is negative, it will silently be forced to 0.
1532 If the window has no modeline, return nil. Otherwise, return the actual
1537 struct window *w = decode_window (window);
1539 if (WINDOW_HAS_MODELINE_P (w))
1544 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
1545 if (ncols != w->modeline_hscroll)
1547 MARK_MODELINE_CHANGED;
1548 w->modeline_hscroll = ncols;
1550 return make_int ((int) ncols);
1556 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1557 Set number of columns WINDOW is scrolled from left margin to NCOL.
1558 NCOL should be zero or positive.
1566 ncols = XINT (ncol);
1567 if (ncols < 0) ncols = 0;
1568 w = decode_window (window);
1569 if (w->hscroll != ncols)
1570 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1575 #if 0 /* bogus FSF crock */
1577 xxDEFUN ("window-redisplay-end-trigger",
1578 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1579 Return WINDOW's redisplay end trigger value.
1580 See `set-window-redisplay-end-trigger' for more information.
1584 return decode_window (window)->redisplay_end_trigger;
1587 xxDEFUN ("set-window-redisplay-end-trigger",
1588 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1589 Set WINDOW's redisplay end trigger value to VALUE.
1590 VALUE should be a buffer position (typically a marker) or nil.
1591 If it is a buffer position, then if redisplay in WINDOW reaches a position
1592 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1593 with two arguments: WINDOW, and the end trigger value.
1594 Afterwards the end-trigger value is reset to nil.
1598 return (decode_window (window)->redisplay_end_trigger = value);
1603 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1604 Return a list of the pixel edge coordinates of WINDOW.
1605 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1606 all relative to 0, 0 at the top left corner of WINDOW's frame.
1607 The frame toolbars, menubars and gutters are considered to be outside
1608 of this area, while the scrollbars are considered to be inside.
1612 struct window *w = decode_window (window);
1613 struct frame *f = XFRAME (w->frame);
1616 w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
1618 w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
1620 return list4 (make_int (left),
1622 make_int (left + w->pixel_width),
1623 make_int (top + w->pixel_height));
1626 DEFUN ("window-text-area-pixel-edges",
1627 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1628 Return a list of the pixel edge coordinates of the text area of WINDOW.
1629 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1630 all relative to 0, 0 at the top left corner of the total area allocated
1631 to the window, which includes the scrollbars.
1635 struct window *w = decode_window (window);
1637 int left = window_left_gutter_width (w, /* modeline = */ 0);
1638 int top = window_top_gutter_height (w);
1639 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1640 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1642 return list4 (make_int (left),
1648 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1649 Return current value of point in WINDOW.
1650 For a non-selected window, this is the value point would have
1651 if that window were selected.
1653 Note that, when WINDOW is the selected window and its buffer
1654 is also currently selected, the value returned is the same as (point).
1655 It would be more strictly correct to return the `top-level' value
1656 of point, outside of any save-excursion forms.
1657 But that value is hard to find.
1661 struct window *w = decode_window (window);
1663 /* The special check for current buffer is necessary for this
1664 function to work as defined when called within an excursion. */
1665 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1666 && current_buffer == XBUFFER (w->buffer))
1667 return Fpoint (Qnil);
1668 return Fmarker_position (w->pointm[CURRENT_DISP]);
1671 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1672 Return position at which display currently starts in WINDOW.
1673 This is updated by redisplay or by calling `set-window-start'.
1677 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1680 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1681 Return position at which display currently ends in WINDOW.
1682 This is updated by redisplay, when it runs to completion.
1683 Simply changing the buffer text or setting `window-start' does not
1684 update this value. WINDOW defaults to the selected window.
1686 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1687 to be the same value as this function would return at the end of the
1688 next full redisplay assuming nothing else changes in the meantime.
1689 This function is potentially much slower with this flag set.
1691 (window, guarantee))
1693 struct window *w = decode_window (window);
1695 if (NILP (guarantee))
1700 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1704 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1705 return make_int (end_of_last_line (w, startp));
1709 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1710 Return pixel height of visible part of last window line if it is clipped.
1711 If the last line is not clipped, return nil.
1715 struct window *w = decode_window (window);
1716 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1717 int num_lines = Dynarr_length (dla);
1718 struct display_line *dl;
1720 /* No lines - no clipped lines */
1721 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
1724 dl = Dynarr_atp (dla, num_lines - 1);
1728 return make_int (dl->ascent + dl->descent - dl->clip);
1731 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1732 Make point value in WINDOW be at position POS in WINDOW's buffer.
1736 struct window *w = decode_window (window);
1738 CHECK_INT_COERCE_MARKER (pos);
1739 if (w == XWINDOW (Fselected_window (Qnil)))
1740 Fgoto_char (pos, Qnil);
1742 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1748 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1749 Make display in WINDOW start at position POS in WINDOW's buffer.
1750 Optional third arg NOFORCE non-nil inhibits next redisplay
1751 from overriding motion of point in order to display at this exact start.
1753 (window, pos, noforce))
1755 struct window *w = decode_window (window);
1757 CHECK_INT_COERCE_MARKER (pos);
1758 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1759 /* this is not right, but much easier than doing what is right. */
1760 /* w->start_at_line_beg = 0; */
1761 /* WTF is the above supposed to mean? GE */
1762 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1763 marker_position (w->start[CURRENT_DISP]));
1766 w->redo_modeline = 1;
1767 SET_LAST_MODIFIED (w, 0);
1768 SET_LAST_FACECHANGE (w);
1770 MARK_WINDOWS_CHANGED (w);
1775 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1776 Return WINDOW's dedicated object, usually t or nil.
1777 See also `set-window-dedicated-p'.
1781 return decode_window (window)->dedicated;
1784 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1785 Control whether WINDOW is dedicated to the buffer it displays.
1786 If it is dedicated, Emacs will not automatically change
1787 which buffer appears in it.
1788 The second argument is the new value for the dedication flag;
1793 struct window *w = decode_window (window);
1795 w->dedicated = NILP (arg) ? Qnil : Qt;
1797 return w->dedicated;
1800 /* FSFmacs has window-display-table here. We have display table as a
1804 /* Record info on buffer window w is displaying
1805 when it is about to cease to display that buffer. */
1807 unshow_buffer (struct window *w)
1809 Lisp_Object buf = w->buffer;
1811 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1814 /* FSF disables this check, so I'll do it too. I hope it won't
1815 break things. --ben */
1817 if (w == XWINDOW (Fselected_window (Qnil))
1818 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1819 /* Do this except when the selected window's buffer
1820 is being removed from some other window. */
1822 /* last_window_start records the start position that this buffer
1823 had in the last window to be disconnected from it.
1824 Now that this statement is unconditional,
1825 it is possible for the buffer to be displayed in the
1826 selected window, while last_window_start reflects another
1827 window which was recently showing the same buffer.
1828 Some people might say that might be a good thing. Let's see. */
1829 XBUFFER (buf)->last_window_start =
1830 marker_position (w->start[CURRENT_DISP]);
1832 /* Point in the selected window's buffer
1833 is actually stored in that buffer, and the window's pointm isn't used.
1834 So don't clobber point in that buffer. */
1835 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1837 struct buffer *b= XBUFFER (buf);
1838 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1839 marker_position (w->pointm[CURRENT_DISP]),
1844 /* Put REPLACEMENT into the window structure in place of OLD. */
1846 replace_window (Lisp_Object old, Lisp_Object replacement)
1849 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1851 /* If OLD is its frame's root_window, then replacement is the new
1852 root_window for that frame. */
1854 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1855 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1857 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1858 WINDOW_TOP (p) = WINDOW_TOP (o);
1859 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1860 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1862 p->next = tem = o->next;
1864 XWINDOW (tem)->prev = replacement;
1866 p->prev = tem = o->prev;
1868 XWINDOW (tem)->next = replacement;
1870 p->parent = tem = o->parent;
1873 if (EQ (XWINDOW (tem)->vchild, old))
1874 XWINDOW (tem)->vchild = replacement;
1875 if (EQ (XWINDOW (tem)->hchild, old))
1876 XWINDOW (tem)->hchild = replacement;
1879 /* #### Here, if replacement is a vertical combination
1880 and so is its new parent, we should make replacement's
1881 children be children of that parent instead. */
1883 ERROR_CHECK_SUBWINDOW_CACHE (p);
1887 window_unmap_subwindows (struct window* w)
1889 assert (!NILP (w->subwindow_instance_cache));
1890 elisp_maphash (unmap_subwindow_instance_cache_mapper,
1891 w->subwindow_instance_cache, (void*)1);
1894 /* we're deleting W; set the structure of W to indicate this. */
1897 mark_window_as_deleted (struct window *w)
1899 /* The window instance cache is going away now, so need to get the
1900 cachels reset by redisplay. */
1901 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
1903 /* The cache is going away. If we leave unmapping to
1904 reset_subwindow_cachels then we get in a situation where the
1905 domain (the window) has been deleted but we still need access to
1906 its attributes in order to unmap windows properly. Since the
1907 subwindows are going to get GC'd anyway as a result of the domain
1908 going away, it is safer to just unmap them all while we know the
1909 domain is still valid. */
1910 ERROR_CHECK_SUBWINDOW_CACHE (w);
1911 window_unmap_subwindows (w);
1914 (while t (split-window) (delete-window))
1915 we end up with a tree of deleted windows which are all connected
1916 through the `next' slot. This might not seem so bad, as they're
1917 deleted, and will presumably be GCed - but if even *one* of those
1918 windows is still being pointed to, by the user, or by a window
1919 configuration, then *all* of those windows stick around.
1921 Since the window-configuration code doesn't need any of the
1922 pointers to other windows (they are all recreated from the
1923 window-config data), we set them all to nil so that we
1924 are able to collect more actual garbage. */
1930 w->subwindow_instance_cache = Qnil;
1934 /* Free the extra data structures attached to windows immediately so
1935 they don't sit around consuming excess space. They will be
1936 reinitialized by the window-configuration code as necessary. */
1937 finalize_window ((void *) w, 0);
1940 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1941 Remove WINDOW from the display. Default is selected window.
1942 If window is the only one on its frame, the frame is deleted as well.
1943 Normally, you cannot delete the last non-minibuffer-only frame (you must
1944 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1945 second argument FORCE is non-nil, you can delete the last frame. (This
1946 will automatically call `save-buffers-kill-emacs'.)
1950 /* This function can GC if this is the only window in the frame */
1958 /* Note: this function is called by other C code on non-leaf
1961 /* Do the equivalent of decode_window() but don't error out on
1962 deleted window; it's OK to delete an already-deleted window. */
1964 window = Fselected_window (Qnil);
1966 CHECK_WINDOW (window);
1968 w = XWINDOW (window);
1970 /* It's okay to delete an already-deleted window. */
1971 if (! WINDOW_LIVE_P (w))
1974 frame = WINDOW_FRAME (w);
1976 d = XDEVICE (FRAME_DEVICE (f));
1978 if (TOP_LEVEL_WINDOW_P (w))
1980 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1981 /* this frame isn't fully initialized yet; don't blow up. */
1984 if (MINI_WINDOW_P (XWINDOW (window)))
1985 error ("Attempt to delete the minibuffer window");
1987 /* It has been suggested that it's a good thing for C-x 0 to have this
1988 behavior, but not such a good idea for #'delete-window to have it.
1989 Maybe C-x 0 should be bound to something else, or maybe frame
1990 deletion should only happen when this is called interactively.
1992 delete_frame_internal (f, !NILP (force), 0, 0);
1996 /* At this point, we know the window has a parent. */
1998 par = XWINDOW (parent);
2000 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
2001 /* It's quite likely that deleting a window will result in
2002 subwindows needing to be deleted also (since they are cached
2003 per-window). So we mark them as changed, so that the cachels will
2004 get reset by redisplay and thus deleted subwindows can get
2006 MARK_FRAME_SUBWINDOWS_CHANGED (f);
2008 /* Are we trying to delete any frame's selected window?
2009 Note that we could be dealing with a non-leaf window
2010 where the selected window is one of our children.
2011 So, we check by scanning all the ancestors of the
2012 frame's selected window and comparing each one with
2015 Lisp_Object pwindow;
2017 pwindow = FRAME_SELECTED_WINDOW (f);
2019 while (!NILP (pwindow))
2021 if (EQ (window, pwindow))
2023 pwindow = XWINDOW (pwindow)->parent;
2026 if (EQ (window, pwindow))
2028 /* OK, we found it. */
2029 Lisp_Object alternative;
2030 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
2032 /* If we're about to delete the selected window on the
2033 selected frame, then we should use Fselect_window to select
2034 the new window. On the other hand, if we're about to
2035 delete the selected window on any other frame, we shouldn't do
2036 anything but set the frame's selected_window slot. */
2037 if (EQ (frame, Fselected_frame (Qnil)))
2038 Fselect_window (alternative, Qnil);
2040 set_frame_selected_window (f, alternative);
2044 /* w->buffer is nil in a non-leaf window; in this case,
2045 get rid of the markers we maintain that point into that buffer. */
2046 if (!NILP (w->buffer))
2049 unchain_marker (w->pointm[CURRENT_DISP]);
2050 unchain_marker (w->pointm[DESIRED_DISP]);
2051 unchain_marker (w->pointm[CMOTION_DISP]);
2052 unchain_marker (w->start[CURRENT_DISP]);
2053 unchain_marker (w->start[DESIRED_DISP]);
2054 unchain_marker (w->start[CMOTION_DISP]);
2055 unchain_marker (w->sb_point);
2056 /* This breaks set-window-configuration if windows in the saved
2057 configuration get deleted and multiple frames are in use. */
2058 /* w->buffer = Qnil; */
2061 /* close up the hole in the sibling list */
2062 if (!NILP (w->next))
2063 XWINDOW (w->next)->prev = w->prev;
2064 if (!NILP (w->prev))
2065 XWINDOW (w->prev)->next = w->next;
2066 if (EQ (window, par->hchild))
2067 par->hchild = w->next;
2068 if (EQ (window, par->vchild))
2069 par->vchild = w->next;
2071 /* Find one of our siblings to give our space to. */
2073 Lisp_Object sib = w->prev;
2076 /* If w gives its space to its next sibling, that sibling needs
2077 to have its top/left side pulled back to where w's is.
2078 set_window_{height,width} will re-position the sibling's
2081 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
2082 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
2085 /* Stretch that sibling. */
2086 if (!NILP (par->vchild))
2087 set_window_pixheight
2088 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
2089 if (!NILP (par->hchild))
2091 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
2094 /* If parent now has only one child,
2095 put the child into the parent's place. */
2097 Lisp_Object parchild = par->hchild;
2098 if (NILP (parchild))
2099 parchild = par->vchild;
2100 if (NILP (XWINDOW (parchild)->next))
2102 replace_window (parent, parchild);
2103 mark_window_as_deleted (XWINDOW (parent));
2107 /* Since we may be deleting combination windows, we must make sure that
2108 not only W but all its children have been marked as deleted. */
2109 if (!NILP (w->hchild))
2110 delete_all_subwindows (XWINDOW (w->hchild));
2111 else if (!NILP (w->vchild))
2112 delete_all_subwindows (XWINDOW (w->vchild));
2114 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and
2115 therefore redisplay, so it requires the mirror structure to be
2116 correct. We must dirty the mirror before it is called. */
2117 f->mirror_dirty = 1;
2119 mark_window_as_deleted (w);
2125 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2126 Return the next window after WINDOW in the canonical ordering of windows.
2127 If omitted, WINDOW defaults to the selected window.
2129 Optional second arg MINIBUF t means count the minibuffer window even
2130 if not active. MINIBUF nil or omitted means count the minibuffer iff
2131 it is active. MINIBUF neither t nor nil means not to count the
2132 minibuffer even if it is active.
2134 Several frames may share a single minibuffer; if the minibuffer
2135 counts, all windows on all frames that share that minibuffer count
2136 too. Therefore, `next-window' can be used to iterate through the
2137 set of windows even when the minibuffer is on another frame. If the
2138 minibuffer does not count, only windows from WINDOW's frame count.
2140 By default, only the windows in the selected frame are considered.
2141 The optional argument WHICH-FRAMES changes this behavior:
2142 WHICH-FRAMES = `visible' means search windows on all visible frames.
2143 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2144 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2145 WHICH-FRAMES = a frame means search only windows on that frame.
2146 Anything else means restrict to the selected frame.
2148 The optional fourth argument WHICH-DEVICES further clarifies on which
2149 devices to search for frames as specified by WHICH-FRAMES. This value
2150 is only meaningful if WHICH-FRAMES is non-nil.
2151 If nil or omitted, search all devices on the selected console.
2152 If a device, only search that device.
2153 If a console, search all devices on that console.
2154 If a device type, search all devices of that type.
2155 If `window-system', search all window-system devices.
2156 Any other non-nil value means search all devices.
2158 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2159 you can use `next-window' to iterate through the entire cycle of
2160 acceptable windows, eventually ending up back at the window you started with.
2161 `previous-window' traverses the same cycle, in the reverse order.
2163 (window, minibuf, which_frames, which_devices))
2166 Lisp_Object start_window;
2169 window = Fselected_window (Qnil);
2171 CHECK_LIVE_WINDOW (window);
2173 start_window = window;
2175 /* minibuf == nil may or may not include minibuffers.
2176 Decide if it does. */
2178 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2179 else if (! EQ (minibuf, Qt))
2181 /* Now `minibuf' is one of:
2182 t => count all minibuffer windows
2183 lambda => count none of them
2184 or a specific minibuffer window (the active one) to count. */
2186 /* which_frames == nil doesn't specify which frames to include. */
2187 if (NILP (which_frames))
2188 which_frames = (! EQ (minibuf, Qlambda)
2189 ? (FRAME_MINIBUF_WINDOW
2192 (XWINDOW (window)))))
2194 else if (EQ (which_frames, Qvisible))
2196 else if (ZEROP (which_frames))
2198 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2199 /* If which_frames is a frame and window arg isn't on that frame, just
2200 return the first window on the frame. */
2201 return frame_first_window (XFRAME (which_frames));
2202 else if (! EQ (which_frames, Qt))
2203 which_frames = Qnil;
2204 /* Now `which_frames' is one of:
2205 t => search all frames
2206 nil => search just the current frame
2207 visible => search just visible frames
2208 0 => search visible and iconified frames
2209 a window => search the frame that window belongs to. */
2211 /* Do this loop at least once, to get the next window, and perhaps
2212 again, if we hit the minibuffer and that is not acceptable. */
2215 /* Find a window that actually has a next one. This loop
2216 climbs up the tree. */
2217 while (tem = XWINDOW (window)->next, NILP (tem))
2218 if (tem = XWINDOW (window)->parent, !NILP (tem))
2220 else /* window must be minibuffer window now */
2222 /* We've reached the end of this frame.
2223 Which other frames are acceptable? */
2224 tem = WINDOW_FRAME (XWINDOW (window));
2226 if (! NILP (which_frames))
2228 Lisp_Object tem1 = tem;
2229 tem = next_frame (tem, which_frames, which_devices);
2231 /* In the case where the minibuffer is active,
2232 and we include its frame as well as the selected one,
2233 next_frame may get stuck in that frame.
2234 If that happens, go back to the selected frame
2235 so we can complete the cycle. */
2237 XSETFRAME (tem, selected_frame ());
2240 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2246 /* If we're in a combination window, find its first child and
2247 recurse on that. Otherwise, we've found the window we want. */
2250 if (!NILP (XWINDOW (window)->hchild))
2251 window = XWINDOW (window)->hchild;
2252 else if (!NILP (XWINDOW (window)->vchild))
2253 window = XWINDOW (window)->vchild;
2257 /* Which windows are acceptable?
2258 Exit the loop and accept this window if
2259 this isn't a minibuffer window,
2260 or we're accepting all minibuffer windows,
2261 or this is the active minibuffer and we are accepting that one, or
2262 we've come all the way around and we're back at the original window. */
2263 while (MINI_WINDOW_P (XWINDOW (window))
2264 && ! EQ (minibuf, Qt)
2265 && ! EQ (minibuf, window)
2266 && ! EQ (window, start_window));
2271 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2272 Return the window preceding WINDOW in the canonical ordering of windows.
2273 If omitted, WINDOW defaults to the selected window.
2275 Optional second arg MINIBUF t means count the minibuffer window even
2276 if not active. MINIBUF nil or omitted means count the minibuffer iff
2277 it is active. MINIBUF neither t nor nil means not to count the
2278 minibuffer even if it is active.
2280 Several frames may share a single minibuffer; if the minibuffer
2281 counts, all windows on all frames that share that minibuffer count
2282 too. Therefore, `previous-window' can be used to iterate through
2283 the set of windows even when the minibuffer is on another frame. If
2284 the minibuffer does not count, only windows from WINDOW's frame count.
2286 By default, only the windows in the selected frame are considered.
2287 The optional argument WHICH-FRAMES changes this behavior:
2288 WHICH-FRAMES = `visible' means search windows on all visible frames.
2289 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2290 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2291 WHICH-FRAMES = a frame means search only windows on that frame.
2292 Anything else means restrict to the selected frame.
2294 The optional fourth argument WHICH-DEVICES further clarifies on which
2295 devices to search for frames as specified by WHICH-FRAMES. This value
2296 is only meaningful if WHICH-FRAMES is non-nil.
2297 If nil or omitted, search all devices on the selected console.
2298 If a device, only search that device.
2299 If a console, search all devices on that console.
2300 If a device type, search all devices of that type.
2301 If `window-system', search all window-system devices.
2302 Any other non-nil value means search all devices.
2304 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2305 you can use `previous-window' to iterate through the entire cycle of
2306 acceptable windows, eventually ending up back at the window you started with.
2307 `next-window' traverses the same cycle, in the reverse order.
2309 (window, minibuf, which_frames, devices))
2312 Lisp_Object start_window;
2315 window = Fselected_window (Qnil);
2317 CHECK_LIVE_WINDOW (window);
2319 start_window = window;
2321 /* minibuf == nil may or may not include minibuffers.
2322 Decide if it does. */
2324 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2325 else if (! EQ (minibuf, Qt))
2327 /* Now `minibuf' is one of:
2328 t => count all minibuffer windows
2329 lambda => count none of them
2330 or a specific minibuffer window (the active one) to count. */
2332 /* which_frames == nil doesn't specify which frames to include.
2333 Decide which frames it includes. */
2334 if (NILP (which_frames))
2335 which_frames = (! EQ (minibuf, Qlambda)
2336 ? (FRAME_MINIBUF_WINDOW
2339 (XWINDOW (window)))))
2341 else if (EQ (which_frames, Qvisible))
2343 else if (ZEROP (which_frames))
2345 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2346 /* If which_frames is a frame and window arg isn't on that frame, just
2347 return the first window on the frame. */
2348 return frame_first_window (XFRAME (which_frames));
2349 else if (! EQ (which_frames, Qt))
2350 which_frames = Qnil;
2351 /* Now `which_frames' is one of:
2352 t => search all frames
2353 nil => search just the current frame
2354 visible => search just visible frames
2355 0 => search visible and iconified frames
2356 a window => search the frame that window belongs to. */
2358 /* Do this loop at least once, to get the next window, and perhaps
2359 again, if we hit the minibuffer and that is not acceptable. */
2362 /* Find a window that actually has a next one. This loop
2363 climbs up the tree. */
2364 while (tem = XWINDOW (window)->prev, NILP (tem))
2365 if (tem = XWINDOW (window)->parent, !NILP (tem))
2367 else /* window must be minibuffer window now */
2369 /* We have found the top window on the frame.
2370 Which frames are acceptable? */
2371 tem = WINDOW_FRAME (XWINDOW (window));
2373 if (! NILP (which_frames))
2374 /* It's actually important that we use previous_frame here,
2375 rather than next_frame. All the windows acceptable
2376 according to the given parameters should form a ring;
2377 Fnext_window and Fprevious_window should go back and
2378 forth around the ring. If we use next_frame here,
2379 then Fnext_window and Fprevious_window take different
2380 paths through the set of acceptable windows.
2381 window_loop assumes that these `ring' requirement are
2384 Lisp_Object tem1 = tem;
2385 tem = previous_frame (tem, which_frames, devices);
2386 /* In the case where the minibuffer is active,
2387 and we include its frame as well as the selected one,
2388 next_frame may get stuck in that frame.
2389 If that happens, go back to the selected frame
2390 so we can complete the cycle. */
2392 XSETFRAME (tem, selected_frame ());
2395 /* If this frame has a minibuffer, find that window first,
2396 because it is conceptually the last window in that frame. */
2397 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2398 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2400 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2407 /* If we're in a combination window, find its first child and
2408 recurse on that. Otherwise, we've found the window we want. */
2411 if (!NILP (XWINDOW (window)->hchild))
2412 window = XWINDOW (window)->hchild;
2413 else if (!NILP (XWINDOW (window)->vchild))
2414 window = XWINDOW (window)->vchild;
2416 while (tem = XWINDOW (window)->next, !NILP (tem))
2420 /* Which windows are acceptable?
2421 Exit the loop and accept this window if
2422 this isn't a minibuffer window,
2423 or we're accepting all minibuffer windows,
2424 or this is the active minibuffer and we are accepting that one, or
2425 we've come all the way around and we're back at the original window. */
2426 while (MINI_WINDOW_P (XWINDOW (window))
2427 && ! EQ (minibuf, Qt)
2428 && ! EQ (minibuf, window)
2429 && ! EQ (window, start_window));
2434 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2435 Return the next window which is vertically after WINDOW.
2440 struct window *w = decode_window (window);
2441 XSETWINDOW (window, w);
2443 if (MINI_WINDOW_P (XWINDOW (window)))
2446 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2448 if (EQ (window, root))
2451 if (!NILP (XWINDOW (window)->hchild))
2452 window = XWINDOW (window)->hchild;
2453 else if (!NILP (XWINDOW (window)->vchild))
2454 window = XWINDOW (window)->vchild;
2461 if (!NILP (XWINDOW (window)->parent) &&
2462 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2464 if (!NILP (XWINDOW (window)->next))
2465 return XWINDOW (window)->next;
2467 window = XWINDOW (window)->parent;
2470 window = XWINDOW (window)->parent;
2472 while (!EQ (window, root));
2475 if (!NILP (XWINDOW (window)->hchild))
2476 window = XWINDOW (window)->hchild;
2477 else if (!NILP (XWINDOW (window)->vchild))
2478 window = XWINDOW (window)->vchild;
2483 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2484 Select the COUNT'th different window on this frame.
2485 All windows on current frame are arranged in a cyclic order.
2486 This command selects the window COUNT steps away in that order.
2487 A negative COUNT moves in the opposite order.
2489 By default, only the windows in the selected frame are considered.
2490 The optional argument WHICH-FRAMES changes this behavior:
2491 WHICH-FRAMES = `visible' means search windows on all visible frames.
2492 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2493 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2494 WHICH-FRAMES = a frame means search only windows on that frame.
2495 Anything else means restrict to the selected frame.
2497 The optional argument WHICH-DEVICES further clarifies on which devices
2498 to search for frames as specified by WHICH-FRAMES. This value is only
2499 meaningful if WHICH-FRAMES is non-nil.
2500 If nil or omitted, search all devices on the selected console.
2501 If a device, only search that device.
2502 If a console, search all devices on that console.
2503 If a device type, search all devices of that type.
2504 If `window-system', search all window-system devices.
2505 Any other non-nil value means search all devices.
2507 (count, which_frames, which_devices))
2513 w = Fselected_window (Qnil);
2518 w = Fnext_window (w, Qnil, which_frames, which_devices);
2523 w = Fprevious_window (w, Qnil, which_frames, which_devices);
2526 Fselect_window (w, Qnil);
2531 /* Look at all windows, performing an operation specified by TYPE
2534 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2535 frame. If FRAMES is a frame, just look at windows on that frame.
2536 If MINI is non-zero, perform the operation on minibuffer windows too.
2542 GET_BUFFER_WINDOW, /* Arg is buffer */
2543 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2544 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2545 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2546 UNDEDICATE_BUFFER, /* Arg is buffer */
2548 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2549 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2553 window_loop (enum window_loop type,
2556 Lisp_Object which_frames,
2558 Lisp_Object which_devices)
2560 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2562 Lisp_Object best_window = Qnil;
2563 Lisp_Object next_window;
2564 Lisp_Object last_window;
2565 struct frame *frame;
2566 Lisp_Object frame_arg = Qt;
2567 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2568 /* #### I think the change of "precomputing" last_window and next_window
2569 * #### catch the lossage this is meant(?) to punt on...
2572 Lisp_Object devcons, concons;
2574 /* If we're only looping through windows on a particular frame,
2575 FRAME points to that frame. If we're looping through windows
2576 on all frames, FRAME is 0. */
2577 if (FRAMEP (which_frames))
2578 frame = XFRAME (which_frames);
2579 else if (NILP (which_frames))
2580 frame = selected_frame ();
2584 /* FRAME_ARG is Qlambda to stick to one frame,
2585 Qvisible to consider all visible frames,
2588 frame_arg = Qlambda;
2589 else if (ZEROP (which_frames))
2590 frame_arg = which_frames;
2591 else if (EQ (which_frames, Qvisible))
2592 frame_arg = which_frames;
2594 DEVICE_LOOP_NO_BREAK (devcons, concons)
2596 Lisp_Object device = XCAR (devcons);
2597 Lisp_Object the_frame;
2600 XSETFRAME (the_frame, frame);
2602 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2604 if (NILP (the_frame))
2607 if (!device_matches_device_spec (device,
2608 NILP (which_devices) ?
2609 FRAME_CONSOLE (XFRAME (the_frame)) :
2613 /* Pick a window to start with. */
2617 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2619 /* Figure out the last window we're going to mess with. Since
2620 Fnext_window, given the same options, is guaranteed to go in a
2621 ring, we can just use Fprevious_window to find the last one.
2623 We can't just wait until we hit the first window again,
2624 because it might be deleted. */
2626 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, device);
2631 struct window *p = XWINDOW (w);
2633 /* Pick the next window now, since some operations will delete
2634 the current window. */
2635 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
2637 /* #### Still needed ?? */
2638 /* Given the outstanding quality of the rest of this code,
2639 I feel no shame about putting this piece of shit in. */
2640 if (++lose_lose >= 500)
2642 /* Call to ABORT() added by Darryl Okahata (16 Nov. 2001),
2643 at Ben's request, to catch any remaining bugs.
2645 If you find that XEmacs is ABORTing here, and you
2646 need to be up and running ASAP, it should be safe to
2647 comment out the following ABORT(), as long as you
2648 leave the "break;" alone. */
2650 break; /* <--- KEEP THIS HERE! Do not delete! */
2653 /* Note that we do not pay attention here to whether
2654 the frame is visible, since Fnext_window skips non-visible frames
2655 if that is desired, under the control of frame_arg. */
2656 if (! MINI_WINDOW_P (p)
2657 || (mini && minibuf_level > 0))
2660 case GET_BUFFER_WINDOW:
2662 if (XBUFFER (p->buffer) == XBUFFER (obj))
2667 case GET_BUFFER_WINDOW_COUNT:
2669 if (XBUFFER (p->buffer) == XBUFFER (obj))
2674 case GET_LRU_WINDOW:
2676 /* t as arg means consider only full-width windows */
2678 && !window_full_width_p (p))
2680 /* Ignore dedicated windows and minibuffers. */
2681 if (MINI_WINDOW_P (p)
2682 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2684 if (NILP (best_window)
2685 || (XINT (XWINDOW (best_window)->use_time)
2686 > XINT (p->use_time)))
2691 case GET_BUFFER_MRU_WINDOW:
2693 /* #### what about the first check in GET_LRU_WINDOW? */
2694 /* Ignore dedicated windows and minibuffers. */
2695 if (MINI_WINDOW_P (p)
2696 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2699 if (XBUFFER (p->buffer) == XBUFFER (obj))
2701 if (NILP (best_window)
2702 || (XINT (XWINDOW (best_window)->use_time)
2703 < XINT (p->use_time)))
2709 case UNDEDICATE_BUFFER:
2711 if ((XBUFFER (p->buffer) == XBUFFER (obj)))
2712 p->dedicated = Qnil;
2716 case DELETE_OTHER_WINDOWS:
2718 /* Don't delete the last window on a frame; this can
2719 happen when the minibuffer is selected, and would
2720 cause the frame to be deleted. */
2721 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2722 Fdelete_window (w, Qnil);
2726 case DELETE_BUFFER_WINDOWS:
2728 if (EQ (p->buffer, obj))
2730 struct frame *f = XFRAME (WINDOW_FRAME (p));
2732 /* If this window is dedicated, and in a frame
2733 of its own, kill the frame. */
2734 if (EQ (w, FRAME_ROOT_WINDOW (f))
2735 && !NILP (p->dedicated)
2736 && (allow_deletion_of_last_visible_frame
2737 || other_visible_frames (f)))
2739 /* Skip the other windows on this frame.
2740 There might be one, the minibuffer! */
2741 if (! EQ (w, last_window))
2742 while (f == XFRAME (WINDOW_FRAME
2743 (XWINDOW (next_window))))
2745 /* As we go, check for the end of the
2746 loop. We mustn't start going
2747 around a second time. */
2748 if (EQ (next_window, last_window))
2753 next_window = Fnext_window (next_window,
2757 /* Now we can safely delete the frame. */
2758 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2761 /* If we're deleting the buffer displayed in
2762 the only window on the frame, find a new
2763 buffer to display there. */
2764 if (NILP (p->parent))
2766 Lisp_Object new_buffer;
2767 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2768 if (NILP (new_buffer))
2769 new_buffer = Fget_buffer_create (QSscratch);
2770 Fset_window_buffer (w, new_buffer, Qnil);
2771 if (EQ (w, Fselected_window (Qnil)))
2772 Fset_buffer (p->buffer);
2775 Fdelete_window (w, Qnil);
2780 case GET_LARGEST_WINDOW:
2782 /* Ignore dedicated windows and minibuffers. */
2783 if (MINI_WINDOW_P (p)
2784 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2787 /* write the check as follows to avoid tripping
2788 error_check_window() --ben */
2789 struct window *b = NILP (best_window) ? 0 :
2790 XWINDOW (best_window);
2791 if (NILP (best_window)
2792 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2793 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2803 if (EQ (w, last_window))
2810 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2813 #if 0 /* not currently used */
2816 buffer_window_count (struct buffer *b, struct frame *f)
2818 Lisp_Object buffer, frame;
2820 XSETFRAME (frame, f);
2821 XSETBUFFER (buffer, b);
2823 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2828 buffer_window_mru (struct window *w)
2830 Lisp_Object window =
2831 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2835 else if (XWINDOW (window) == w)
2844 undedicate_windows (Lisp_Object buffer, Lisp_Object frame)
2846 window_loop (UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2850 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2851 Return the window least recently selected or used for display.
2853 By default, only the windows in the selected frame are considered.
2854 The optional argument WHICH-FRAMES changes this behavior:
2855 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2856 If WHICH-FRAMES is 0, search all visible and iconified frames.
2857 If WHICH-FRAMES is t, search all frames.
2858 If WHICH-FRAMES is nil, search only the selected frame.
2859 If WHICH-FRAMES is a frame, search only that frame.
2861 The optional argument WHICH-DEVICES further clarifies on which devices
2862 to search for frames as specified by WHICH-FRAMES. This value is only
2863 meaningful if WHICH-FRAMES is non-nil.
2864 If nil or omitted, search all devices on the selected console.
2865 If a device, only search that device.
2866 If a console, search all devices on that console.
2867 If a device type, search all devices of that type.
2868 If `window-system', search all devices on window-system consoles.
2869 Any other non-nil value means search all devices.
2871 (which_frames, which_devices))
2874 /* First try for a non-dedicated window that is full-width */
2875 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2876 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2879 /* Then try for any non-dedicated window */
2880 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices);
2881 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2885 /* FSFmacs never returns a dedicated window here. If we do,
2886 it makes `display-buffer' not work right. #### All of this
2887 shit is so disgusting and awful that it needs to be rethought
2889 /* then try for a dedicated window that is full-width */
2890 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2891 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2894 /* If none of them, then all windows, dedicated or not. */
2895 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
2897 /* At this point we damn well better have found something. */
2898 if (NILP (w)) ABORT ();
2904 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2905 Return the window largest in area.
2907 By default, only the windows in the selected frame are considered.
2908 The optional argument WHICH-FRAMES changes this behavior:
2909 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2910 If WHICH-FRAMES is 0, search all visible and iconified frames.
2911 If WHICH-FRAMES is t, search all frames.
2912 If WHICH-FRAMES is nil, search only the selected frame.
2913 If WHICH-FRAMES is a frame, search only that frame.
2915 The optional argument WHICH-DEVICES further clarifies on which devices
2916 to search for frames as specified by WHICH-FRAMES. This value is only
2917 meaningful if WHICH-FRAMES is non-nil.
2918 If nil or omitted, search all devices on the selected console.
2919 If a device, only search that device.
2920 If a console, search all devices on that console.
2921 If a device type, search all devices of that type.
2922 If `window-system', search all devices on window-system consoles.
2923 Any other non-nil value means search all devices.
2925 (which_frames, which_devices))
2927 /* Don't search dedicated windows because FSFmacs doesn't.
2928 This stuff is all black magic so don't try to apply common
2930 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2931 which_frames, 0, which_devices);
2934 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2935 Return a window currently displaying BUFFER, or nil if none.
2937 By default, only the windows in the selected frame are considered.
2938 The optional argument WHICH-FRAMES changes this behavior:
2939 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2940 If WHICH-FRAMES is 0, search all visible and iconified frames.
2941 If WHICH-FRAMES is t, search all frames.
2942 If WHICH-FRAMES is nil, search only the selected frame.
2943 If WHICH-FRAMES is a frame, search only that frame.
2945 The optional argument WHICH-DEVICES further clarifies on which devices
2946 to search for frames as specified by WHICH-FRAMES. This value is only
2947 meaningful if WHICH-FRAMES is non-nil.
2948 If nil or omitted, search all devices on the selected console.
2949 If a device, only search that device.
2950 If a console, search all devices on that console.
2951 If a device type, search all devices of that type.
2952 If `window-system', search all devices on window-system consoles.
2953 Any other non-nil value means search all devices.
2955 (buffer, which_frames, which_devices))
2957 buffer = Fget_buffer (buffer);
2958 if (BUFFERP (buffer))
2959 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2960 return window_loop (GET_BUFFER_WINDOW, buffer, 1,
2961 which_frames, 1, which_devices);
2966 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2967 but there is no sensible way to implement those functions, since
2968 you can't in general derive a window from a buffer. */
2970 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2972 Return the width in pixels of the left outside margin of window WINDOW.
2973 If WINDOW is nil, the selected window is assumed.
2977 return make_int (window_left_margin_width (decode_window (window)));
2980 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2982 Return the width in pixels of the right outside margin of window WINDOW.
2983 If WINDOW is nil, the selected window is assumed.
2987 return make_int (window_right_margin_width (decode_window (window)));
2990 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2991 Make WINDOW (or the selected window) fill its frame.
2992 Only the frame WINDOW is on is affected.
2993 This function tries to reduce display jumps
2994 by keeping the text previously visible in WINDOW
2995 in the same place on the frame. Doing this depends on
2996 the value of (window-start WINDOW), so if calling this function
2997 in a program gives strange scrolling, make sure the window-start
2998 value is reasonable when this function is called.
3002 struct window *w = decode_window (window);
3003 struct buffer *b = XBUFFER (w->buffer);
3005 int old_top = WINDOW_TOP (w);
3007 XSETWINDOW (window, w);
3009 if (MINI_WINDOW_P (w) && old_top > 0)
3010 error ("Can't expand minibuffer to full frame");
3012 /* Ignore dedicated windows. */
3013 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3015 start_pos = marker_position (w->start[CURRENT_DISP]);
3017 /* Try to minimize scrolling, by setting the window start to the
3018 point which will cause the text at the old window start to be at
3019 the same place on the frame. But don't try to do this if the
3020 window start is outside the visible portion (as might happen when
3021 the display is not current, due to typeahead). */
3022 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
3023 && !MINI_WINDOW_P (w))
3025 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
3027 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
3029 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
3031 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3033 /* We need to do this, so that the window-scroll-functions
3041 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3042 "bDelete windows on (buffer): ", /*
3043 Delete all windows showing BUFFER.
3045 Optional second argument WHICH-FRAMES controls which frames are affected.
3046 If nil or omitted, delete all windows showing BUFFER in any frame.
3047 If t, delete only windows showing BUFFER in the selected frame.
3048 If `visible', delete all windows showing BUFFER in any visible frame.
3049 If a frame, delete only windows showing BUFFER in that frame.
3050 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3051 except that the meanings of nil and t are reversed.
3053 The optional third argument WHICH-DEVICES further clarifies on which
3054 devices to search for frames as specified by WHICH-FRAMES. This value
3055 is only meaningful if WHICH-FRAMES is not t.
3056 If nil or omitted, search only the selected console.
3057 If a device, only search that device.
3058 If a console, search all devices on that console.
3059 If a device type, search all devices of that type.
3060 If `window-system', search all devices on a window system.
3061 Any other non-nil value means search all devices.
3063 (buffer, which_frames, which_devices))
3065 /* This function can GC */
3066 buffer = Fget_buffer (buffer);
3067 CHECK_BUFFER (buffer);
3069 /* WHICH-FRAMES values t and nil mean the opposite of what
3070 window_loop expects. */
3071 if (EQ (which_frames, Qnil))
3073 else if (EQ (which_frames, Qt))
3074 which_frames = Qnil;
3076 /* Ignore dedicated windows. */
3077 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0,
3078 which_frames, 0, which_devices);
3083 list_windows (struct window *w, Lisp_Object value)
3087 if (!NILP (w->hchild))
3088 value = list_windows (XWINDOW (w->hchild), value);
3089 else if (!NILP (w->vchild))
3090 value = list_windows (XWINDOW (w->vchild), value);
3094 XSETWINDOW (window, w);
3095 value = Fcons (window, value);
3099 w = XWINDOW (w->next);
3105 list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec)
3107 Lisp_Object devcons, concons;
3108 Lisp_Object retval = Qnil;
3110 DEVICE_LOOP_NO_BREAK (devcons, concons)
3112 Lisp_Object frame_list, the_window;
3113 Lisp_Object device, tail;
3115 device = XCAR (devcons);
3116 frame_list = DEVICE_FRAME_LIST (XDEVICE (device));
3118 LIST_LOOP (tail, frame_list)
3120 if ((NILP (frame_spec)
3121 && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device))))
3122 || (EQ (frame_spec, Qvisible)
3123 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail))))
3124 || (FRAMEP (frame_spec)
3125 && !EQ (frame_spec, XCAR (tail)))
3126 || (!NILP (frame_spec)
3127 && !device_matches_device_spec (device,
3128 NILP (device_spec) ?
3132 the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail)));
3133 retval = list_windows (XWINDOW (the_window), retval);
3136 return Fnreverse (retval);
3139 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3,
3140 "bReplace buffer in windows: ", /*
3141 Replace BUFFER with some other buffer in all windows showing it.
3143 Optional second argument WHICH-FRAMES controls which frames are affected.
3144 If nil or omitted, all frames are affected.
3145 If t, only the selected frame is affected.
3146 If `visible', all visible frames are affected.
3147 If a frame, only that frame is affected.
3148 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3149 except that the meanings of nil and t are reversed.
3151 The optional third argument WHICH-DEVICES further clarifies on which
3152 devices to search for frames as specified by WHICH-FRAMES. This value
3153 is only meaningful if WHICH-FRAMES is not t.
3154 If nil or omitted, search only the selected console.
3155 If a device, only search that device.
3156 If a console, search all devices on that console.
3157 If a device type, search all devices of that type.
3158 If `window-system', search all devices on a window system.
3159 Any other non-nil value means search all devices.
3161 (buffer, which_frames, which_devices))
3163 /* This function can GC */
3164 Lisp_Object window_list;
3166 struct gcpro gcpro1, gcpro2;
3168 if (EQ (which_frames, Qnil))
3170 else if (EQ (which_frames, Qt))
3171 which_frames = Qnil;
3172 window_list = list_all_windows (which_frames, which_devices);
3174 buffer = Fget_buffer (buffer);
3175 CHECK_BUFFER (buffer);
3177 GCPRO2 (window_list, buffer);
3178 LIST_LOOP (tail, window_list)
3180 Lisp_Object window = XCAR (tail);
3181 if (!MINI_WINDOW_P (XWINDOW (window))
3182 && EQ (XWINDOW (window)->buffer, buffer))
3184 Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil);
3185 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
3186 if (NILP (another_buffer))
3187 another_buffer = Fget_buffer_create (QSscratch);
3188 if (!NILP (XWINDOW (window)->dedicated)
3190 FRAME_ROOT_WINDOW (XFRAME (frame)))
3191 && (allow_deletion_of_last_visible_frame
3192 || other_visible_frames (XFRAME (frame))))
3194 delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */
3198 Fset_window_buffer (window, another_buffer, Qnil);
3199 if (EQ (window, Fselected_window (Qnil)))
3200 Fset_buffer (XWINDOW (window)->buffer);
3208 /* The smallest acceptable dimensions for a window. Anything smaller
3209 might crash Emacs. */
3210 #define MIN_SAFE_WINDOW_WIDTH (2)
3211 #define MIN_SAFE_WINDOW_HEIGHT (2)
3213 /* Make sure that window_min_height and window_min_width are
3214 not too small; if they are, set them to safe minima. */
3217 check_min_window_sizes (void)
3219 /* Smaller values might permit a crash. */
3220 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3221 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3222 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3223 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3227 frame_min_height (struct frame *frame)
3229 /* For height, we have to see whether the frame has a minibuffer, and
3230 whether it wants a modeline. */
3231 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3232 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3233 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3236 /* Return non-zero if both frame sizes are less than or equal to
3237 minimal allowed values. ROWS and COLS are in characters */
3239 frame_size_valid_p (struct frame *frame, int rows, int cols)
3241 return (rows >= frame_min_height (frame)
3242 && cols >= MIN_SAFE_WINDOW_WIDTH);
3245 /* Return non-zero if both frame sizes are less than or equal to
3246 minimal allowed values. WIDTH and HEIGHT are in pixels */
3248 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3251 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3252 return frame_size_valid_p (frame, rows, cols);
3255 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3256 minimum allowable size. */
3258 check_frame_size (struct frame *frame, int *rows, int *cols)
3260 int min_height = frame_min_height (frame);
3262 if (*rows < min_height)
3264 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3265 *cols = MIN_SAFE_WINDOW_WIDTH;
3268 /* Normally the window is deleted if it gets too small.
3269 nodelete nonzero means do not do this.
3270 (The caller should check later and do so if appropriate) */
3272 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3275 struct window *w = XWINDOW (window);
3276 struct frame *f = XFRAME (w->frame);
3278 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3279 Lisp_Object child, minor_kid, major_kid;
3282 int defheight, defwidth;
3284 /* #### This is very likely incorrect and instead the char_to_pixel_
3285 functions should be called. */
3286 default_face_height_and_width (window, &defheight, &defwidth);
3287 line_size = (set_height ? defheight : defwidth);
3289 check_min_window_sizes ();
3291 minsize = (set_height ? window_min_height : window_min_width);
3292 minsize *= line_size;
3295 && !TOP_LEVEL_WINDOW_P (w)
3296 && new_pixsize < minsize)
3298 Fdelete_window (window, Qnil);
3302 SET_LAST_MODIFIED (w, 0);
3303 SET_LAST_FACECHANGE (w);
3304 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3307 WINDOW_HEIGHT (w) = new_pixsize;
3308 major_kid = w->vchild;
3309 minor_kid = w->hchild;
3313 WINDOW_WIDTH (w) = new_pixsize;
3314 major_kid = w->hchild;
3315 minor_kid = w->vchild;
3318 if (!NILP (minor_kid))
3320 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3323 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3325 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3327 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3330 else if (!NILP (major_kid))
3332 int last_pos, last_old_pos, pos, old_pos, first;
3333 int pixel_adj_left = new_pixsize - old_pixsize;
3334 int div_val = old_pixsize << 1;
3337 * Previously we bailed out here if there was no size change.
3338 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3339 * toolbar appears or disappears, windows may not change size,
3340 * but their top and left coordinates need to be updated.
3342 * So we don't bail until after the loop below.
3345 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3348 for (child = major_kid; !NILP (child); child = c->next)
3350 c = XWINDOW (child);
3354 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3355 WINDOW_TOP (c) = last_pos;
3359 old_pos = last_old_pos + WINDOW_WIDTH (c);
3360 WINDOW_LEFT (c) = last_pos;
3363 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3364 /* All but the last window should have a height which is
3365 a multiple of the default line height. */
3366 if (!NILP (c->next))
3367 pos = (pos / line_size) * line_size;
3369 /* Avoid confusion: don't delete child if it becomes too small */
3370 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3372 last_pos = pos + first;
3373 last_old_pos = old_pos;
3376 /* Sometimes we may get called with our old size. In that case
3377 we don't need to do anything else. */
3378 if (!pixel_adj_left)
3381 /* Now delete any children that became too small. */
3383 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3386 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3388 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3393 /* Set the height of WINDOW and all its inferiors. */
3395 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3397 set_window_pixsize (window, new_pixheight, nodelete, 1);
3400 /* Recursively set width of WINDOW and its inferiors. */
3402 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3404 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3408 static int window_select_count;
3410 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3411 Make WINDOW display BUFFER as its contents.
3412 BUFFER can be a buffer or buffer name.
3414 With non-nil optional argument NORECORD, do not modify the
3415 global or per-frame buffer ordering.
3417 (window, buffer, norecord))
3420 struct window *w = decode_window (window);
3421 int old_buffer_local_face_property = 0;
3423 buffer = Fget_buffer (buffer);
3424 CHECK_BUFFER (buffer);
3426 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3427 error ("Attempt to display deleted buffer");
3431 error ("Window is deleted");
3433 /* While this seems like a logical thing to do, it causes problems
3434 because of saved window configurations. It is possible for a
3435 buffer to get restored into a window in which it is already being
3436 displayed, but start and point are actually at completely
3437 different locations. So we let this function complete fully and
3438 it will then make sure redisplay correctly updates things.
3440 #### This is a kludge. The correct approach is not to do this
3441 but to fix set-window-configuration. */
3443 else if (EQ (tem, buffer))
3446 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3447 is first being set up. */
3449 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3450 error ("Window is dedicated to buffer %s",
3451 XSTRING_DATA (XBUFFER (tem)->name));
3453 old_buffer_local_face_property =
3454 XBUFFER (w->buffer)->buffer_local_face_property;
3459 w->window_end_pos[CURRENT_DISP] = 0;
3461 w->modeline_hscroll = 0;
3462 Fset_marker (w->pointm[CURRENT_DISP],
3463 make_int (BUF_PT (XBUFFER (buffer))),
3465 set_marker_restricted (w->start[CURRENT_DISP],
3466 make_int (XBUFFER (buffer)->last_window_start),
3468 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3469 /* set start_at_line_beg correctly. GE */
3470 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3471 marker_position (w->start[CURRENT_DISP]));
3472 w->force_start = 0; /* Lucid fix */
3473 SET_LAST_MODIFIED (w, 1);
3474 SET_LAST_FACECHANGE (w);
3475 MARK_WINDOWS_CHANGED (w);
3477 int new_buffer_local_face_property =
3478 XBUFFER (w->buffer)->buffer_local_face_property;
3480 if (new_buffer_local_face_property
3481 || new_buffer_local_face_property != old_buffer_local_face_property)
3482 MARK_WINDOW_FACES_CHANGED (w);
3484 recompute_all_cached_specifiers_in_window (w);
3485 if (EQ (window, Fselected_window (Qnil)))
3487 if (NILP (norecord))
3488 Frecord_buffer (buffer);
3490 Fset_buffer (buffer);
3495 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3496 Select WINDOW. Most editing will apply to WINDOW's buffer.
3497 The main editor command loop selects the buffer of the selected window
3498 before each command.
3500 With non-nil optional argument NORECORD, do not modify the
3501 global or per-frame buffer ordering.
3506 Lisp_Object old_selected_window = Fselected_window (Qnil);
3508 CHECK_LIVE_WINDOW (window);
3509 w = XWINDOW (window);
3511 /* we have already caught dead-window errors */
3512 if (!NILP (w->hchild) || !NILP (w->vchild))
3513 error ("Trying to select non-leaf window");
3515 w->use_time = make_int (++window_select_count);
3517 if (EQ (window, old_selected_window))
3520 /* deselect the old window, if it exists (it might not exist if
3521 the selected device has no frames, which occurs at startup) */
3522 if (!NILP (old_selected_window))
3524 struct window *ow = XWINDOW (old_selected_window);
3526 Fset_marker (ow->pointm[CURRENT_DISP],
3527 make_int (BUF_PT (XBUFFER (ow->buffer))),
3530 MARK_WINDOWS_CHANGED (ow);
3533 /* now select the window's frame */
3534 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3536 select_frame_1 (WINDOW_FRAME (w));
3538 /* also select the window's buffer */
3539 if (NILP (norecord))
3540 Frecord_buffer (w->buffer);
3541 Fset_buffer (w->buffer);
3543 /* Go to the point recorded in the window.
3544 This is important when the buffer is in more
3545 than one window. It also matters when
3546 redisplay_window has altered point after scrolling,
3547 because it makes the change only in the window. */
3549 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3550 if (new_point < BUF_BEGV (current_buffer))
3551 new_point = BUF_BEGV (current_buffer);
3552 else if (new_point > BUF_ZV (current_buffer))
3553 new_point = BUF_ZV (current_buffer);
3555 BUF_SET_PT (current_buffer, new_point);
3558 MARK_WINDOWS_CHANGED (w);
3564 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3565 Lisp_Object override_frame)
3567 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3571 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3573 /* This function can GC */
3576 struct buffer *b = XBUFFER (buf);
3578 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3579 widen_buffer (b, 0);
3580 BUF_SET_PT (b, BUF_BEG (b));
3582 if (!NILP (Vtemp_buffer_show_function))
3583 call1 (Vtemp_buffer_show_function, buf);
3586 window = display_buffer (buf, Qnil, same_frame);
3588 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3589 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3591 Vminibuffer_scroll_window = window;
3592 w = XWINDOW (window);
3594 w->modeline_hscroll = 0;
3595 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3596 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3597 set_marker_restricted (w->sb_point, make_int (1), buf);
3599 /* Run temp-buffer-show-hook, with the chosen window selected. */
3600 if (!preparing_for_armageddon)
3603 tem = Fboundp (Qtemp_buffer_show_hook);
3606 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3609 int count = specpdl_depth ();
3611 /* Select the window that was chosen, for running
3613 record_unwind_protect (save_window_excursion_unwind,
3614 Fcurrent_window_configuration (Qnil));
3616 Fselect_window (window, Qnil);
3617 run_hook (Qtemp_buffer_show_hook);
3618 unbind_to (count, Qnil);
3626 make_dummy_parent (Lisp_Object window)
3629 struct window *o = XWINDOW (window);
3630 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3632 XSETWINDOW (new, p);
3633 copy_lcrecord (p, o);
3635 /* Don't copy the pointers to the line start cache or the face
3637 p->line_start_cache = Dynarr_new (line_start_cache);
3638 p->face_cachels = Dynarr_new (face_cachel);
3639 p->glyph_cachels = Dynarr_new (glyph_cachel);
3640 p->subwindow_instance_cache =
3641 make_image_instance_cache_hash_table ();
3643 /* Put new into window structure in place of window */
3644 replace_window (window, new);
3652 p->start[CURRENT_DISP] = Qnil;
3653 p->start[DESIRED_DISP] = Qnil;
3654 p->start[CMOTION_DISP] = Qnil;
3655 p->pointm[CURRENT_DISP] = Qnil;
3656 p->pointm[DESIRED_DISP] = Qnil;
3657 p->pointm[CMOTION_DISP] = Qnil;
3662 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3663 Split WINDOW, putting SIZE lines in the first of the pair.
3664 WINDOW defaults to the selected one and SIZE to half its size.
3665 If optional third arg HORFLAG is non-nil, split side by side and put
3666 SIZE columns in the first of the pair. The newly created window is
3669 (window, size, horflag))
3672 struct window *o, *p;
3678 window = Fselected_window (Qnil);
3680 CHECK_LIVE_WINDOW (window);
3682 o = XWINDOW (window);
3683 f = XFRAME (WINDOW_FRAME (o));
3687 if (!NILP (horflag))
3688 /* In the new scheme, we are symmetric with respect to separators
3689 so there is no need to do weird things here. */
3691 psize = (WINDOW_WIDTH (o) + window_divider_width (o)) >> 1;
3692 csize = window_pixel_width_to_char_width (o, psize, 0);
3696 psize = WINDOW_HEIGHT (o) >> 1;
3697 csize = window_pixel_height_to_char_height (o, psize, 1);
3703 csize = XINT (size);
3704 if (!NILP (horflag))
3705 psize = window_char_width_to_pixel_width (o, csize, 0);
3707 psize = window_char_height_to_pixel_height (o, csize, 1);
3710 if (MINI_WINDOW_P (o))
3711 error ("Attempt to split minibuffer window");
3712 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3713 error ("Attempt to split unsplittable frame");
3715 check_min_window_sizes ();
3719 if (csize < window_min_height)
3720 error ("Window height %d too small (after splitting)", csize);
3721 if (csize + window_min_height > window_char_height (o, 1))
3722 error ("Window height %d too small (after splitting)",
3723 window_char_height (o, 1) - csize);
3724 if (NILP (o->parent)
3725 || NILP (XWINDOW (o->parent)->vchild))
3727 make_dummy_parent (window);
3729 /* #### I can't understand why you have to reset face
3730 cachels here. This can cause crash so let's disable it
3731 and see the difference. See redisplay-tests.el --yh */
3732 reset_face_cachels (XWINDOW (window));
3735 XWINDOW (new)->vchild = window;
3736 XFRAME (o->frame)->mirror_dirty = 1;
3741 if (csize < window_min_width)
3742 error ("Window width %d too small (after splitting)", csize);
3743 if (csize + window_min_width > window_char_width (o, 0))
3744 error ("Window width %d too small (after splitting)",
3745 window_char_width (o, 0) - csize);
3746 if (NILP (o->parent)
3747 || NILP (XWINDOW (o->parent)->hchild))
3749 make_dummy_parent (window);
3751 /* #### See above. */
3752 reset_face_cachels (XWINDOW (window));
3755 XWINDOW (new)->hchild = window;
3756 XFRAME (o->frame)->mirror_dirty = 1;
3760 /* Now we know that window's parent is a vertical combination
3761 if we are dividing vertically, or a horizontal combination
3762 if we are making side-by-side windows */
3764 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3765 new = allocate_window ();
3768 p->frame = o->frame;
3770 if (!NILP (p->next))
3771 XWINDOW (p->next)->prev = new;
3774 p->parent = o->parent;
3777 reset_face_cachels (p);
3778 reset_glyph_cachels (p);
3781 /* Apportion the available frame space among the two new windows */
3783 if (!NILP (horflag))
3785 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3786 WINDOW_TOP (p) = WINDOW_TOP (o);
3787 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3788 WINDOW_WIDTH (o) = psize;
3789 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3793 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3794 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3795 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3796 WINDOW_HEIGHT (o) = psize;
3797 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3800 XFRAME (p->frame)->mirror_dirty = 1;
3801 /* do this last (after the window is completely initialized and
3802 the mirror-dirty flag is set) so that specifier recomputation
3803 caused as a result of this will work properly and not ABORT. */
3804 Fset_window_buffer (new, o->buffer, Qt);
3809 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3810 Make the selected window COUNT lines taller.
3811 From program, optional second arg HORIZONTALP non-nil means grow
3812 sideways COUNT columns, and optional third arg WINDOW specifies the
3813 window to change instead of the selected window.
3815 (count, horizontalp, window))
3818 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0);
3822 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3823 Make the selected window COUNT pixels taller.
3824 From program, optional second arg HORIZONTALP non-nil means grow
3825 sideways COUNT pixels, and optional third arg WINDOW specifies the
3826 window to change instead of the selected window.
3828 (count, horizontalp, window))
3831 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1);
3835 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3836 Make the selected window COUNT lines shorter.
3837 From program, optional second arg HORIZONTALP non-nil means shrink
3838 sideways COUNT columns, and optional third arg WINDOW specifies the
3839 window to change instead of the selected window.
3841 (count, horizontalp, window))
3844 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0);
3848 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3849 Make the selected window COUNT pixels smaller.
3850 From program, optional second arg HORIZONTALP non-nil means shrink
3851 sideways COUNT pixels, and optional third arg WINDOW specifies the
3852 window to change instead of the selected window.
3854 (count, horizontalp, window))
3857 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1);
3862 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3863 int include_gutters_p)
3866 int defheight, defwidth;
3870 XSETWINDOW (window, w);
3872 avail_height = (pixel_height -
3873 (include_gutters_p ? 0 :
3874 window_top_window_gutter_height (w) +
3875 window_bottom_window_gutter_height (w)));
3877 default_face_height_and_width (window, &defheight, &defwidth);
3879 char_height = avail_height / defheight;
3881 /* It's the calling function's responsibility to check these values
3882 and make sure they're not out of range.
3884 #### We need to go through the calling functions and actually
3886 return max (0, char_height);
3890 window_char_height_to_pixel_height (struct window *w, int char_height,
3891 int include_gutters_p)
3894 int defheight, defwidth;
3899 XSETWINDOW (window, w);
3901 default_face_height_and_width (window, &defheight, &defwidth);
3903 avail_height = char_height * defheight;
3904 pixel_height = (avail_height +
3905 (include_gutters_p ? 0 :
3906 window_top_window_gutter_height (w) +
3907 window_bottom_window_gutter_height (w)));
3909 /* It's the calling function's responsibility to check these values
3910 and make sure they're not out of range.
3912 #### We need to go through the calling functions and actually
3914 return max (0, pixel_height);
3917 /* Return number of default lines of text can fit in the window W.
3918 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3919 horizontal scrollbar) in the space that is used for the calculation.
3920 This doesn't include space used by the frame gutters.
3923 window_char_height (struct window *w, int include_gutters_p)
3925 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3930 * Return number of lines currently displayed in window w. If
3931 * end-of-buffer is displayed then the area below end-of-buffer is assume
3932 * to be blank lines of default height.
3933 * Does not include the modeline.
3936 window_displayed_height (struct window *w)
3938 struct buffer *b = XBUFFER (w->buffer);
3939 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3941 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3943 : w->window_end_pos[CURRENT_DISP]);
3945 if (!Dynarr_length (dla))
3946 return window_char_height (w, 0);
3948 num_lines = Dynarr_length (dla);
3950 /* #### Document and assert somewhere that w->window_end_pos == -1
3951 indicates that end-of-buffer is being displayed. */
3954 struct display_line *dl = Dynarr_atp (dla, 0);
3955 int ypos1 = dl->ypos + dl->descent;
3956 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3958 int defheight, defwidth;
3960 XSETWINDOW (window, w);
3966 if (Dynarr_length (dla) == 1)
3967 ypos1 = WINDOW_TEXT_TOP (w);
3970 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3971 /* If this line is clipped then we know that there is no
3972 blank room between eob and the modeline. If we are
3973 scrolling on clipped lines just know off the clipped
3975 if (scroll_on_clipped_lines && dl->clip)
3976 return num_lines - 1;
3977 ypos1 = dl->ypos + dl->descent - dl->clip;
3981 default_face_height_and_width (window, &defheight, &defwidth);
3982 /* #### This probably needs to know about the clipping area once a
3983 final definition is decided on. */
3984 num_lines += ((ypos2 - ypos1) / defheight);
3988 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3991 if (scroll_on_clipped_lines
3992 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
4000 window_pixel_width (Lisp_Object window)
4002 return WINDOW_WIDTH (XWINDOW (window));
4005 /* Calculate the pixel of a window, optionally including margin space
4006 but no vertical gutters. */
4008 window_pixel_width_to_char_width (struct window *w, int pixel_width,
4009 int include_margins_p)
4013 int defheight, defwidth;
4016 XSETWINDOW (window, w);
4018 avail_width = (pixel_width -
4019 window_left_gutter_width (w, 0) -
4020 window_right_gutter_width (w, 0) -
4021 (include_margins_p ? 0 : window_left_margin_width (w)) -
4022 (include_margins_p ? 0 : window_right_margin_width (w)));
4024 default_face_height_and_width (window, &defheight, &defwidth);
4026 char_width = (avail_width / defwidth);
4028 /* It's the calling function's responsibility to check these values
4029 and make sure they're not out of range.
4031 #### We need to go through the calling functions and actually
4033 return max (0, char_width);
4037 window_char_width_to_pixel_width (struct window *w, int char_width,
4038 int include_margins_p)
4042 int defheight, defwidth;
4045 XSETWINDOW (window, w);
4047 default_face_height_and_width (window, &defheight, &defwidth);
4049 avail_width = char_width * defwidth;
4050 pixel_width = (avail_width +
4051 window_left_window_gutter_width (w, 0) +
4052 window_right_window_gutter_width (w, 0) +
4053 (include_margins_p ? 0 : window_left_margin_width (w)) +
4054 (include_margins_p ? 0 : window_right_margin_width (w)));
4056 /* It's the calling function's responsibility to check these values
4057 and make sure they're not out of range.
4059 #### We need to go through the calling functions and actually
4061 return max (0, pixel_width);
4064 /* This returns the usable space which doesn't include space needed by
4065 scrollbars or divider lines. */
4067 window_char_width (struct window *w, int include_margins_p)
4069 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
4073 #define MINSIZE(w) \
4075 ? window_min_width * defwidth \
4076 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4079 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4081 #define CURSIZE(w) \
4082 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4084 #define CURCHARSIZE(w) \
4085 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4087 #define MINCHARSIZE(window) \
4088 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4089 ? 1 : window_min_height)
4092 window_pixheight (Lisp_Object w)
4094 return window_pixel_height (XWINDOW (w));
4097 /* Unlike set_window_pixheight, this function
4098 also changes the heights of the siblings so as to
4099 keep everything consistent. */
4102 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp,
4105 struct window *win = decode_window (window);
4106 int widthflag = !NILP (horizontalp);
4111 int (*sizefun) (Lisp_Object) = (widthflag
4112 ? window_pixel_width
4113 : window_pixheight);
4114 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4115 ? set_window_pixwidth
4116 : set_window_pixheight);
4118 int defheight, defwidth;
4123 check_min_window_sizes ();
4125 XSETWINDOW (window, win);
4126 f = XFRAME (win->frame);
4127 if (EQ (window, FRAME_ROOT_WINDOW (f)))
4128 error ("Won't change only window");
4130 /* #### This is very likely incorrect and instead the char_to_pixel_
4131 functions should be called. */
4132 default_face_height_and_width (window, &defheight, &defwidth);
4136 w = XWINDOW (window);
4141 error ("No other window to side of this one");
4145 ? !NILP (XWINDOW (parent)->hchild)
4146 : !NILP (XWINDOW (parent)->vchild))
4151 sizep = &CURSIZE (w);
4152 dim = CURCHARSIZE (w);
4154 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4155 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4157 if (MINI_WINDOW_P (XWINDOW (window)))
4159 else if (!NILP (parent))
4161 Fdelete_window (window, Qnil);
4167 delta *= (widthflag ? defwidth : defheight);
4172 maxdelta = ((!NILP (parent))
4173 ? (*sizefun) (parent) - *sizep
4174 : ((!NILP (w->next))
4175 ? (*sizefun) (w->next) - MINSIZE (w->next)
4176 : ((!NILP (w->prev))
4177 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4178 /* This is a frame with only one window,
4179 a minibuffer-only or a minibufferless frame. */
4182 if (delta > maxdelta)
4183 /* This case traps trying to make the minibuffer
4184 the full frame, or make the only window aside from the
4185 minibuffer the full frame. */
4192 /* #### Chuck: is this correct? */
4193 if (*sizep + delta < MINSIZE (window))
4195 Fdelete_window (window);
4201 if (!NILP (w->next) &&
4202 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4204 CURBEG (XWINDOW (w->next)) += delta;
4205 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4206 (*setsizefun) (window, *sizep + delta, 0);
4208 else if (!NILP (w->prev) &&
4209 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4211 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4212 CURBEG (w) -= delta;
4213 (*setsizefun) (window, *sizep + delta, 0);
4218 int opht = (*sizefun) (parent);
4220 /* If trying to grow this window to or beyond size of the parent,
4221 make delta1 so big that, on shrinking back down,
4222 all the siblings end up with less than one line and are deleted. */
4223 if (opht <= *sizep + delta)
4224 delta1 = opht * opht * 2;
4225 /* Otherwise, make delta1 just right so that if we add delta1
4226 lines to this window and to the parent, and then shrink
4227 the parent back to its original size, the new proportional
4228 size of this window will increase by delta. */
4230 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4232 /* Add delta1 lines or columns to this window, and to the parent,
4233 keeping things consistent while not affecting siblings. */
4234 CURSIZE (XWINDOW (parent)) = opht + delta1;
4235 (*setsizefun) (window, *sizep + delta1, 0);
4237 /* Squeeze out delta1 lines or columns from our parent,
4238 shrinking this window and siblings proportionately.
4239 This brings parent back to correct size.
4240 Delta1 was calculated so this makes this window the desired size,
4241 taking it all out of the siblings. */
4242 (*setsizefun) (parent, opht, 0);
4245 SET_LAST_MODIFIED (w, 0);
4246 SET_LAST_FACECHANGE (w);
4247 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4248 /* overkill maybe, but better to be correct */
4249 MARK_FRAME_GUTTERS_CHANGED (f);
4259 /* Scroll contents of window WINDOW up COUNT lines.
4260 If COUNT < (top line height / average line height) then we just adjust
4263 window_scroll (Lisp_Object window, Lisp_Object count, int direction,
4264 Error_behavior errb)
4266 struct window *w = XWINDOW (window);
4267 struct buffer *b = XBUFFER (w->buffer);
4268 int selected = EQ (window, Fselected_window (Qnil));
4270 Lisp_Object point, tem;
4271 display_line_dynarr *dla;
4272 int fheight, fwidth, modeline = 0;
4273 struct display_line* dl;
4276 point = make_int (BUF_PT (b));
4279 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4281 if (pos < BUF_BEGV (b))
4283 else if (pos > BUF_ZV (b))
4286 point = make_int (pos);
4289 /* Always set force_start so that redisplay_window will run
4290 the window-scroll-functions. */
4293 /* #### When the fuck does this happen? I'm so glad that history has
4294 completely documented the behavior of the scrolling functions under
4295 all circumstances. */
4296 tem = Fpos_visible_in_window_p (point, window);
4299 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4301 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4302 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4303 WINDOW_TEXT_TOP_CLIP (w) = 0;
4304 MARK_WINDOWS_CHANGED (w);
4309 if (EQ (count, Qminus))
4313 count = Fprefix_numeric_value (count);
4314 value = XINT (count) * direction;
4317 return; /* someone just made a pointless call */
4321 /* If the user didn't specify how far to scroll then we have to figure it
4322 out by ourselves. */
4323 if (NILP (count) || EQ (count, Qminus))
4325 /* Going forwards is easy. If that is what we are doing then just
4326 set value and the section which handles the user specifying a
4327 positive value will work. */
4330 value = window_displayed_height (w) - next_screen_context_lines;
4331 value = (value < 1 ? 1 : value);
4334 /* Going backwards is hard. We can't use the same loop used if the
4335 user specified a negative value because we care about
4336 next_screen_context_lines. In a variable height world you don't
4337 know how many lines above you can actually be displayed and still
4338 have the context lines appear. So we leave value set to 0 and add
4339 a separate section to deal with this. */
4343 if (direction == 1 && !value)
4348 /* Determine parameters to test for partial line scrolling with. */
4349 dla = window_display_lines (w, CURRENT_DISP);
4351 if (INTP (Vwindow_pixel_scroll_increment))
4352 fheight = XINT (Vwindow_pixel_scroll_increment);
4353 else if (!NILP (Vwindow_pixel_scroll_increment))
4354 default_face_height_and_width (window, &fheight, &fwidth);
4356 if (Dynarr_length (dla) >= 1)
4357 modeline = Dynarr_atp (dla, 0)->modeline;
4359 dl = Dynarr_atp (dla, modeline);
4363 /* Go for partial display line scrolling. This just means bumping
4364 the clip by a reasonable amount and redisplaying, everything else
4365 remains unchanged. */
4366 if (!NILP (Vwindow_pixel_scroll_increment)
4368 Dynarr_length (dla) >= (1 + modeline)
4370 (dl->ascent - dl->top_clip) > fheight * value)
4372 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4373 MARK_WINDOWS_CHANGED (w);
4378 Bufpos startp, old_start;
4380 if (WINDOW_TEXT_TOP_CLIP (w))
4382 WINDOW_TEXT_TOP_CLIP (w) = 0;
4383 MARK_WINDOWS_CHANGED (w);
4386 old_start = marker_position (w->start[CURRENT_DISP]);
4387 startp = vmotion (w, old_start, value, &vtarget);
4389 if (vtarget < value &&
4390 (w->window_end_pos[CURRENT_DISP] == -1
4391 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4393 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4398 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4401 w->start_at_line_beg = beginning_of_line_p (b, startp);
4402 MARK_WINDOWS_CHANGED (w);
4404 if (!point_would_be_visible (w, startp, XINT (point)))
4407 BUF_SET_PT (b, startp);
4409 set_marker_restricted (w->pointm[CURRENT_DISP],
4418 /* Go for partial display line scrolling. This just means bumping
4419 the clip by a reasonable amount and redisplaying, everything else
4420 remains unchanged. */
4421 if (!NILP (Vwindow_pixel_scroll_increment)
4423 Dynarr_length (dla) >= (1 + modeline)
4425 (dl->ascent - dl->top_clip) - fheight * value <
4426 (dl->ascent + dl->descent - dl->clip)
4428 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4430 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4431 MARK_WINDOWS_CHANGED (w);
4436 Bufpos startp, old_start;
4438 if (WINDOW_TEXT_TOP_CLIP (w))
4440 WINDOW_TEXT_TOP_CLIP (w) = 0;
4441 MARK_WINDOWS_CHANGED (w);
4444 old_start = marker_position (w->start[CURRENT_DISP]);
4445 startp = vmotion (w, old_start, value, &vtarget);
4448 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4450 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4455 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4458 w->start_at_line_beg = beginning_of_line_p (b, startp);
4459 MARK_WINDOWS_CHANGED (w);
4461 /* #### Scroll back by less than a line. This code was
4462 originally for scrolling over large pixmaps and it
4463 loses when a line being *exposed* at the top of the
4464 window is bigger than the current one. However, for
4465 pixel based scrolling in general we can guess that
4466 the line we are going to display is probably the same
4467 size as the one we are on. In that instance we can
4468 have a reasonable stab at a suitable top clip. Fixing
4469 this properly is hard (and probably slow) as we would
4470 have to call redisplay to figure out the exposed line
4472 if (!NILP (Vwindow_pixel_scroll_increment)
4473 && Dynarr_length (dla) >= (1 + modeline)
4474 && dl->ascent + fheight * value > 0)
4476 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4479 if (!point_would_be_visible (w, startp, XINT (point)))
4483 if (MINI_WINDOW_P (w))
4486 new_point = start_of_last_line (w, startp);
4489 BUF_SET_PT (b, new_point);
4491 set_marker_restricted (w->pointm[CURRENT_DISP],
4492 make_int (new_point),
4498 else /* value == 0 && direction == -1 */
4500 if (WINDOW_TEXT_TOP_CLIP (w))
4502 WINDOW_TEXT_TOP_CLIP (w) = 0;
4503 MARK_WINDOWS_CHANGED (w);
4505 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4507 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4513 int movement = next_screen_context_lines - 1;
4514 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4515 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4517 start_with_point_on_display_line (w, bottom,
4518 -1 - (movement - vtarget));
4520 if (startp >= old_startp)
4521 startp = vmotion (w, old_startp, -1, NULL);
4523 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4526 w->start_at_line_beg = beginning_of_line_p (b, startp);
4527 MARK_WINDOWS_CHANGED (w);
4529 if (!point_would_be_visible (w, startp, XINT (point)))
4531 Bufpos new_point = start_of_last_line (w, startp);
4534 BUF_SET_PT (b, new_point);
4536 set_marker_restricted (w->pointm[CURRENT_DISP],
4537 make_int (new_point),
4544 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4545 Scroll text of current window up COUNT lines; or near full screen if no arg.
4546 A near full screen is `next-screen-context-lines' less than a full screen.
4547 Negative COUNT means scroll downward.
4548 When calling from a program, supply an integer as argument or nil.
4549 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4550 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4553 The characters that are moved over may be added to the current selection
4554 \(i.e. active region) if the Shift key is held down, a motion key is used
4555 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4556 the documentation for this variable for more details.
4560 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME);
4564 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4565 Scroll text of current window down COUNT lines; or near full screen if no arg.
4566 A near full screen is `next-screen-context-lines' less than a full screen.
4567 Negative COUNT means scroll upward.
4568 When calling from a program, supply a number as argument or nil.
4569 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4570 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4573 The characters that are moved over may be added to the current selection
4574 \(i.e. active region) if the Shift key is held down, a motion key is used
4575 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4576 the documentation for this variable for more details.
4580 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME);
4584 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4585 Return the other window for "other window scroll" commands.
4586 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4587 specifies the window.
4588 If `other-window-scroll-buffer' is non-nil, a window
4589 showing that buffer is used.
4594 Lisp_Object selected_window = Fselected_window (Qnil);
4596 if (MINI_WINDOW_P (XWINDOW (selected_window))
4597 && !NILP (Vminibuffer_scroll_window))
4598 window = Vminibuffer_scroll_window;
4599 /* If buffer is specified, scroll that buffer. */
4600 else if (!NILP (Vother_window_scroll_buffer))
4602 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4604 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4608 /* Nothing specified; look for a neighboring window on the same
4610 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4612 if (EQ (window, selected_window))
4613 /* That didn't get us anywhere; look for a window on another
4616 window = Fnext_window (window, Qnil, Qt, Qnil);
4617 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4618 && ! EQ (window, selected_window));
4621 CHECK_LIVE_WINDOW (window);
4623 if (EQ (window, selected_window))
4624 error ("There is no other window");
4629 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4630 Scroll next window upward COUNT lines; or near full frame if no arg.
4631 The next window is the one below the current one; or the one at the top
4632 if the current one is at the bottom. Negative COUNT means scroll downward.
4633 When calling from a program, supply a number as argument or nil.
4635 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4636 specifies the window to scroll.
4637 If `other-window-scroll-buffer' is non-nil, scroll the window
4638 showing that buffer, popping the buffer up if necessary.
4642 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME);
4646 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4647 Scroll selected window display COUNT columns left.
4648 Default for COUNT is window width minus 2.
4650 The characters that are moved over may be added to the current selection
4651 \(i.e. active region) if the Shift key is held down, a motion key is used
4652 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4653 the documentation for this variable for more details.
4657 Lisp_Object window = Fselected_window (Qnil);
4658 struct window *w = XWINDOW (window);
4659 int n = (NILP (count) ?
4660 window_char_width (w, 0) - 2 :
4661 XINT (Fprefix_numeric_value (count)));
4663 return Fset_window_hscroll (window, make_int (w->hscroll + n));
4666 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4667 Scroll selected window display COUNT columns right.
4668 Default for COUNT is window width minus 2.
4670 The characters that are moved over may be added to the current selection
4671 \(i.e. active region) if the Shift key is held down, a motion key is used
4672 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4673 the documentation for this variable for more details.
4677 Lisp_Object window = Fselected_window (Qnil);
4678 struct window *w = XWINDOW (window);
4679 int n = (NILP (count) ?
4680 window_char_width (w, 0) - 2 :
4681 XINT (Fprefix_numeric_value (count)));
4683 return Fset_window_hscroll (window, make_int (w->hscroll - n));
4686 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4687 Center point in WINDOW. With N, put point on line N.
4688 The desired position of point is always relative to the window.
4689 If WINDOW is nil, the selected window is used.
4693 struct window *w = decode_window (window);
4694 struct buffer *b = XBUFFER (w->buffer);
4695 Bufpos opoint = BUF_PT (b);
4699 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4702 n = Fprefix_numeric_value (n);
4704 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4707 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4709 w->start_at_line_beg = beginning_of_line_p (b, startp);
4711 MARK_WINDOWS_CHANGED (w);
4715 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4716 Position point relative to WINDOW.
4717 With no argument, position text at center of window.
4718 An argument specifies window line; zero means top of window,
4719 negative means relative to bottom of window.
4720 If WINDOW is nil, the selected window is used.
4727 Bufpos start, new_point;
4730 /* Don't use decode_window() because we need the new value of
4733 window = Fselected_window (Qnil);
4735 CHECK_LIVE_WINDOW (window);
4736 w = XWINDOW (window);
4737 b = XBUFFER (w->buffer);
4739 height = window_displayed_height (w);
4740 selected = EQ (window, Fselected_window (w->frame));
4746 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4747 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4749 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4752 BUF_SET_PT (b, new_point);
4754 Fset_window_point (window, make_int (new_point));
4756 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4760 start = marker_position (w->start[CURRENT_DISP]);
4761 if (start < BUF_BEGV (b))
4762 start = BUF_BEGV (b);
4763 else if (start > BUF_ZV (b))
4767 new_point = BUF_PT (b);
4769 new_point = marker_position (w->pointm[CURRENT_DISP]);
4771 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4774 BUF_SET_PT (b, new_point);
4776 Fset_window_point (window, make_int (new_point));
4778 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4781 return make_int (retval);
4785 /* #### Is this going to work right when at eob? */
4786 arg = Fprefix_numeric_value (arg);
4788 XSETINT (arg, XINT (arg) + height);
4791 start = marker_position (w->start[CURRENT_DISP]);
4792 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4795 new_point = BUF_PT (b);
4797 new_point = marker_position (w->pointm[CURRENT_DISP]);
4799 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4802 BUF_SET_PT (b, new_point);
4804 Fset_window_point (window, make_int (new_point));
4806 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4808 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4814 BUF_SET_PT (b, start);
4816 Fset_window_point (window, make_int (start));
4820 return Fvertical_motion (arg, window, Qnil);
4824 new_point = vmotion (XWINDOW (window),
4825 marker_position (w->pointm[CURRENT_DISP]),
4827 Fset_window_point (window, make_int (new_point));
4828 return make_int (vpos);
4834 map_windows_1 (Lisp_Object window,
4835 int (*mapfun) (struct window *w, void *closure),
4838 for (; !NILP (window); window = XWINDOW (window)->next)
4841 struct window *w = XWINDOW (window);
4843 if (!NILP (w->vchild))
4844 retval = map_windows_1 (w->vchild, mapfun, closure);
4845 else if (!NILP (w->hchild))
4846 retval = map_windows_1 (w->hchild, mapfun, closure);
4848 retval = (mapfun) (w, closure);
4857 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4858 invocation of MAPFUN. If any invocation of MAPFUN returns
4859 non-zero, the mapping is halted. Otherwise, map_windows() maps
4860 over all windows in F.
4862 If MAPFUN creates or deletes windows, the behavior is undefined. */
4865 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4869 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4872 Lisp_Object frmcons, devcons, concons;
4874 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4876 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4888 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4891 w->shadow_thickness_changed = 1;
4892 MARK_WINDOWS_CHANGED (w);
4896 vertical_divider_changed_in_window (Lisp_Object specifier,
4900 MARK_WINDOWS_CHANGED (w);
4901 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4904 /* also used in scrollbar.c */
4906 some_window_value_changed (Lisp_Object specifier, struct window *w,
4909 MARK_WINDOWS_CHANGED (w);
4912 #ifdef MEMORY_USAGE_STATS
4918 #ifdef HAVE_SCROLLBARS
4922 int other_redisplay;
4927 compute_window_mirror_usage (struct window_mirror *mir,
4928 struct window_stats *stats,
4929 struct overhead_stats *ovstats)
4933 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4935 #ifdef HAVE_SCROLLBARS
4937 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4940 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4943 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4946 #endif /* HAVE_SCROLLBARS */
4947 stats->other_redisplay +=
4948 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4949 stats->other_redisplay +=
4950 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4954 compute_window_usage (struct window *w, struct window_stats *stats,
4955 struct overhead_stats *ovstats)
4958 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4959 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4960 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4961 stats->line_start +=
4962 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4963 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4966 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4967 Return stats about the memory usage of window WINDOW.
4968 The values returned are in the form of an alist of usage types and byte
4969 counts. The byte counts attempt to encompass all the memory used
4970 by the window (separate from the memory logically associated with a
4971 buffer or frame), including internal structures and any malloc()
4972 overhead associated with them. In practice, the byte counts are
4973 underestimated because certain memory usage is very hard to determine
4974 \(e.g. the amount of memory used inside the Xt library or inside the
4975 X server) and because there is other stuff that might logically
4976 be associated with a window, buffer, or frame (e.g. window configurations,
4977 glyphs) but should not obviously be included in the usage counts.
4979 Multiple slices of the total memory usage may be returned, separated
4980 by a nil. Each slice represents a particular view of the memory, a
4981 particular way of partitioning it into groups. Within a slice, there
4982 is no overlap between the groups of memory, and each slice collectively
4983 represents all the memory concerned.
4987 struct window_stats stats;
4988 struct overhead_stats ovstats;
4989 Lisp_Object val = Qnil;
4991 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4993 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4995 val = acons (Qface_cache, make_int (stats.face), val);
4996 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4997 #ifdef HAVE_SCROLLBARS
4998 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
5000 val = acons (Qline_start_cache, make_int (stats.line_start), val);
5001 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
5002 val = acons (Qother, make_int (stats.other), val);
5003 val = Fcons (Qnil, val);
5004 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
5005 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
5006 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
5008 return Fnreverse (val);
5011 #endif /* MEMORY_USAGE_STATS */
5014 /************************************************************************/
5015 /* Window configurations */
5016 /************************************************************************/
5018 /* #### This window configuration stuff has had serious bugs lurking in it
5019 for years; it would be a -huge- win if this was reimplemented in lisp.
5022 /* If you add anything to this structure make sure saved_window_equal
5026 Lisp_Object window; /* window */
5027 Lisp_Object buffer; /* buffer */
5028 Lisp_Object start; /* copied marker */
5029 Lisp_Object pointm; /* copied marker */
5030 Lisp_Object sb_point; /* copied marker */
5031 Lisp_Object mark; /* copied marker */
5037 Charcount modeline_hscroll;
5038 int parent_index; /* index into saved_windows */
5039 int prev_index; /* index into saved_windows */
5040 char start_at_line_beg; /* boolean */
5042 #define WINDOW_SLOT_DECLARATION
5043 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5044 #include "winslots.h"
5047 /* If you add anything to this structure make sure window_config_equal
5049 struct window_config
5051 struct lcrecord_header header;
5052 /* int frame_width; No longer needed, JV
5053 int frame_height; */
5055 Lisp_Object selected_frame;
5057 Lisp_Object current_window;
5058 Lisp_Object current_buffer;
5059 Lisp_Object minibuffer_scroll_window;
5060 Lisp_Object root_window;
5061 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5062 /* Record the values of window-min-width and window-min-height
5063 so that window sizes remain consistent with them. */
5064 int min_width, min_height;
5065 unsigned int saved_windows_count;
5066 /* Zero-sized arrays aren't ANSI C */
5067 struct saved_window saved_windows[1];
5070 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5071 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5072 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5073 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5074 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5077 mark_window_config (Lisp_Object obj)
5079 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5081 mark_object (config->current_window);
5082 mark_object (config->current_buffer);
5083 mark_object (config->minibuffer_scroll_window);
5084 mark_object (config->root_window);
5086 for (i = 0; i < config->saved_windows_count; i++)
5088 struct saved_window *s = SAVED_WINDOW_N (config, i);
5089 mark_object (s->window);
5090 mark_object (s->buffer);
5091 mark_object (s->start);
5092 mark_object (s->pointm);
5093 mark_object (s->sb_point);
5094 mark_object (s->mark);
5096 /* #### This looked like this. I do not see why specifier cached
5097 values should not be marked, as such specifiers as toolbars
5098 might have GC-able instances. Freed configs are not marked,
5099 aren't they? -- kkm */
5100 mark_object (s->dedicated);
5102 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5103 #include "winslots.h"
5109 inline static size_t
5110 sizeof_window_config_for_n_windows (unsigned int n)
5112 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (struct window_config,
5113 struct saved_window, saved_windows, n);
5117 sizeof_window_config (const void *h)
5119 const struct window_config *c = (const struct window_config *) h;
5120 return sizeof_window_config_for_n_windows (c->saved_windows_count);
5124 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5126 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5129 error ("printing unreadable object #<window-configuration 0x%x>",
5130 config->header.uid);
5131 write_c_string ("#<window-configuration ", printcharfun);
5132 sprintf (buf, "0x%x>", config->header.uid);
5133 write_c_string (buf, printcharfun);
5136 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
5137 window_configuration,
5139 print_window_config,
5140 0, 0, 0, 0, sizeof_window_config,
5141 struct window_config);
5144 /* Returns a boolean indicating whether the two saved windows are
5147 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
5149 #define WINDOW_SLOT(slot, compare) \
5150 if (!compare (win1->slot, win2->slot)) \
5152 #include "winslots.h"
5155 EQ (win1->window, win2->window) &&
5156 EQ (win1->buffer, win2->buffer) &&
5157 internal_equal (win1->start, win2->start, 0) &&
5158 internal_equal (win1->pointm, win2->pointm, 0) &&
5159 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5160 internal_equal (win1->mark, win2->mark, 0) &&
5161 win1->pixel_left == win2->pixel_left &&
5162 win1->pixel_top == win2->pixel_top &&
5163 win1->pixel_width == win2->pixel_width &&
5164 win1->pixel_height == win2->pixel_height &&
5165 win1->hscroll == win2->hscroll &&
5166 win1->modeline_hscroll == win2->modeline_hscroll &&
5167 win1->parent_index == win2->parent_index &&
5168 win1->prev_index == win2->prev_index &&
5169 win1->start_at_line_beg == win2->start_at_line_beg;
5172 /* Returns a boolean indicating whether the two given configurations
5175 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5177 struct window_config *fig1, *fig2;
5180 /* First check if they are truly the same. */
5181 if (EQ (conf1, conf2))
5184 fig1 = XWINDOW_CONFIGURATION (conf1);
5185 fig2 = XWINDOW_CONFIGURATION (conf2);
5187 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5188 EQ (fig1->current_window, fig2->current_window) &&
5189 EQ (fig1->current_buffer, fig2->current_buffer) &&
5190 EQ (fig1->root_window, fig2->root_window) &&
5191 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5193 fig1->frame_width == fig2->frame_width &&
5194 fig1->frame_height == fig2->frame_height)) */
5197 for (i = 0; i < fig1->saved_windows_count; i++)
5199 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5200 SAVED_WINDOW_N (fig2, i)))
5207 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5208 Return t if OBJECT is a window-configuration object.
5212 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5216 mark_windows_in_use_closure (struct window *w, void *closure)
5218 int mark = *(int *)closure;
5219 w->config_mark = mark;
5224 mark_windows_in_use (struct frame *f, int mark)
5226 map_windows (f, mark_windows_in_use_closure, &mark);
5229 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5231 free_window_configuration (Lisp_Object window_config)
5234 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5236 /* Free all the markers. It's not completely necessary that
5237 we do this (window configs sitting in a free list aren't
5238 marked normally so the markers wouldn't be marked anyway)
5239 but it's more efficient. */
5240 for (i = 0; i < config->saved_windows_count; i++)
5242 struct saved_window *p = SAVED_WINDOW_N (config, i);
5244 if (!NILP (p->pointm))
5246 free_marker (XMARKER (p->pointm));
5249 if (!NILP (p->start))
5251 free_marker (XMARKER (p->start));
5254 if (!NILP (p->sb_point))
5256 free_marker (XMARKER (p->sb_point));
5259 if (!NILP (p->mark))
5261 free_marker (XMARKER (p->mark));
5266 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5267 free_managed_lcrecord (Vwindow_configuration_free_list
5268 [config->saved_windows_count - 1],
5274 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5275 Set the configuration of windows and buffers as specified by CONFIGURATION.
5276 CONFIGURATION must be a value previously returned
5277 by `current-window-configuration' (which see).
5282 struct window_config *config;
5283 struct saved_window *p;
5284 Lisp_Object new_current_buffer;
5288 struct gcpro gcpro1;
5289 Lisp_Object old_window_config;
5290 /* int previous_frame_height;
5291 int previous_frame_width;*/
5292 int previous_pixel_top;
5293 int previous_pixel_height;
5294 int previous_pixel_left;
5295 int previous_pixel_width;
5296 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5297 int real_font_height;
5298 int converted_minibuf_height,target_minibuf_height;
5299 int specpdl_count = specpdl_depth ();
5301 GCPRO1 (configuration);
5303 CHECK_WINDOW_CONFIGURATION (configuration);
5304 config = XWINDOW_CONFIGURATION (configuration);
5306 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5309 /* Do not signal an error here if the frame was deleted. There are
5310 reasonable cases where we could get here with a deleted frame and
5311 just want to do close to nothing instead. */
5313 if (FRAME_LIVE_P (f))
5315 /* restore the frame characteristics */
5317 new_current_buffer = config->current_buffer;
5318 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5319 new_current_buffer = Qnil;
5322 * Assumed precondition: w->config_mark = 0 for all w
5323 * This procedure should ensure this is true by the time it exits
5324 * to ensure the precondition for future calls.
5326 * We use w->config_mark to know whether we're modifying a
5327 * window that is currently visible on the frame (#### we
5328 * should just be able to check whether the window is dead
5329 * or not, but this way is safer?). As we process each
5330 * window, we set its config_mark to 0. At the end, we
5331 * go through all the windows that used to be on the frame,
5332 * set each one's config_mark to 0 (to maintain the
5333 * assumed precondition) and delete each one that's no
5336 * #### Using a window-configuration to keep track of
5337 * the current windows is wasteful. All we need is the
5338 * list of windows, so we could just use a dynarr.
5340 old_window_config = Fcurrent_window_configuration (frame);
5342 /* If the new configuration is already equal to the old, then stop
5343 right here. This saves the work below and it also saves
5344 triggering a full redisplay of this window. This is a huge win
5345 when using the mouse since the mode motion code uses
5346 save-window-excursion extensively but will rarely cause the
5347 configuration to actually change. */
5348 if (window_config_equal (configuration, old_window_config))
5350 free_window_configuration (old_window_config);
5355 /* We can't quit or even check for quit because that may cause
5356 investigation of the frame state, which may crash if the frame is
5357 in an inconsistent state. */
5358 begin_dont_check_for_quit ();
5359 record_unwind_protect (free_window_configuration, old_window_config);
5361 mark_windows_in_use (f, 1);
5362 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5363 /* Force subwindows to be remapped. This is overkill but saves
5364 us having to rely on the redisplay code to unmap any extant
5367 #### It does cause some extra flashing though which we could
5368 possibly avoid. So consider trying to get redisplay to work
5371 Removing the instances from the frame cache is wrong because
5372 an instance is only put in the frame cache when it is
5373 instantiated. So if we do this there is a chance that stuff
5374 will never get put back in the frame cache. */
5375 reset_frame_subwindow_instance_cache (f);
5378 /* JV: This is bogus,
5379 First of all, the units are inconsistent. The frame sizes are measured
5380 in characters but the window sizes are stored in pixels. So if a
5381 font size change happened between saving and restoring, the
5382 frame "sizes" maybe equal but the windows still should be
5383 resized. This is tickled a lot by the new "character size
5384 stays constant" policy in 21.0. It leads to very weird
5385 glitches (and possibly crashes when asserts are tickled).
5387 Just changing the units doesn't help because changing the
5388 toolbar configuration can also change the pixel positions.
5389 Luckily there is a much simpler way of doing this, see below.
5391 previous_frame_width = FRAME_WIDTH (f);
5392 previous_frame_height = FRAME_HEIGHT (f);
5393 /* If the frame has been resized since this window configuration was
5394 made, we change the frame to the size specified in the
5395 configuration, restore the configuration, and then resize it
5396 back. We keep track of the prevailing height in these variables. */
5397 if (config->frame_height != FRAME_HEIGHT (f)
5398 || config->frame_width != FRAME_WIDTH (f))
5399 change_frame_size (f, config->frame_height, config->frame_width, 0);
5402 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5403 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5404 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5405 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5407 /* remember some properties of the minibuffer */
5409 default_face_height_and_width (frame, &real_font_height, 0);
5410 assert(real_font_height > 0);
5412 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5414 previous_minibuf_height
5415 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5416 previous_minibuf_top
5417 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5418 previous_minibuf_width
5419 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5423 previous_minibuf_height = 0;
5424 previous_minibuf_top = 0;
5425 previous_minibuf_width = 0;
5427 converted_minibuf_height =
5428 (previous_minibuf_height % real_font_height) == 0 ?
5429 - (previous_minibuf_height / real_font_height ) : /* lines */
5430 previous_minibuf_height; /* pixels */
5432 /* Temporarily avoid any problems with windows that are smaller
5433 than they are supposed to be. */
5434 window_min_height = 1;
5435 window_min_width = 1;
5437 /* OK, now restore all the windows in the window config.
5438 This may involve "undeleting" windows, since the
5439 windows in the window config may be deleted.
5441 for (k = 0; k < config->saved_windows_count; k++)
5443 p = SAVED_WINDOW_N (config, k);
5444 w = XWINDOW (p->window);
5447 /* The window might be dead. In this case, its redisplay
5448 structures were freed, so we need to reallocate them. */
5449 if (!w->face_cachels)
5451 w->face_cachels = Dynarr_new (face_cachel);
5452 reset_face_cachels (w);
5454 if (!w->glyph_cachels)
5455 w->glyph_cachels = Dynarr_new (glyph_cachel);
5456 if (!w->line_start_cache)
5457 w->line_start_cache = Dynarr_new (line_start_cache);
5458 w->gutter_extent_modiff[0] = 0;
5459 w->gutter_extent_modiff[1] = 0;
5460 w->gutter_extent_modiff[2] = 0;
5461 w->gutter_extent_modiff[3] = 0;
5464 if (p->parent_index >= 0)
5465 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5469 if (p->prev_index >= 0)
5471 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5473 /* This is true for a minibuffer-only frame. */
5474 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5477 XWINDOW (w->prev)->next = p->window;
5482 if (!NILP (w->parent))
5484 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5486 XWINDOW (w->parent)->vchild = p->window;
5487 XWINDOW (w->parent)->hchild = Qnil;
5491 XWINDOW (w->parent)->hchild = p->window;
5492 XWINDOW (w->parent)->vchild = Qnil;
5496 if (!w->config_mark)
5498 /* #### This should be equivalent to the window previously
5499 having been dead. If we're brave, we'll put in an
5500 assertion to this effect. */
5501 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5503 else /* if (!EQ (w->buffer, p->buffer)) */
5505 /* With the new redisplay we let it know that a change has
5506 been made and it will take care of the rest. If we don't
5507 tell it something has possibly changed it could lead to
5508 incorrect display. */
5509 MARK_WINDOWS_CHANGED (w);
5512 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5513 WINDOW_TOP (w) = WINDOW_TOP (p);
5514 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5515 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5516 w->hscroll = p->hscroll;
5517 w->modeline_hscroll = p->modeline_hscroll;
5518 w->line_cache_last_updated = Qzero;
5519 /* When we restore a window's configuration, the identity of
5520 the window hasn't actually changed - so there is no
5521 reason why we shouldn't preserve the instance cache for
5522 it - unless it was originally deleted. This will often
5523 buy us something as we will not have to re-instantiate
5524 all the instances. This is because this is an instance
5525 cache - not a display cache. Preserving the display cache
5526 would definitely be wrong.
5528 We specifically want to do this for tabs, since for some
5529 reason finding a file will cause the configuration to be
5531 if (NILP (w->subwindow_instance_cache))
5532 w->subwindow_instance_cache =
5533 make_image_instance_cache_hash_table ();
5535 SET_LAST_MODIFIED (w, 1);
5536 SET_LAST_FACECHANGE (w);
5539 /* #### Consider making the instance cache a winslot. */
5540 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5541 #include "winslots.h"
5543 /* Reinstall the saved buffer and pointers into it. */
5544 if (NILP (p->buffer))
5545 w->buffer = p->buffer;
5548 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5549 /* If saved buffer is alive, install it. */
5551 w->buffer = p->buffer;
5552 w->start_at_line_beg = p->start_at_line_beg;
5553 set_marker_restricted (w->start[CURRENT_DISP],
5554 Fmarker_position (p->start),
5556 set_marker_restricted (w->pointm[CURRENT_DISP],
5557 Fmarker_position (p->pointm),
5559 set_marker_restricted (w->sb_point,
5560 Fmarker_position (p->sb_point),
5562 Fset_marker (XBUFFER (w->buffer)->mark,
5563 Fmarker_position (p->mark), w->buffer);
5565 /* As documented in Fcurrent_window_configuration, don't
5566 save the location of point in the buffer which was current
5567 when the window configuration was recorded. */
5568 if (!EQ (p->buffer, new_current_buffer) &&
5569 XBUFFER (p->buffer) == current_buffer)
5570 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5572 else if (NILP (w->buffer) ||
5573 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5574 /* Else if window's old buffer is dead too, get a live one. */
5576 /* #### The following line makes me nervous... */
5577 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5578 w->buffer = Fget_buffer_create (QSscratch);
5579 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5580 /* This will set the markers to beginning of visible
5582 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5583 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5585 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5586 w->start_at_line_beg = 1;
5589 /* Keeping window's old buffer; make sure the markers
5592 /* Set window markers at start of visible range. */
5593 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5594 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5596 if (XMARKER (w->sb_point)->buffer == 0)
5597 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5598 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5599 set_marker_restricted (w->pointm[CURRENT_DISP],
5601 (BUF_PT (XBUFFER (w->buffer))),
5603 w->start_at_line_beg = 1;
5608 FRAME_ROOT_WINDOW (f) = config->root_window;
5609 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5610 then calls do_switch_frame() below to select the frame that was
5611 recorded in the window config as being selected.
5613 Instead, we don't ever change the selected frame, and either
5614 call Fselect_window() below if the window config's frame is
5615 currently selected, or just set the selected window of the
5616 window config's frame. */
5619 /* Set the frame height to the value it had before this function. */
5620 if (previous_frame_height != FRAME_HEIGHT (f)
5621 || previous_frame_width != FRAME_WIDTH (f))
5622 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5624 /* We just reset the size and position of the minibuffer, to its old
5625 value, which needn't be valid. So we do some magic to see which value
5626 to actually take. Then we set it.
5629 We take the old value if is in the same units but differs from the
5632 #### Now we get more cases correct then ever before, but
5633 are we treating all? For instance what if the frames minibuf window
5634 is no longer the same one?
5636 target_minibuf_height = previous_minibuf_height;
5637 if (converted_minibuf_height &&
5638 (converted_minibuf_height * config->minibuf_height) > 0 &&
5639 (converted_minibuf_height != config->minibuf_height))
5641 target_minibuf_height = config->minibuf_height < 0 ?
5642 - (config->minibuf_height * real_font_height) :
5643 config->minibuf_height;
5644 target_minibuf_height =
5645 max(target_minibuf_height,real_font_height);
5647 if (previous_minibuf_height)
5649 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5650 = previous_minibuf_top -
5651 (target_minibuf_height - previous_minibuf_height);
5652 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5653 target_minibuf_height, 0);
5654 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5655 previous_minibuf_width, 0);
5658 /* This is a better way to deal with frame resizing, etc.
5659 What we _actually_ want is for the old (just restored)
5661 into the place of the new one. So we just do that. Simple! */
5662 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5663 /* Note that this function also updates the subwindow
5665 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5666 previous_pixel_height -
5667 (target_minibuf_height - previous_minibuf_height), 0);
5668 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5669 /* Note that this function also updates the subwindow
5671 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5673 /* If restoring in the current frame make the window current,
5674 otherwise just update the frame selected_window slot to be
5675 the restored current_window. */
5676 if (f == selected_frame ())
5679 /* When using `pop-window-configuration', often the minibuffer
5680 ends up as the selected window even though it's not active ...
5681 I really don't know the cause of this, but it should never
5682 happen. This kludge should fix it.
5684 #### Find out why this is really going wrong. */
5685 if (!minibuf_level &&
5686 MINI_WINDOW_P (XWINDOW (config->current_window)))
5687 window_to_select = Fnext_window (config->current_window,
5690 window_to_select = config->current_window;
5692 /* Do this last so that buffer stacking is calculated
5694 Fselect_window (config->current_window, Qnil);
5696 if (!NILP (new_current_buffer))
5698 Fset_buffer (new_current_buffer);
5699 Frecord_buffer (new_current_buffer);
5703 Fset_buffer (XWINDOW (config->current_window)->buffer);
5704 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5708 set_frame_selected_window (f, config->current_window);
5711 old_window_config = Qnil; /* Warning suppression */
5713 /* Restore the minimum heights recorded in the configuration. */
5714 window_min_height = config->min_height;
5715 window_min_width = config->min_width;
5718 /* see above comment */
5719 /* Fselect_window will have made f the selected frame, so we
5720 reselect the proper frame here. Fhandle_switch_frame will change the
5721 selected window too, but that doesn't make the call to
5722 Fselect_window above totally superfluous; it still sets f's
5724 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5725 do_switch_frame (config->selected_frame, Qnil, 0);
5728 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5730 if (FRAME_LIVE_P (f))
5732 /* Do this before calling recompute_all_cached_specifiers_in_window()
5733 so that things like redisplay_redraw_cursor() won't ABORT due
5734 to no window mirror present. */
5735 f->mirror_dirty = 1;
5737 config = XWINDOW_CONFIGURATION (old_window_config);
5738 for (k = 0; k < config->saved_windows_count; k++)
5740 p = SAVED_WINDOW_N (config, k);
5741 w = XWINDOW (p->window);
5742 /* Remember, we set w->config_mark on all currently visible
5743 windows, and reset it on all newly visible windows.
5744 Any windows still marked need to be deleted. */
5747 mark_window_as_deleted (w);
5752 /* We just potentially changed the window's buffer and
5753 potentially turned a dead window into a live one,
5754 so we need to recompute the cached specifier values. */
5755 recompute_all_cached_specifiers_in_window (w);
5760 /* Now restore things, when everything else if OK. */
5762 unbind_to (specpdl_count, Qnil);
5769 /* Mark all subwindows of a window as deleted. The argument
5770 W is actually the subwindow tree of the window in question. */
5773 delete_all_subwindows (struct window *w)
5775 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5776 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5777 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5779 mark_window_as_deleted (w);
5784 count_windows (struct window *window)
5787 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5788 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5789 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5793 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5796 for (j = 0; j < lim; j++)
5798 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5802 return 0; /* suppress compiler warning */
5806 save_window_save (Lisp_Object window, struct window_config *config, int i)
5810 for (; !NILP (window); window = w->next)
5812 struct saved_window *p = SAVED_WINDOW_N (config, i);
5814 w = XWINDOW (window);
5817 p->buffer = w->buffer;
5818 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5819 WINDOW_TOP (p) = WINDOW_TOP (w);
5820 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5821 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5822 p->hscroll = w->hscroll;
5823 p->modeline_hscroll = w->modeline_hscroll;
5825 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5826 #include "winslots.h"
5828 if (!NILP (w->buffer))
5830 /* Save w's value of point in the window configuration.
5831 If w is the selected window, then get the value of point
5832 from the buffer; pointm is garbage in the selected window. */
5833 if (EQ (window, Fselected_window (Qnil)))
5835 p->pointm = noseeum_make_marker ();
5836 Fset_marker (p->pointm,
5837 make_int (BUF_PT (XBUFFER (w->buffer))),
5841 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5843 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5844 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5845 p->start_at_line_beg = w->start_at_line_beg;
5847 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5855 p->start_at_line_beg = 0;
5858 if (NILP (w->parent))
5859 p->parent_index = -1;
5861 p->parent_index = saved_window_index (w->parent, config, i);
5865 p->prev_index = saved_window_index (w->prev, config, i);
5866 if (!NILP (w->vchild))
5867 i = save_window_save (w->vchild, config, i);
5868 if (!NILP (w->hchild))
5869 i = save_window_save (w->hchild, config, i);
5876 /* Added to doc string:
5878 This also records the currently selected frame, and FRAME's focus
5879 redirection (see `redirect-frame-focus').
5884 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5885 Return an object representing the current window configuration of FRAME.
5886 If FRAME is nil or omitted, use the selected frame.
5887 This describes the number of windows, their sizes and current buffers,
5888 and for each window on FRAME the displayed buffer, where display
5889 starts, and the positions of point and mark.
5890 An exception is made for point in the current buffer:
5891 its value is -not- saved.
5896 struct frame *f = decode_frame (frame);
5897 struct window_config *config;
5898 unsigned int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5900 int real_font_height;
5902 if (n_windows <= countof (Vwindow_configuration_free_list))
5903 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5904 (Vwindow_configuration_free_list
5907 /* More than ten windows; just allocate directly */
5908 config = (struct window_config *)
5909 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5910 &lrecord_window_configuration);
5911 XSETWINDOW_CONFIGURATION (result, config);
5913 config->frame_width = FRAME_WIDTH (f);
5914 config->frame_height = FRAME_HEIGHT (f); */
5915 /* #### When using `push-window-configuration', often the minibuffer ends
5916 up as the selected window because functions run as the result of
5917 user interaction e.g. hyper-apropos. It seems to me the sensible
5918 thing to do is not record the minibuffer here.
5920 #### Unfortunately this is a change to previous behaviour, however logical
5921 it may be, so revert for the moment. */
5923 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5924 config->current_window = FRAME_SELECTED_WINDOW (f);
5926 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5928 config->current_window = FRAME_SELECTED_WINDOW (f);
5929 XSETBUFFER (config->current_buffer, current_buffer);
5930 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5931 config->root_window = FRAME_ROOT_WINDOW (f);
5932 config->min_height = window_min_height;
5933 config->min_width = window_min_width;
5934 config->saved_windows_count = n_windows;
5935 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5937 /* save the minibuffer height using the heuristics from
5938 change_frame_size_1 */
5940 XSETFRAME (frame, f); /* frame could have been nil ! */
5941 default_face_height_and_width (frame, &real_font_height, 0);
5942 assert(real_font_height > 0);
5944 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5945 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5948 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5949 - (minibuf_height / real_font_height ) : /* lines */
5950 minibuf_height; /* pixels */
5956 save_window_excursion_unwind (Lisp_Object window_config)
5958 Lisp_Object val = Fset_window_configuration (window_config);
5959 free_window_configuration (window_config);
5963 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5964 Execute body, preserving window sizes and contents.
5965 Restores which buffer appears in which window, where display starts,
5966 as well as the current buffer.
5967 Does not restore the value of point in current buffer.
5971 /* This function can GC */
5973 int speccount = specpdl_depth ();
5975 record_unwind_protect (save_window_excursion_unwind,
5976 Fcurrent_window_configuration (Qnil));
5977 val = Fprogn (args);
5978 return unbind_to (speccount, val);
5981 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5982 Return the horizontal pixel position of POS in window.
5983 Beginning of line is column 0. This is calculated using the redisplay
5984 display tables. If WINDOW is nil, the current window is assumed.
5985 If POS is nil, point is assumed. Note that POS must be visible for
5986 a non-nil result to be returned.
5990 struct window* w = decode_window (window);
5991 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5993 struct display_line *dl = 0;
5994 struct display_block *db = 0;
5995 struct rune* rb = 0;
5996 int y = w->last_point_y[CURRENT_DISP];
5997 int x = w->last_point_x[CURRENT_DISP];
5999 if (MINI_WINDOW_P (w))
6002 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
6008 pos = Fwindow_point (window);
6013 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
6018 for (i = first_line; i < Dynarr_length (dla); i++)
6020 dl = Dynarr_atp (dla, i);
6021 /* find the vertical location first */
6022 if (point >= dl->bufpos && point <= dl->end_bufpos)
6024 db = get_display_block_from_line (dl, TEXT);
6025 for (i = 0; i < Dynarr_length (db->runes); i++)
6027 rb = Dynarr_atp (db->runes, i);
6028 if (point <= rb->bufpos)
6040 /* optimized case */
6041 dl = Dynarr_atp (dla, y);
6042 db = get_display_block_from_line (dl, TEXT);
6044 if (x >= Dynarr_length (db->runes))
6047 rb = Dynarr_atp (db->runes, x);
6050 return make_int (rb->xpos - WINDOW_LEFT (w));
6055 /* This is short and simple in elisp, but... it was written to debug
6056 problems purely on the C side. That is where we need to call it so
6059 debug_print_window (Lisp_Object window, int level)
6062 Lisp_Object child = Fwindow_first_vchild (window);
6065 child = Fwindow_first_hchild (window);
6067 for (i = level; i > 0; i--)
6070 stderr_out ("#<window");
6072 Lisp_Object buffer = XWINDOW (window)->buffer;
6073 if (!NILP (buffer) && BUFFERP (buffer))
6074 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
6076 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
6078 while (!NILP (child))
6080 debug_print_window (child, level + 1);
6081 child = Fwindow_next_child (child);
6085 void debug_print_windows (struct frame *f);
6087 debug_print_windows (struct frame *f)
6089 debug_print_window (f->root_window, 0);
6090 putc ('\n', stderr);
6092 #endif /* DEBUG_XEMACS */
6095 /************************************************************************/
6096 /* initialization */
6097 /************************************************************************/
6100 syms_of_window (void)
6102 INIT_LRECORD_IMPLEMENTATION (window);
6103 INIT_LRECORD_IMPLEMENTATION (window_configuration);
6105 defsymbol (&Qwindowp, "windowp");
6106 defsymbol (&Qwindow_live_p, "window-live-p");
6107 defsymbol (&Qwindow_configurationp, "window-configuration-p");
6108 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6109 defsymbol (&Qdisplay_buffer, "display-buffer");
6111 #ifdef MEMORY_USAGE_STATS
6112 defsymbol (&Qface_cache, "face-cache");
6113 defsymbol (&Qglyph_cache, "glyph-cache");
6114 defsymbol (&Qline_start_cache, "line-start-cache");
6115 #ifdef HAVE_SCROLLBARS
6116 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
6118 defsymbol (&Qother_redisplay, "other-redisplay");
6119 /* Qother in general.c */
6122 DEFSYMBOL (Qtruncate_partial_width_windows);
6124 DEFSUBR (Fselected_window);
6125 DEFSUBR (Flast_nonminibuf_window);
6126 DEFSUBR (Fminibuffer_window);
6127 DEFSUBR (Fwindow_minibuffer_p);
6129 DEFSUBR (Fwindow_live_p);
6130 DEFSUBR (Fwindow_first_hchild);
6131 DEFSUBR (Fwindow_first_vchild);
6132 DEFSUBR (Fwindow_next_child);
6133 DEFSUBR (Fwindow_previous_child);
6134 DEFSUBR (Fwindow_parent);
6135 DEFSUBR (Fwindow_lowest_p);
6136 DEFSUBR (Fwindow_truncated_p);
6137 DEFSUBR (Fwindow_highest_p);
6138 DEFSUBR (Fwindow_leftmost_p);
6139 DEFSUBR (Fwindow_rightmost_p);
6140 DEFSUBR (Fpos_visible_in_window_p);
6141 DEFSUBR (Fwindow_buffer);
6142 DEFSUBR (Fwindow_frame);
6143 DEFSUBR (Fwindow_height);
6144 DEFSUBR (Fwindow_displayed_height);
6145 DEFSUBR (Fwindow_width);
6146 DEFSUBR (Fwindow_full_width);
6147 DEFSUBR (Fwindow_pixel_height);
6148 DEFSUBR (Fwindow_pixel_width);
6149 DEFSUBR (Fwindow_text_area_height);
6150 DEFSUBR (Fwindow_text_area_pixel_height);
6151 DEFSUBR (Fwindow_displayed_text_pixel_height);
6152 DEFSUBR (Fwindow_text_area_pixel_width);
6153 DEFSUBR (Fwindow_hscroll);
6154 DEFSUBR (Fset_window_hscroll);
6155 DEFSUBR (Fmodeline_hscroll);
6156 DEFSUBR (Fset_modeline_hscroll);
6157 #if 0 /* bogus FSF crock */
6158 DEFSUBR (Fwindow_redisplay_end_trigger);
6159 DEFSUBR (Fset_window_redisplay_end_trigger);
6161 DEFSUBR (Fwindow_pixel_edges);
6162 DEFSUBR (Fwindow_text_area_pixel_edges);
6163 DEFSUBR (Fwindow_point);
6164 DEFSUBR (Fwindow_start);
6165 DEFSUBR (Fwindow_end);
6166 DEFSUBR (Fwindow_last_line_visible_height);
6167 DEFSUBR (Fset_window_point);
6168 DEFSUBR (Fset_window_start);
6169 DEFSUBR (Fwindow_dedicated_p);
6170 DEFSUBR (Fset_window_dedicated_p);
6171 DEFSUBR (Fnext_window);
6172 DEFSUBR (Fprevious_window);
6173 DEFSUBR (Fnext_vertical_window);
6174 DEFSUBR (Fother_window);
6175 DEFSUBR (Fget_lru_window);
6176 DEFSUBR (Fget_largest_window);
6177 DEFSUBR (Fget_buffer_window);
6178 DEFSUBR (Fwindow_left_margin_pixel_width);
6179 DEFSUBR (Fwindow_right_margin_pixel_width);
6180 DEFSUBR (Fdelete_other_windows);
6181 DEFSUBR (Fdelete_windows_on);
6182 DEFSUBR (Freplace_buffer_in_windows);
6183 DEFSUBR (Fdelete_window);
6184 DEFSUBR (Fset_window_buffer);
6185 DEFSUBR (Fselect_window);
6186 DEFSUBR (Fsplit_window);
6187 DEFSUBR (Fenlarge_window);
6188 DEFSUBR (Fenlarge_window_pixels);
6189 DEFSUBR (Fshrink_window);
6190 DEFSUBR (Fshrink_window_pixels);
6191 DEFSUBR (Fscroll_up);
6192 DEFSUBR (Fscroll_down);
6193 DEFSUBR (Fscroll_left);
6194 DEFSUBR (Fscroll_right);
6195 DEFSUBR (Fother_window_for_scrolling);
6196 DEFSUBR (Fscroll_other_window);
6197 DEFSUBR (Fcenter_to_window_line);
6198 DEFSUBR (Fmove_to_window_line);
6199 #ifdef MEMORY_USAGE_STATS
6200 DEFSUBR (Fwindow_memory_usage);
6202 DEFSUBR (Fwindow_configuration_p);
6203 DEFSUBR (Fset_window_configuration);
6204 DEFSUBR (Fcurrent_window_configuration);
6205 DEFSUBR (Fsave_window_excursion);
6206 DEFSUBR (Fcurrent_pixel_column);
6210 reinit_vars_of_window (void)
6213 /* Make sure all windows get marked */
6214 minibuf_window = Qnil;
6215 staticpro_nodump (&minibuf_window);
6217 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6219 Vwindow_configuration_free_list[i] =
6220 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6221 &lrecord_window_configuration);
6222 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6227 vars_of_window (void)
6229 reinit_vars_of_window ();
6231 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6232 *Non-nil means to scroll if point lands on a line which is clipped.
6234 scroll_on_clipped_lines = 1;
6236 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6237 See `temp-buffer-show-function'.
6239 Vtemp_buffer_show_hook = Qnil;
6241 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6242 Non-nil means call as function to display a help buffer.
6243 The function is called with one argument, the buffer to be displayed.
6244 Used by `with-output-to-temp-buffer'.
6245 If this function is used, then it must do the entire job of showing
6246 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6247 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6249 Vtemp_buffer_show_function = Qnil;
6251 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6252 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6254 Vminibuffer_scroll_window = Qnil;
6256 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6257 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6259 Vother_window_scroll_buffer = Qnil;
6261 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6262 *Number of pixels to scroll by per requested line.
6263 If nil then normal line scrolling occurs regardless of line height.
6264 If t then scrolling is done in increments equal to the height of the default face.
6266 Vwindow_pixel_scroll_increment = Qt;
6268 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6269 *Number of lines of continuity when scrolling by screenfuls.
6271 next_screen_context_lines = 2;
6273 DEFVAR_INT ("window-min-height", &window_min_height /*
6274 *Delete any window less than this tall (including its modeline).
6276 window_min_height = 4;
6278 DEFVAR_INT ("window-min-width", &window_min_width /*
6279 *Delete any window less than this wide.
6281 window_min_width = 10;
6285 specifier_vars_of_window (void)
6287 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6288 *How thick to draw 3D shadows around modelines.
6289 If this is set to 0, modelines will be the traditional 2D. Sizes above
6290 10 will be accepted but the maximum thickness that will be drawn is 10.
6291 This is a specifier; use `set-specifier' to change it.
6293 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6294 /* The initial value for modeline-shadow-thickness is 2, but if the
6295 user removes all specifications we provide a fallback value of 0,
6296 which is probably what was expected. */
6297 set_specifier_fallback (Vmodeline_shadow_thickness,
6298 list1 (Fcons (Qnil, Qzero)));
6299 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6301 set_specifier_caching (Vmodeline_shadow_thickness,
6302 offsetof (struct window, modeline_shadow_thickness),
6303 modeline_shadow_thickness_changed,
6306 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6307 *Whether the modeline should be displayed.
6308 This is a specifier; use `set-specifier' to change it.
6310 Vhas_modeline_p = Fmake_specifier (Qboolean);
6311 set_specifier_fallback (Vhas_modeline_p,
6312 list1 (Fcons (Qnil, Qt)));
6313 set_specifier_caching (Vhas_modeline_p,
6314 offsetof (struct window, has_modeline_p),
6315 /* #### It's strange that we need a special
6316 flag to indicate that the shadow-thickness
6317 has changed, but not one to indicate that
6318 the modeline has been turned off or on. */
6319 some_window_value_changed,
6322 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6323 &Vvertical_divider_always_visible_p /*
6324 *Should XEmacs always display vertical dividers between windows.
6326 When this is non-nil, vertical dividers are always shown, and are
6327 draggable. When it is nil, vertical dividers are shown only when
6328 there are no scrollbars in between windows, and are not draggable.
6330 This is a specifier; use `set-specifier' to change it.
6332 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6333 set_specifier_fallback (Vvertical_divider_always_visible_p,
6334 list1 (Fcons (Qnil, Qt)));
6335 set_specifier_caching (Vvertical_divider_always_visible_p,
6336 offsetof (struct window,
6337 vertical_divider_always_visible_p),
6338 vertical_divider_changed_in_window,
6341 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6342 *How thick to draw 3D shadows around vertical dividers.
6343 This is a specifier; use `set-specifier' to change it.
6345 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6346 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6347 list1 (Fcons (Qnil, Qzero)));
6348 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6350 set_specifier_caching (Vvertical_divider_shadow_thickness,
6351 offsetof (struct window,
6352 vertical_divider_shadow_thickness),
6353 vertical_divider_changed_in_window,
6355 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6356 *The width of the vertical dividers, not including shadows.
6358 For TTY windows, divider line is always one character wide. When
6359 instance of this specifier is zero in a TTY window, no divider is
6360 drawn at all between windows. When non-zero, a one character wide
6361 divider is displayed.
6363 This is a specifier; use `set-specifier' to change it.
6366 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6368 Lisp_Object fb = Qnil;
6370 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6373 fb = Fcons (Fcons (list1 (Qgtk), make_int (3)), fb);
6375 #ifdef HAVE_X_WINDOWS
6376 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6378 #ifdef HAVE_MS_WINDOWS
6379 /* #### This should be made magic and made to obey system settings */
6380 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6382 set_specifier_fallback (Vvertical_divider_line_width, fb);
6384 set_specifier_caching (Vvertical_divider_line_width,
6385 offsetof (struct window,
6386 vertical_divider_line_width),
6387 vertical_divider_changed_in_window,
6390 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6391 *How much space to leave around the vertical dividers.
6393 In TTY windows, spacing is always zero, and the value of this
6394 specifier is ignored.
6396 This is a specifier; use `set-specifier' to change it.
6398 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6400 Lisp_Object fb = Qnil;
6402 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6404 #ifdef HAVE_X_WINDOWS
6405 /* #### 3D dividers look great on MS Windows with spacing = 0.
6406 Should not the same value be the fallback under X? - kkm */
6407 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6410 fb = Fcons (Fcons (list1 (Qgtk), Qzero), fb);
6412 #ifdef HAVE_MS_WINDOWS
6413 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6415 set_specifier_fallback (Vvertical_divider_spacing, fb);
6417 set_specifier_caching (Vvertical_divider_spacing,
6418 offsetof (struct window, vertical_divider_spacing),
6419 vertical_divider_changed_in_window,