1 /* Window creation, deletion and examination for XEmacs.
2 Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1996 Chuck Thompson.
7 This file is part of XEmacs.
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
24 /* Synched up with: FSF 19.30. */
25 /* Beginning to diverge significantly. */
27 /* This file has been Mule-ized. */
37 #include "redisplay.h"
43 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
44 Lisp_Object Qdisplay_buffer;
46 #ifdef MEMORY_USAGE_STATS
47 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
48 #ifdef HAVE_SCROLLBARS
49 Lisp_Object Qscrollbar_instances;
53 EXFUN (Fnext_window, 4);
55 static int window_pixel_width_to_char_width (struct window *w,
57 int include_margins_p);
58 static int window_char_width_to_pixel_width (struct window *w,
60 int include_margins_p);
61 static int window_pixel_height_to_char_height (struct window *w,
63 int include_gutters_p);
64 static int window_char_height_to_pixel_height (struct window *w,
66 int include_gutters_p);
67 static void change_window_height (Lisp_Object window, int delta,
68 Lisp_Object horizontalp, int inpixels);
70 /* Thickness of shadow border around 3d modelines. */
71 Lisp_Object Vmodeline_shadow_thickness;
73 /* Whether vertical dividers are draggable and displayed */
74 Lisp_Object Vvertical_divider_always_visible_p;
76 /* Whether a modeline should be displayed. */
77 Lisp_Object Vhas_modeline_p;
79 /* Thickness of shadow border around vertical dividers. */
80 Lisp_Object Vvertical_divider_shadow_thickness;
82 /* Divider surface width (not counting 3-d borders) */
83 Lisp_Object Vvertical_divider_line_width;
85 /* Spacing between outer edge of divider border and window edge */
86 Lisp_Object Vvertical_divider_spacing;
88 /* How much to scroll by per-line. */
89 Lisp_Object Vwindow_pixel_scroll_increment;
91 /* Scroll if point lands on the bottom line and that line is partially
93 int scroll_on_clipped_lines;
95 /* The minibuffer window of the selected frame.
96 Note that you cannot test for minibufferness of an arbitrary window
97 by comparing against this; but you can test for minibufferness of
98 the selected window. */
99 Lisp_Object minibuf_window;
101 /* Non-nil means it is the window for C-M-v to scroll
102 when the minibuffer is selected. */
103 Lisp_Object Vminibuffer_scroll_window;
105 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
106 Lisp_Object Vother_window_scroll_buffer;
108 /* Non-nil means it's the function to call to display temp buffers. */
109 Lisp_Object Vtemp_buffer_show_function;
111 Lisp_Object Vtemp_buffer_show_hook;
113 /* If a window gets smaller than either of these, it is removed. */
114 Fixnum window_min_height;
115 Fixnum window_min_width;
117 /* Hook run at end of temp_output_buffer_show. */
118 Lisp_Object Qtemp_buffer_show_hook;
120 /* Number of lines of continuity in scrolling by screenfuls. */
121 Fixnum next_screen_context_lines;
123 /* List of freed window configurations with 1 - 10 windows. */
124 static Lisp_Object Vwindow_configuration_free_list[10];
126 Lisp_Object Qtruncate_partial_width_windows;
128 #define SET_LAST_MODIFIED(w, cache_too) \
130 (w)->last_modified[CURRENT_DISP] = Qzero; \
131 (w)->last_modified[DESIRED_DISP] = Qzero; \
132 (w)->last_modified[CMOTION_DISP] = Qzero; \
134 (w)->line_cache_last_updated = Qzero; \
137 #define SET_LAST_FACECHANGE(w) \
139 (w)->last_facechange[CURRENT_DISP] = Qzero; \
140 (w)->last_facechange[DESIRED_DISP] = Qzero; \
141 (w)->last_facechange[CMOTION_DISP] = Qzero; \
145 #define MARK_DISP_VARIABLE(field) \
146 mark_object (window->field[CURRENT_DISP]); \
147 mark_object (window->field[DESIRED_DISP]); \
148 mark_object (window->field[CMOTION_DISP]);
151 mark_window (Lisp_Object obj)
153 struct window *window = XWINDOW (obj);
154 mark_object (window->frame);
155 mark_object (window->mini_p);
156 mark_object (window->next);
157 mark_object (window->prev);
158 mark_object (window->hchild);
159 mark_object (window->vchild);
160 mark_object (window->parent);
161 mark_object (window->buffer);
162 MARK_DISP_VARIABLE (start);
163 MARK_DISP_VARIABLE (pointm);
164 mark_object (window->sb_point); /* #### move to scrollbar.c? */
165 mark_object (window->use_time);
166 MARK_DISP_VARIABLE (last_modified);
167 MARK_DISP_VARIABLE (last_point);
168 MARK_DISP_VARIABLE (last_start);
169 MARK_DISP_VARIABLE (last_facechange);
170 mark_object (window->line_cache_last_updated);
171 mark_object (window->redisplay_end_trigger);
172 mark_object (window->subwindow_instance_cache);
174 mark_face_cachels (window->face_cachels);
175 mark_glyph_cachels (window->glyph_cachels);
177 #define WINDOW_SLOT(slot, compare) mark_object (window->slot)
178 #include "winslots.h"
184 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
189 error ("printing unreadable object #<window 0x%x>",
190 XWINDOW (obj)->header.uid);
192 write_c_string ("#<window", printcharfun);
193 if (!NILP (XWINDOW (obj)->buffer))
195 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
196 write_c_string (" on ", printcharfun);
197 print_internal (name, printcharfun, 1);
199 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
200 write_c_string (buf, printcharfun);
204 finalize_window (void *header, int for_disksave)
206 struct window *w = (struct window *) header;
208 if (w->line_start_cache)
210 Dynarr_free (w->line_start_cache);
211 w->line_start_cache = 0;
218 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
220 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
221 if (cachel->merged_faces)
223 Dynarr_free (cachel->merged_faces);
224 cachel->merged_faces = 0;
227 Dynarr_free (w->face_cachels);
231 if (w->glyph_cachels)
233 Dynarr_free (w->glyph_cachels);
234 w->glyph_cachels = 0;
238 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
239 mark_window, print_window, finalize_window,
240 0, 0, 0, struct window);
243 #define INIT_DISP_VARIABLE(field, initialization) \
244 p->field[CURRENT_DISP] = initialization; \
245 p->field[DESIRED_DISP] = initialization; \
246 p->field[CMOTION_DISP] = initialization;
248 /* We have an implicit assertion that the first two elements (default
249 and modeline faces) are always present in the face_element_cache.
250 Normally redisplay ensures this. However, it is possible for a
251 window to get created and functions which reference these values
252 called before redisplay works with the window for the first time.
253 All callers of allocate_window should therefore call
254 reset_face_cachels on the created window. We can't do it
255 here because the window must have its frame pointer set or
256 reset_face_cachels will fail. */
258 allocate_window (void)
261 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
275 INIT_DISP_VARIABLE (start, Fmake_marker ());
276 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
277 p->sb_point = Fmake_marker ();
279 INIT_DISP_VARIABLE (last_modified, Qzero);
280 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
281 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
282 INIT_DISP_VARIABLE (last_facechange, Qzero);
283 p->face_cachels = Dynarr_new (face_cachel);
284 p->glyph_cachels = Dynarr_new (glyph_cachel);
285 p->line_start_cache = Dynarr_new (line_start_cache);
286 p->subwindow_instance_cache = make_image_instance_cache_hash_table ();
288 p->line_cache_last_updated = Qzero;
289 INIT_DISP_VARIABLE (last_point_x, 0);
290 INIT_DISP_VARIABLE (last_point_y, 0);
291 INIT_DISP_VARIABLE (window_end_pos, 0);
292 p->redisplay_end_trigger = Qnil;
294 p->gutter_extent_modiff[0] = 0;
295 p->gutter_extent_modiff[1] = 0;
296 p->gutter_extent_modiff[2] = 0;
297 p->gutter_extent_modiff[3] = 0;
299 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
300 #include "winslots.h"
302 p->windows_changed = 1;
303 p->shadow_thickness_changed = 1;
307 #undef INIT_DISP_VARIABLE
310 * The redisplay structures used to be stored with each window. While
311 * they are logically something associated with frames they can't be
312 * stored there with a redisplay which handles variable height lines.
313 * Lines in horizontally split windows might not line up. So they get
314 * stored with the windows.
316 * The problem with this is window configurations. When restoring a
317 * window configuration it now becomes problematic to do an
318 * incremental redisplay. The solution is to store the redisplay
319 * structures with the frame as they should be but laid out in the
320 * same manner as the window structure. Thus is born the window
323 * It also becomes a convenient place to stick scrollbar instances
324 * since they extrapolate out to having the same problem described for
325 * the display structures.
328 /* Create a new window mirror structure and associated redisplay
330 static struct window_mirror *
331 new_window_mirror (struct frame *f)
333 struct window_mirror *t = xnew_and_zero (struct window_mirror);
337 t->current_display_lines = Dynarr_new (display_line);
338 t->desired_display_lines = Dynarr_new (display_line);
341 #ifdef HAVE_SCROLLBARS
342 t->scrollbar_vertical_instance = NULL;
343 t->scrollbar_horizontal_instance = NULL;
349 /* Synchronize the mirror structure with a given window structure.
350 This is normally called from update_frame_window_mirror with a
351 starting window of f->root_window. */
352 static struct window_mirror *
353 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
359 free_window_mirror (mir);
366 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
368 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
369 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
370 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
373 * If the redisplay structs are not empty and the mirror has
374 * children, then this mirror structure was formerly being used for
375 * display but is no longer. Reset its current display structs so
376 * that redisplay doesn't accidentally think they are accurate if it
377 * is later used for display purposes once again. Also, mark the
378 * scrollbar instance as not active.
380 if (mir->vchild || mir->hchild)
382 /* The redisplay structures are big. Leaving them around in
383 non-leaf windows can add up to a lot of wasted space. So
385 free_display_structs (mir);
386 mir->current_display_lines = Dynarr_new (display_line);
387 mir->desired_display_lines = Dynarr_new (display_line);
389 #ifdef HAVE_SCROLLBARS
390 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
398 /* Given a window mirror, determine which real window it contains the
399 redisplay structures for. */
401 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
402 struct window_mirror *mir)
404 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
408 if (!NILP (XWINDOW (win)->vchild))
411 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
415 if (!NILP (XWINDOW (win)->hchild))
418 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
427 /* Given a real window, find the mirror structure which contains its
428 redisplay structures. */
429 static struct window_mirror *
430 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
433 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
435 if (w == XWINDOW (win))
438 if (!NILP (XWINDOW (win)->vchild))
440 struct window_mirror *retval =
441 find_window_mirror_internal (XWINDOW (win)->vchild,
443 if (retval) return retval;
446 if (!NILP (XWINDOW (win)->hchild))
448 struct window_mirror *retval =
449 find_window_mirror_internal (XWINDOW (win)->hchild,
451 if (retval) return retval;
458 /* Update the mirror structure for the given frame. */
460 update_frame_window_mirror (struct frame *f)
462 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
466 /* Free a given mirror structure along with all of its children as
467 well as their associated display structures. */
469 free_window_mirror (struct window_mirror *mir)
473 struct window_mirror *prev = mir;
474 if (mir->hchild) free_window_mirror (mir->hchild);
475 if (mir->vchild) free_window_mirror (mir->vchild);
476 #ifdef HAVE_SCROLLBARS
477 release_window_mirror_scrollbars (mir);
479 free_display_structs (mir);
485 /* Given a mirror structure, return the window it mirrors. Calls
486 real_window_internal to do most of the work. */
488 real_window (struct window_mirror *mir, int no_abort)
490 Lisp_Object retval = real_window_internal (mir->frame->root_window,
491 mir->frame->root_mirror, mir);
492 if (NILP (retval) && !no_abort)
498 /* Given a real window, return its mirror structure. Calls
499 find_window_mirror_internal to do all of the work. */
500 struct window_mirror *
501 find_window_mirror (struct window *w)
503 struct frame *f = XFRAME (w->frame);
505 update_frame_window_mirror (f);
506 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
509 /*****************************************************************************
510 find_window_by_pixel_pos
512 Given a pixel position relative to a frame, find the window at that
514 ****************************************************************************/
516 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
521 for (; !NILP (win); win = XWINDOW (win)->next)
525 if (!NILP (XWINDOW (win)->vchild))
527 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
530 if (!NILP (XWINDOW (win)->hchild))
532 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
536 if (pix_x >= WINDOW_LEFT (w)
537 && pix_x <= WINDOW_RIGHT (w)
538 && pix_y >= WINDOW_TOP (w)
539 && pix_y <= WINDOW_BOTTOM (w))
545 /* Return a pointer to the display structures for the given window. */
546 display_line_dynarr *
547 window_display_lines (struct window *w, int which)
549 struct window_mirror *t;
551 if (XFRAME (w->frame)->mirror_dirty)
552 update_frame_window_mirror (XFRAME (w->frame));
553 t = find_window_mirror (w);
557 if (which == CURRENT_DISP)
558 return t->current_display_lines;
559 else if (which == DESIRED_DISP)
560 return t->desired_display_lines;
561 else if (which == CMOTION_DISP)
562 /* The CMOTION_DISP display lines are global. */
563 return cmotion_display_lines;
567 return 0; /* shut up compiler */
571 window_display_buffer (struct window *w)
573 struct window_mirror *t;
575 if (XFRAME (w->frame)->mirror_dirty)
576 update_frame_window_mirror (XFRAME (w->frame));
577 t = find_window_mirror (w);
585 set_window_display_buffer (struct window *w, struct buffer *b)
587 struct window_mirror *t;
589 if (XFRAME (w->frame)->mirror_dirty)
590 update_frame_window_mirror (XFRAME (w->frame));
591 t = find_window_mirror (w);
599 /* Determining a window's position based solely on its pixel
600 positioning doesn't work. Instead, we do it the intelligent way,
601 by checking its positioning in the window hierarchy. */
603 window_is_leftmost (struct window *w)
605 Lisp_Object parent, current_ancestor, window;
607 XSETWINDOW (window, w);
609 parent = XWINDOW (window)->parent;
610 current_ancestor = window;
612 while (!NILP (parent))
614 if (!NILP (XWINDOW (parent)->hchild) &&
615 !EQ (XWINDOW (parent)->hchild, current_ancestor))
618 current_ancestor = parent;
619 parent = XWINDOW (parent)->parent;
626 window_is_rightmost (struct window *w)
628 Lisp_Object parent, current_ancestor, window;
630 XSETWINDOW (window, w);
632 parent = XWINDOW (window)->parent;
633 current_ancestor = window;
635 while (!NILP (parent))
637 if (!NILP (XWINDOW (parent)->hchild)
638 && !NILP (XWINDOW (current_ancestor)->next))
641 current_ancestor = parent;
642 parent = XWINDOW (parent)->parent;
649 window_full_width_p (struct window *w)
651 return window_is_leftmost (w) && window_is_rightmost (w);
655 window_is_highest (struct window *w)
657 Lisp_Object parent, current_ancestor, window;
659 XSETWINDOW (window, w);
661 parent = XWINDOW (window)->parent;
662 current_ancestor = window;
664 while (!NILP (parent))
666 if (!NILP (XWINDOW (parent)->vchild) &&
667 !EQ (XWINDOW (parent)->vchild, current_ancestor))
670 current_ancestor = parent;
671 parent = XWINDOW (parent)->parent;
674 /* This is really to catch the minibuffer but we make it generic in
675 case we ever change things around to let the minibuffer be on top. */
676 if (NILP (XWINDOW (current_ancestor)->prev))
683 window_is_lowest (struct window *w)
685 Lisp_Object parent, current_ancestor, window;
687 XSETWINDOW (window, w);
689 parent = XWINDOW (window)->parent;
690 current_ancestor = window;
692 while (!NILP (parent))
694 if (!NILP (XWINDOW (parent)->vchild)
695 && !NILP (XWINDOW (current_ancestor)->next))
698 current_ancestor = parent;
699 parent = XWINDOW (parent)->parent;
705 #if 0 /* not currently used */
708 window_full_height_p (struct window *w)
710 return window_is_highest (w) && window_is_lowest (w);
716 window_truncation_on (struct window *w)
718 /* Minibuffer windows are never truncated.
719 #### is this the right way ? */
720 if (MINI_WINDOW_P (w))
723 /* Horizontally scrolled windows are truncated. */
727 /* If truncate_partial_width_windows is true and the window is not
728 the full width of the frame it is truncated. */
729 if (!NILP (symbol_value_in_buffer (Qtruncate_partial_width_windows,
731 && !(window_is_leftmost (w) && window_is_rightmost (w)))
734 /* If the window's buffer's value of truncate_lines is non-nil, then
735 the window is truncated. */
736 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
742 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
743 Returns non-nil if text in the window is truncated.
747 struct window *w = decode_window (window);
749 return window_truncation_on (w) ? Qt : Qnil;
754 have_undivided_common_edge (struct window *w_right, void *closure)
756 struct window *w_left = (struct window *) closure;
757 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
758 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
759 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
760 #ifdef HAVE_SCROLLBARS
761 && (NILP (w_right->scrollbar_on_left_p)
762 || NILP (w_right->vertical_scrollbar_visible_p)
763 || ZEROP (w_right->scrollbar_width))
769 window_needs_vertical_divider_1 (struct window *w)
771 /* Never if we're on the right */
772 if (window_is_rightmost (w))
775 /* Always if draggable */
776 if (!NILP (w->vertical_divider_always_visible_p))
779 #ifdef HAVE_SCROLLBARS
780 /* Our right scrollbar is enough to separate us at the right */
781 if (NILP (w->scrollbar_on_left_p)
782 && !NILP (w->vertical_scrollbar_visible_p)
783 && !ZEROP (w->scrollbar_width))
787 /* Ok. to determine whether we need a divider on the left, we must
788 check that our right neighbor windows have scrollbars on their
789 left sides. We must check all such windows which have common
790 left edge with our window's right edge. */
791 return map_windows (XFRAME (WINDOW_FRAME (w)),
792 have_undivided_common_edge, (void*)w);
796 window_needs_vertical_divider (struct window *w)
798 if (!w->need_vertical_divider_valid_p)
800 w->need_vertical_divider_p =
801 window_needs_vertical_divider_1 (w);
802 w->need_vertical_divider_valid_p = 1;
804 return w->need_vertical_divider_p;
807 /* Called from invalidate_vertical_divider_cache_in_frame */
809 invalidate_vertical_divider_cache_in_window (struct window *w,
812 w->need_vertical_divider_valid_p = 0;
816 /* Calculate width of vertical divider, including its shadows
817 and spacing. The returned value is effectively the distance
818 between adjacent window edges. This function does not check
819 whether a window needs a vertical divider, so the returned
820 value is a "theoretical" one */
822 window_divider_width (struct window *w)
824 /* the shadow thickness can be negative. This means that the divider
825 will have a depressed look */
827 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
829 XINT (w->vertical_divider_line_width)
830 + 2 * XINT (w->vertical_divider_spacing)
831 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
833 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
837 window_scrollbar_width (struct window *w)
839 #ifdef HAVE_SCROLLBARS
840 if (!WINDOW_WIN_P (w)
843 || NILP (w->vertical_scrollbar_visible_p))
844 /* #### when does NILP (w->buffer) happen? */
847 return XINT (w->scrollbar_width);
850 #endif /* HAVE_SCROLLBARS */
853 /* Horizontal scrollbars are only active on windows with truncation
856 window_scrollbar_height (struct window *w)
858 #ifdef HAVE_SCROLLBARS
859 if (!WINDOW_WIN_P (w)
862 || NILP (w->horizontal_scrollbar_visible_p)
863 || !window_truncation_on (w))
866 return XINT (w->scrollbar_height);
869 #endif /* HAVE_SCROLLBARS */
873 window_modeline_height (struct window *w)
875 struct frame *f = XFRAME (w->frame);
878 if (MINI_WINDOW_P (w) || NILP (w->buffer))
882 else if (!WINDOW_HAS_MODELINE_P (w))
884 if (window_scrollbar_height (w))
888 modeline_height = FRAMEMETH (f, divider_height, ());
890 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
891 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
900 display_line_dynarr *dla;
902 /* We don't force a regeneration of the modeline here.
903 Instead it is now a precondition that any function calling
904 this should make sure that one of these structures is
905 up-to-date. In practice this only affects two internal
906 redisplay functions, regenerate_window and
907 regenerate_window_point_center. */
908 /* We check DESIRED_DISP because if it is valid it is more
909 up-to-date than CURRENT_DISP. For calls to this outside
910 of redisplay it doesn't matter which structure we check
911 since there is a redisplay condition that these
912 structures be identical outside of redisplay. */
913 dla = window_display_lines (w, DESIRED_DISP);
914 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
915 modeline_height = (Dynarr_atp (dla, 0)->ascent +
916 Dynarr_atp (dla, 0)->descent);
919 dla = window_display_lines (w, CURRENT_DISP);
920 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
921 modeline_height = (Dynarr_atp (dla, 0)->ascent +
922 Dynarr_atp (dla, 0)->descent);
924 /* This should be an abort except I'm not yet 100%
925 confident that it won't ever get hit (though I
926 haven't been able to trigger it). It is extremely
927 unlikely to cause any noticeable problem and even if
928 it does it will be a minor display glitch. */
929 /* #### Bullshit alert. It does get hit and it causes
930 noticeable glitches. real_current_modeline_height
931 is a kludge to fix this for 19.14. */
932 modeline_height = real_current_modeline_height (w);
935 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
936 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
940 return modeline_height;
943 /*****************************************************************************
944 margin_width_internal
946 For a given window, return the width in pixels of the specified margin.
947 ****************************************************************************/
949 margin_width_internal (struct window *w, int left_margin)
952 int window_cwidth = window_char_width (w, 1);
957 /* We might be getting called on a non-leaf. */
958 if (NILP (w->buffer))
961 /* The minibuffer never has margins. */
962 if (MINI_WINDOW_P (w))
965 XSETWINDOW (window, w);
966 b = XBUFFER (w->buffer);
967 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
968 XINT (w->right_margin_width));
970 default_face_height_and_width (window, 0, &font_width);
972 /* The left margin takes precedence over the right margin so we
973 subtract its width from the space available for the right
976 window_cwidth -= XINT (w->left_margin_width);
978 /* The margin cannot be wider than the window is. We allow the
979 value to be bigger since it is possible for the user to enlarge
980 the window such that the left margin value would no longer be too
981 big, but we won't return a value that is larger. */
982 if (margin_cwidth > window_cwidth)
983 margin_cwidth = window_cwidth;
985 /* At the user level the margin is always specified in characters.
986 Internally however it is manipulated in terms of pixels. */
987 return margin_cwidth * font_width;
991 window_left_margin_width (struct window *w)
993 return margin_width_internal (w, 1);
997 window_right_margin_width (struct window *w)
999 return margin_width_internal (w, 0);
1002 /*****************************************************************************
1005 The gutters of a window are those areas in the boundary defined by
1006 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1007 do not contain text. Items which may be in the gutters include
1008 scrollbars, toolbars and modelines. The margin areas are not
1009 included. This is an exception made because redisplay special cases
1010 the handling of those areas in many places in such a way that
1011 including them in the gutter area would make life difficult.
1013 The size functions refer to height for the bottom and top gutters and
1014 width for the left and right gutters. The starting position
1015 functions refer to the Y coord for bottom and top gutters and the X
1016 coord for left and right gutters. All starting positions are
1017 relative to the frame, not the window.
1018 ****************************************************************************/
1021 window_top_window_gutter_height (struct window *w)
1023 if (!NILP (w->hchild) || !NILP (w->vchild))
1026 #ifdef HAVE_SCROLLBARS
1027 if (!NILP (w->scrollbar_on_top_p))
1028 return window_scrollbar_height (w);
1035 window_top_gutter_height (struct window *w)
1037 return window_top_window_gutter_height (w);
1041 window_bottom_window_gutter_height (struct window *w)
1045 if (!NILP (w->hchild) || !NILP (w->vchild))
1048 gutter = window_modeline_height (w);
1050 #ifdef HAVE_SCROLLBARS
1051 if (NILP (w->scrollbar_on_top_p))
1052 return window_scrollbar_height (w) + gutter;
1059 window_bottom_gutter_height (struct window *w)
1061 return window_bottom_window_gutter_height (w);
1065 window_left_window_gutter_width (struct window *w, int modeline)
1067 if (!NILP (w->hchild) || !NILP (w->vchild))
1070 #ifdef HAVE_SCROLLBARS
1071 if (!modeline && !NILP (w->scrollbar_on_left_p))
1072 return window_scrollbar_width (w);
1079 window_left_gutter_width (struct window *w, int modeline)
1081 return window_left_window_gutter_width (w, modeline);
1085 window_right_window_gutter_width (struct window *w, int modeline)
1089 if (!NILP (w->hchild) || !NILP (w->vchild))
1092 #ifdef HAVE_SCROLLBARS
1093 if (!modeline && NILP (w->scrollbar_on_left_p))
1094 gutter += window_scrollbar_width (w);
1097 if (window_needs_vertical_divider (w))
1098 gutter += window_divider_width (w);
1104 window_right_gutter_width (struct window *w, int modeline)
1106 return window_right_window_gutter_width (w, modeline);
1110 window_pixel_height (struct window* w)
1112 return WINDOW_HEIGHT (w);
1116 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1117 Return t if OBJECT is a window.
1121 return WINDOWP (object) ? Qt : Qnil;
1124 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1125 Return t if OBJECT is a window which is currently visible.
1129 return WINDOWP (object) && WINDOW_LIVE_P (XWINDOW (object))
1133 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1134 Return the window that the cursor now appears in and commands apply to.
1135 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1136 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1137 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1138 is a console, the selected frame on that console's selected device will
1139 be used. Otherwise, the selected frame is used.
1143 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1144 return Qnil; /* happens at startup */
1147 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1148 return FRAME_SELECTED_WINDOW (f);
1152 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1153 Return the last selected window that is not a minibuffer window.
1154 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1155 return the last non-minibuffer window used by that frame. If
1156 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1157 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1158 that console's selected device will be used. Otherwise, the selected
1163 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1164 return Qnil; /* happens at startup */
1167 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1168 return FRAME_LAST_NONMINIBUF_WINDOW (f);
1172 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1173 Return the window used now for minibuffers.
1174 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1175 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1176 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1177 is a console, the selected frame on that console's selected device will
1178 be used. Otherwise, the selected frame is used.
1182 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1185 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1186 Return non-nil if WINDOW is a minibuffer window.
1190 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1193 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1194 Return the first horizontal child of WINDOW, or nil.
1198 return decode_window (window)->hchild;
1201 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1202 Return the first vertical child of WINDOW, or nil.
1206 return decode_window (window)->vchild;
1209 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1210 Return the next window on the same level as WINDOW, or nil.
1214 return decode_window (window)->next;
1217 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1218 Return the previous window on the same level as WINDOW, or nil.
1222 return decode_window (window)->prev;
1225 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1226 Return the parent of WINDOW, or nil.
1230 return decode_window (window)->parent;
1233 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1234 Return non-nil if WINDOW is along the bottom of its frame.
1238 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1241 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1242 Return non-nil if WINDOW is along the top of its frame.
1246 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1249 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1250 Return non-nil if WINDOW is along the left edge of its frame.
1254 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1257 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1258 Return non-nil if WINDOW is along the right edge of its frame.
1262 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1265 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1266 Return t if position POS is currently on the frame in WINDOW.
1267 Returns nil if that position is scrolled vertically out of view.
1268 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1272 struct window *w = decode_window (window);
1273 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1275 struct buffer *buf = XBUFFER (w->buffer);
1278 posint = BUF_PT (buf);
1281 CHECK_INT_COERCE_MARKER (pos);
1282 posint = XINT (pos);
1285 if (posint < top || posint > BUF_ZV (buf))
1288 /* w->start can be out of range. If it is, do something reasonable. */
1289 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1292 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1297 decode_window (Lisp_Object window)
1300 return XWINDOW (Fselected_window (Qnil));
1302 CHECK_LIVE_WINDOW (window);
1303 return XWINDOW (window);
1306 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1307 Return the buffer that WINDOW is displaying.
1311 return decode_window (window)->buffer;
1314 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1315 Return the frame that window WINDOW is on.
1319 return decode_window (window)->frame;
1322 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1323 Return the number of default lines in WINDOW.
1324 This actually works by dividing the window's pixel height (including
1325 the modeline and horizontal scrollbar, if any) by the height of the
1326 default font; therefore, the number of displayed lines will probably
1328 Use `window-height' to get consistent results in geometry calculations.
1329 Use `window-displayed-height' to get the actual number of lines
1330 currently displayed in a window.
1332 The names are somewhat confusing; here's a table to help out:
1335 -------------------------------------------------------------------------
1337 (rows/columns) window-width window-text-area-height
1338 (pixels) window-text-area-pixel-width window-text-area-pixel-height
1341 (rows/columns) window-full-width window-height
1342 (pixels) window-pixel-width window-pixel-height
1345 (rows/columns) ---- window-displayed-height
1346 (pixels) ---- window-displayed-text-pixel-height
1350 return make_int (window_char_height (decode_window (window), 1));
1353 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1354 Return the number of lines currently displayed in WINDOW.
1355 This counts the actual number of lines displayed in WINDOW
1356 \(as opposed to `window-height'). The modeline and horizontal
1357 scrollbar do not count as lines. If there is some blank space
1358 between the end of the buffer and the end of the window, this
1359 function pretends that there are lines of text in the default
1364 return make_int (window_displayed_height (decode_window (window)));
1367 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1368 Return the height of WINDOW in pixels. Defaults to current window.
1369 This includes the window's modeline and horizontal scrollbar (if any).
1373 return make_int (window_pixel_height (decode_window (window)));
1376 DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
1377 Return the number of default lines in the text area of WINDOW.
1378 This actually works by dividing the window's text area pixel height (i.e.
1379 excluding the modeline and horizontal scrollbar, if any) by the height of the
1380 default font; therefore, the number of displayed lines will probably
1382 See also `window-height' and `window-displayed-height'.
1386 return make_int (window_char_height (decode_window (window), 0));
1389 DEFUN ("window-text-area-pixel-height",
1390 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1391 Return the height in pixels of the text-displaying portion of WINDOW.
1392 Unlike `window-pixel-height', the space occupied by the modeline and
1393 horizontal scrollbar, if any, is not counted.
1397 struct window *w = decode_window (window);
1399 return make_int (WINDOW_TEXT_HEIGHT (w));
1402 DEFUN ("window-displayed-text-pixel-height",
1403 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1404 Return the height in pixels of the text displayed in WINDOW.
1405 Unlike `window-text-area-pixel-height', any blank space below the
1406 end of the buffer is not included. If optional argument NOCLIPPED
1407 is non-nil, do not include space occupied by clipped lines.
1409 (window, noclipped))
1412 Bufpos start, eobuf;
1414 int hlimit, height, prev_height = -1;
1418 line_start_cache_dynarr *cache;
1421 window = Fselected_window (Qnil);
1423 CHECK_LIVE_WINDOW (window);
1424 w = XWINDOW (window);
1426 start = marker_position (w->start[CURRENT_DISP]);
1427 hlimit = WINDOW_TEXT_HEIGHT (w);
1428 eobuf = BUF_ZV (XBUFFER (w->buffer));
1430 default_face_height_and_width (window, &defheight, NULL);
1432 /* guess lines needed in line start cache + a few extra */
1433 needed = (hlimit + defheight-1) / defheight + 3;
1436 elt = point_in_line_start_cache (w, start, needed);
1437 assert (elt >= 0); /* in the cache */
1439 cache = w->line_start_cache;
1440 nelt = Dynarr_length (cache);
1443 for (i = elt; i < nelt; i++) {
1444 line = Dynarr_atp (cache, i)->height;
1446 if (height + line > hlimit)
1447 return make_int (!NILP (noclipped) ? height : hlimit);
1451 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1452 return make_int (height);
1455 /* get here => need more cache lines. try again. */
1456 assert(height > prev_height); /* progress? */
1457 prev_height = height;
1459 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1462 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1465 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1466 Return the number of display columns in WINDOW.
1467 This is the width that is usable columns available for text in WINDOW,
1468 and does not include vertical scrollbars, dividers, or the like. See also
1469 `window-full-width' and `window-height'.
1473 return make_int (window_char_width (decode_window (window), 0));
1476 DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /*
1477 Return the total number of columns in WINDOW.
1478 This is like `window-width' but includes vertical scrollbars, dividers,
1483 return make_int (window_char_width (decode_window (window), 1));
1486 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1487 Return the width of WINDOW in pixels. Defaults to current window.
1491 return make_int (decode_window (window)->pixel_width);
1494 DEFUN ("window-text-area-pixel-width",
1495 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1496 Return the width in pixels of the text-displaying portion of WINDOW.
1497 Unlike `window-pixel-width', the space occupied by the vertical
1498 scrollbar or divider, if any, is not counted.
1502 struct window *w = decode_window (window);
1504 return make_int (WINDOW_TEXT_WIDTH (w));
1507 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1508 Return the number of columns by which WINDOW is scrolled from left margin.
1512 return make_int (decode_window (window)->hscroll);
1515 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1516 Return the horizontal scrolling amount of WINDOW's modeline.
1517 If the window has no modeline, return nil.
1521 struct window *w = decode_window (window);
1523 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
1527 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1528 Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
1529 If NCOL is negative, it will silently be forced to 0.
1530 If the window has no modeline, return nil. Otherwise, return the actual
1535 struct window *w = decode_window (window);
1537 if (WINDOW_HAS_MODELINE_P (w))
1542 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
1543 if (ncols != w->modeline_hscroll)
1545 MARK_MODELINE_CHANGED;
1546 w->modeline_hscroll = ncols;
1548 return make_int ((int) ncols);
1554 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1555 Set number of columns WINDOW is scrolled from left margin to NCOL.
1556 NCOL should be zero or positive.
1564 ncols = XINT (ncol);
1565 if (ncols < 0) ncols = 0;
1566 w = decode_window (window);
1567 if (w->hscroll != ncols)
1568 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1573 #if 0 /* bogus FSF crock */
1575 xxDEFUN ("window-redisplay-end-trigger",
1576 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1577 Return WINDOW's redisplay end trigger value.
1578 See `set-window-redisplay-end-trigger' for more information.
1582 return decode_window (window)->redisplay_end_trigger;
1585 xxDEFUN ("set-window-redisplay-end-trigger",
1586 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1587 Set WINDOW's redisplay end trigger value to VALUE.
1588 VALUE should be a buffer position (typically a marker) or nil.
1589 If it is a buffer position, then if redisplay in WINDOW reaches a position
1590 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1591 with two arguments: WINDOW, and the end trigger value.
1592 Afterwards the end-trigger value is reset to nil.
1596 return (decode_window (window)->redisplay_end_trigger = value);
1601 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1602 Return a list of the pixel edge coordinates of WINDOW.
1603 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1604 all relative to 0, 0 at the top left corner of WINDOW's frame.
1605 The frame toolbars, menubars and gutters are considered to be outside
1606 of this area, while the scrollbars are considered to be inside.
1610 struct window *w = decode_window (window);
1611 struct frame *f = XFRAME (w->frame);
1614 w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
1616 w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
1618 return list4 (make_int (left),
1620 make_int (left + w->pixel_width),
1621 make_int (top + w->pixel_height));
1624 DEFUN ("window-text-area-pixel-edges",
1625 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1626 Return a list of the pixel edge coordinates of the text area of WINDOW.
1627 The returned list is of the form (LEFT TOP RIGHT BOTTOM),
1628 all relative to 0, 0 at the top left corner of the total area allocated
1629 to the window, which includes the scrollbars.
1633 struct window *w = decode_window (window);
1635 int left = window_left_gutter_width (w, /* modeline = */ 0);
1636 int top = window_top_gutter_height (w);
1637 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1638 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1640 return list4 (make_int (left),
1646 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1647 Return current value of point in WINDOW.
1648 For a non-selected window, this is the value point would have
1649 if that window were selected.
1651 Note that, when WINDOW is the selected window and its buffer
1652 is also currently selected, the value returned is the same as (point).
1653 It would be more strictly correct to return the `top-level' value
1654 of point, outside of any save-excursion forms.
1655 But that value is hard to find.
1659 struct window *w = decode_window (window);
1661 /* The special check for current buffer is necessary for this
1662 function to work as defined when called within an excursion. */
1663 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1664 && current_buffer == XBUFFER (w->buffer))
1665 return Fpoint (Qnil);
1666 return Fmarker_position (w->pointm[CURRENT_DISP]);
1669 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1670 Return position at which display currently starts in WINDOW.
1671 This is updated by redisplay or by calling `set-window-start'.
1675 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1678 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1679 Return position at which display currently ends in WINDOW.
1680 This is updated by redisplay, when it runs to completion.
1681 Simply changing the buffer text or setting `window-start' does not
1682 update this value. WINDOW defaults to the selected window.
1684 If optional arg GUARANTEE is non-nil, the return value is guaranteed
1685 to be the same value as this function would return at the end of the
1686 next full redisplay assuming nothing else changes in the meantime.
1687 This function is potentially much slower with this flag set.
1689 (window, guarantee))
1691 struct window *w = decode_window (window);
1693 if (NILP (guarantee))
1698 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1702 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1703 return make_int (end_of_last_line (w, startp));
1707 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1708 Return pixel height of visible part of last window line if it is clipped.
1709 If the last line is not clipped, return nil.
1713 struct window *w = decode_window (window);
1714 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1715 int num_lines = Dynarr_length (dla);
1716 struct display_line *dl;
1718 /* No lines - no clipped lines */
1719 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
1722 dl = Dynarr_atp (dla, num_lines - 1);
1726 return make_int (dl->ascent + dl->descent - dl->clip);
1729 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1730 Make point value in WINDOW be at position POS in WINDOW's buffer.
1734 struct window *w = decode_window (window);
1736 CHECK_INT_COERCE_MARKER (pos);
1737 if (w == XWINDOW (Fselected_window (Qnil)))
1738 Fgoto_char (pos, Qnil);
1740 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1746 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1747 Make display in WINDOW start at position POS in WINDOW's buffer.
1748 Optional third arg NOFORCE non-nil inhibits next redisplay
1749 from overriding motion of point in order to display at this exact start.
1751 (window, pos, noforce))
1753 struct window *w = decode_window (window);
1755 CHECK_INT_COERCE_MARKER (pos);
1756 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1757 /* this is not right, but much easier than doing what is right. */
1758 /* w->start_at_line_beg = 0; */
1759 /* WTF is the above supposed to mean? GE */
1760 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1761 marker_position (w->start[CURRENT_DISP]));
1764 w->redo_modeline = 1;
1765 SET_LAST_MODIFIED (w, 0);
1766 SET_LAST_FACECHANGE (w);
1768 MARK_WINDOWS_CHANGED (w);
1773 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1774 Return WINDOW's dedicated object, usually t or nil.
1775 See also `set-window-dedicated-p'.
1779 return decode_window (window)->dedicated;
1782 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1783 Control whether WINDOW is dedicated to the buffer it displays.
1784 If it is dedicated, Emacs will not automatically change
1785 which buffer appears in it.
1786 The second argument is the new value for the dedication flag;
1791 struct window *w = decode_window (window);
1793 w->dedicated = NILP (arg) ? Qnil : Qt;
1795 return w->dedicated;
1798 /* FSFmacs has window-display-table here. We have display table as a
1802 /* Record info on buffer window w is displaying
1803 when it is about to cease to display that buffer. */
1805 unshow_buffer (struct window *w)
1807 Lisp_Object buf = w->buffer;
1809 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1812 /* FSF disables this check, so I'll do it too. I hope it won't
1813 break things. --ben */
1815 if (w == XWINDOW (Fselected_window (Qnil))
1816 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1817 /* Do this except when the selected window's buffer
1818 is being removed from some other window. */
1820 /* last_window_start records the start position that this buffer
1821 had in the last window to be disconnected from it.
1822 Now that this statement is unconditional,
1823 it is possible for the buffer to be displayed in the
1824 selected window, while last_window_start reflects another
1825 window which was recently showing the same buffer.
1826 Some people might say that might be a good thing. Let's see. */
1827 XBUFFER (buf)->last_window_start =
1828 marker_position (w->start[CURRENT_DISP]);
1830 /* Point in the selected window's buffer
1831 is actually stored in that buffer, and the window's pointm isn't used.
1832 So don't clobber point in that buffer. */
1833 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1835 struct buffer *b= XBUFFER (buf);
1836 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1837 marker_position (w->pointm[CURRENT_DISP]),
1842 /* Put REPLACEMENT into the window structure in place of OLD. */
1844 replace_window (Lisp_Object old, Lisp_Object replacement)
1847 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1849 /* If OLD is its frame's root_window, then replacement is the new
1850 root_window for that frame. */
1852 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1853 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1855 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1856 WINDOW_TOP (p) = WINDOW_TOP (o);
1857 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1858 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1860 p->next = tem = o->next;
1862 XWINDOW (tem)->prev = replacement;
1864 p->prev = tem = o->prev;
1866 XWINDOW (tem)->next = replacement;
1868 p->parent = tem = o->parent;
1871 if (EQ (XWINDOW (tem)->vchild, old))
1872 XWINDOW (tem)->vchild = replacement;
1873 if (EQ (XWINDOW (tem)->hchild, old))
1874 XWINDOW (tem)->hchild = replacement;
1877 /* #### Here, if replacement is a vertical combination
1878 and so is its new parent, we should make replacement's
1879 children be children of that parent instead. */
1881 ERROR_CHECK_SUBWINDOW_CACHE (p);
1885 window_unmap_subwindows (struct window* w)
1887 assert (!NILP (w->subwindow_instance_cache));
1888 elisp_maphash (unmap_subwindow_instance_cache_mapper,
1889 w->subwindow_instance_cache, (void*)1);
1892 /* we're deleting W; set the structure of W to indicate this. */
1895 mark_window_as_deleted (struct window *w)
1897 /* The window instance cache is going away now, so need to get the
1898 cachels reset by redisplay. */
1899 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
1901 /* The cache is going away. If we leave unmapping to
1902 reset_subwindow_cachels then we get in a situation where the
1903 domain (the window) has been deleted but we still need access to
1904 its attributes in order to unmap windows properly. Since the
1905 subwindows are going to get GC'd anyway as a result of the domain
1906 going away, it is safer to just unmap them all while we know the
1907 domain is still valid. */
1908 ERROR_CHECK_SUBWINDOW_CACHE (w);
1909 window_unmap_subwindows (w);
1912 (while t (split-window) (delete-window))
1913 we end up with a tree of deleted windows which are all connected
1914 through the `next' slot. This might not seem so bad, as they're
1915 deleted, and will presumably be GCed - but if even *one* of those
1916 windows is still being pointed to, by the user, or by a window
1917 configuration, then *all* of those windows stick around.
1919 Since the window-configuration code doesn't need any of the
1920 pointers to other windows (they are all recreated from the
1921 window-config data), we set them all to nil so that we
1922 are able to collect more actual garbage. */
1928 w->subwindow_instance_cache = Qnil;
1932 /* Free the extra data structures attached to windows immediately so
1933 they don't sit around consuming excess space. They will be
1934 reinitialized by the window-configuration code as necessary. */
1935 finalize_window ((void *) w, 0);
1938 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1939 Remove WINDOW from the display. Default is selected window.
1940 If window is the only one on its frame, the frame is deleted as well.
1941 Normally, you cannot delete the last non-minibuffer-only frame (you must
1942 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1943 second argument FORCE is non-nil, you can delete the last frame. (This
1944 will automatically call `save-buffers-kill-emacs'.)
1948 /* This function can GC if this is the only window in the frame */
1956 /* Note: this function is called by other C code on non-leaf
1959 /* Do the equivalent of decode_window() but don't error out on
1960 deleted window; it's OK to delete an already-deleted window. */
1962 window = Fselected_window (Qnil);
1964 CHECK_WINDOW (window);
1966 w = XWINDOW (window);
1968 /* It's okay to delete an already-deleted window. */
1969 if (! WINDOW_LIVE_P (w))
1972 frame = WINDOW_FRAME (w);
1974 d = XDEVICE (FRAME_DEVICE (f));
1976 if (TOP_LEVEL_WINDOW_P (w))
1978 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1979 /* this frame isn't fully initialized yet; don't blow up. */
1982 if (MINI_WINDOW_P (XWINDOW (window)))
1983 error ("Attempt to delete the minibuffer window");
1985 /* It has been suggested that it's a good thing for C-x 0 to have this
1986 behavior, but not such a good idea for #'delete-window to have it.
1987 Maybe C-x 0 should be bound to something else, or maybe frame
1988 deletion should only happen when this is called interactively.
1990 delete_frame_internal (f, !NILP (force), 0, 0);
1994 /* At this point, we know the window has a parent. */
1996 par = XWINDOW (parent);
1998 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1999 /* It's quite likely that deleting a window will result in
2000 subwindows needing to be deleted also (since they are cached
2001 per-window). So we mark them as changed, so that the cachels will
2002 get reset by redisplay and thus deleted subwindows can get
2004 MARK_FRAME_SUBWINDOWS_CHANGED (f);
2006 /* Are we trying to delete any frame's selected window?
2007 Note that we could be dealing with a non-leaf window
2008 where the selected window is one of our children.
2009 So, we check by scanning all the ancestors of the
2010 frame's selected window and comparing each one with
2013 Lisp_Object pwindow;
2015 pwindow = FRAME_SELECTED_WINDOW (f);
2017 while (!NILP (pwindow))
2019 if (EQ (window, pwindow))
2021 pwindow = XWINDOW (pwindow)->parent;
2024 if (EQ (window, pwindow))
2026 /* OK, we found it. */
2027 Lisp_Object alternative;
2028 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
2030 /* If we're about to delete the selected window on the
2031 selected frame, then we should use Fselect_window to select
2032 the new window. On the other hand, if we're about to
2033 delete the selected window on any other frame, we shouldn't do
2034 anything but set the frame's selected_window slot. */
2035 if (EQ (frame, Fselected_frame (Qnil)))
2036 Fselect_window (alternative, Qnil);
2038 set_frame_selected_window (f, alternative);
2042 /* w->buffer is nil in a non-leaf window; in this case,
2043 get rid of the markers we maintain that point into that buffer. */
2044 if (!NILP (w->buffer))
2047 unchain_marker (w->pointm[CURRENT_DISP]);
2048 unchain_marker (w->pointm[DESIRED_DISP]);
2049 unchain_marker (w->pointm[CMOTION_DISP]);
2050 unchain_marker (w->start[CURRENT_DISP]);
2051 unchain_marker (w->start[DESIRED_DISP]);
2052 unchain_marker (w->start[CMOTION_DISP]);
2053 unchain_marker (w->sb_point);
2054 /* This breaks set-window-configuration if windows in the saved
2055 configuration get deleted and multiple frames are in use. */
2056 /* w->buffer = Qnil; */
2059 /* close up the hole in the sibling list */
2060 if (!NILP (w->next))
2061 XWINDOW (w->next)->prev = w->prev;
2062 if (!NILP (w->prev))
2063 XWINDOW (w->prev)->next = w->next;
2064 if (EQ (window, par->hchild))
2065 par->hchild = w->next;
2066 if (EQ (window, par->vchild))
2067 par->vchild = w->next;
2069 /* Find one of our siblings to give our space to. */
2071 Lisp_Object sib = w->prev;
2074 /* If w gives its space to its next sibling, that sibling needs
2075 to have its top/left side pulled back to where w's is.
2076 set_window_{height,width} will re-position the sibling's
2079 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
2080 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
2083 /* Stretch that sibling. */
2084 if (!NILP (par->vchild))
2085 set_window_pixheight
2086 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
2087 if (!NILP (par->hchild))
2089 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
2092 /* If parent now has only one child,
2093 put the child into the parent's place. */
2095 Lisp_Object parchild = par->hchild;
2096 if (NILP (parchild))
2097 parchild = par->vchild;
2098 if (NILP (XWINDOW (parchild)->next))
2100 replace_window (parent, parchild);
2101 mark_window_as_deleted (XWINDOW (parent));
2105 /* Since we may be deleting combination windows, we must make sure that
2106 not only W but all its children have been marked as deleted. */
2107 if (!NILP (w->hchild))
2108 delete_all_subwindows (XWINDOW (w->hchild));
2109 else if (!NILP (w->vchild))
2110 delete_all_subwindows (XWINDOW (w->vchild));
2112 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and
2113 therefore redisplay, so it requires the mirror structure to be
2114 correct. We must dirty the mirror before it is called. */
2115 f->mirror_dirty = 1;
2117 mark_window_as_deleted (w);
2123 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2124 Return the next window after WINDOW in the canonical ordering of windows.
2125 If omitted, WINDOW defaults to the selected window.
2127 Optional second arg MINIBUF t means count the minibuffer window even
2128 if not active. MINIBUF nil or omitted means count the minibuffer iff
2129 it is active. MINIBUF neither t nor nil means not to count the
2130 minibuffer even if it is active.
2132 Several frames may share a single minibuffer; if the minibuffer
2133 counts, all windows on all frames that share that minibuffer count
2134 too. Therefore, `next-window' can be used to iterate through the
2135 set of windows even when the minibuffer is on another frame. If the
2136 minibuffer does not count, only windows from WINDOW's frame count.
2138 By default, only the windows in the selected frame are considered.
2139 The optional argument WHICH-FRAMES changes this behavior:
2140 WHICH-FRAMES = `visible' means search windows on all visible frames.
2141 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2142 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2143 WHICH-FRAMES = a frame means search only windows on that frame.
2144 Anything else means restrict to the selected frame.
2146 The optional fourth argument WHICH-DEVICES further clarifies on which
2147 devices to search for frames as specified by WHICH-FRAMES. This value
2148 is only meaningful if WHICH-FRAMES is non-nil.
2149 If nil or omitted, search all devices on the selected console.
2150 If a device, only search that device.
2151 If a console, search all devices on that console.
2152 If a device type, search all devices of that type.
2153 If `window-system', search all window-system devices.
2154 Any other non-nil value means search all devices.
2156 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2157 you can use `next-window' to iterate through the entire cycle of
2158 acceptable windows, eventually ending up back at the window you started with.
2159 `previous-window' traverses the same cycle, in the reverse order.
2161 (window, minibuf, which_frames, which_devices))
2164 Lisp_Object start_window;
2167 window = Fselected_window (Qnil);
2169 CHECK_LIVE_WINDOW (window);
2171 start_window = window;
2173 /* minibuf == nil may or may not include minibuffers.
2174 Decide if it does. */
2176 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2177 else if (! EQ (minibuf, Qt))
2179 /* Now `minibuf' is one of:
2180 t => count all minibuffer windows
2181 lambda => count none of them
2182 or a specific minibuffer window (the active one) to count. */
2184 /* which_frames == nil doesn't specify which frames to include. */
2185 if (NILP (which_frames))
2186 which_frames = (! EQ (minibuf, Qlambda)
2187 ? (FRAME_MINIBUF_WINDOW
2190 (XWINDOW (window)))))
2192 else if (EQ (which_frames, Qvisible))
2194 else if (ZEROP (which_frames))
2196 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2197 /* If which_frames is a frame and window arg isn't on that frame, just
2198 return the first window on the frame. */
2199 return frame_first_window (XFRAME (which_frames));
2200 else if (! EQ (which_frames, Qt))
2201 which_frames = Qnil;
2202 /* Now `which_frames' is one of:
2203 t => search all frames
2204 nil => search just the current frame
2205 visible => search just visible frames
2206 0 => search visible and iconified frames
2207 a window => search the frame that window belongs to. */
2209 /* Do this loop at least once, to get the next window, and perhaps
2210 again, if we hit the minibuffer and that is not acceptable. */
2213 /* Find a window that actually has a next one. This loop
2214 climbs up the tree. */
2215 while (tem = XWINDOW (window)->next, NILP (tem))
2216 if (tem = XWINDOW (window)->parent, !NILP (tem))
2218 else /* window must be minibuffer window now */
2220 /* We've reached the end of this frame.
2221 Which other frames are acceptable? */
2222 tem = WINDOW_FRAME (XWINDOW (window));
2224 if (! NILP (which_frames))
2226 Lisp_Object tem1 = tem;
2227 tem = next_frame (tem, which_frames, which_devices);
2229 /* In the case where the minibuffer is active,
2230 and we include its frame as well as the selected one,
2231 next_frame may get stuck in that frame.
2232 If that happens, go back to the selected frame
2233 so we can complete the cycle. */
2235 XSETFRAME (tem, selected_frame ());
2238 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2244 /* If we're in a combination window, find its first child and
2245 recurse on that. Otherwise, we've found the window we want. */
2248 if (!NILP (XWINDOW (window)->hchild))
2249 window = XWINDOW (window)->hchild;
2250 else if (!NILP (XWINDOW (window)->vchild))
2251 window = XWINDOW (window)->vchild;
2255 /* Which windows are acceptable?
2256 Exit the loop and accept this window if
2257 this isn't a minibuffer window,
2258 or we're accepting all minibuffer windows,
2259 or this is the active minibuffer and we are accepting that one, or
2260 we've come all the way around and we're back at the original window. */
2261 while (MINI_WINDOW_P (XWINDOW (window))
2262 && ! EQ (minibuf, Qt)
2263 && ! EQ (minibuf, window)
2264 && ! EQ (window, start_window));
2269 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2270 Return the window preceding WINDOW in the canonical ordering of windows.
2271 If omitted, WINDOW defaults to the selected window.
2273 Optional second arg MINIBUF t means count the minibuffer window even
2274 if not active. MINIBUF nil or omitted means count the minibuffer iff
2275 it is active. MINIBUF neither t nor nil means not to count the
2276 minibuffer even if it is active.
2278 Several frames may share a single minibuffer; if the minibuffer
2279 counts, all windows on all frames that share that minibuffer count
2280 too. Therefore, `previous-window' can be used to iterate through
2281 the set of windows even when the minibuffer is on another frame. If
2282 the minibuffer does not count, only windows from WINDOW's frame count.
2284 By default, only the windows in the selected frame are considered.
2285 The optional argument WHICH-FRAMES changes this behavior:
2286 WHICH-FRAMES = `visible' means search windows on all visible frames.
2287 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2288 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2289 WHICH-FRAMES = a frame means search only windows on that frame.
2290 Anything else means restrict to the selected frame.
2292 The optional fourth argument WHICH-DEVICES further clarifies on which
2293 devices to search for frames as specified by WHICH-FRAMES. This value
2294 is only meaningful if WHICH-FRAMES is non-nil.
2295 If nil or omitted, search all devices on the selected console.
2296 If a device, only search that device.
2297 If a console, search all devices on that console.
2298 If a device type, search all devices of that type.
2299 If `window-system', search all window-system devices.
2300 Any other non-nil value means search all devices.
2302 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2303 you can use `previous-window' to iterate through the entire cycle of
2304 acceptable windows, eventually ending up back at the window you started with.
2305 `next-window' traverses the same cycle, in the reverse order.
2307 (window, minibuf, which_frames, devices))
2310 Lisp_Object start_window;
2313 window = Fselected_window (Qnil);
2315 CHECK_LIVE_WINDOW (window);
2317 start_window = window;
2319 /* minibuf == nil may or may not include minibuffers.
2320 Decide if it does. */
2322 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2323 else if (! EQ (minibuf, Qt))
2325 /* Now `minibuf' is one of:
2326 t => count all minibuffer windows
2327 lambda => count none of them
2328 or a specific minibuffer window (the active one) to count. */
2330 /* which_frames == nil doesn't specify which frames to include.
2331 Decide which frames it includes. */
2332 if (NILP (which_frames))
2333 which_frames = (! EQ (minibuf, Qlambda)
2334 ? (FRAME_MINIBUF_WINDOW
2337 (XWINDOW (window)))))
2339 else if (EQ (which_frames, Qvisible))
2341 else if (ZEROP (which_frames))
2343 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2344 /* If which_frames is a frame and window arg isn't on that frame, just
2345 return the first window on the frame. */
2346 return frame_first_window (XFRAME (which_frames));
2347 else if (! EQ (which_frames, Qt))
2348 which_frames = Qnil;
2349 /* Now `which_frames' is one of:
2350 t => search all frames
2351 nil => search just the current frame
2352 visible => search just visible frames
2353 0 => search visible and iconified frames
2354 a window => search the frame that window belongs to. */
2356 /* Do this loop at least once, to get the next window, and perhaps
2357 again, if we hit the minibuffer and that is not acceptable. */
2360 /* Find a window that actually has a next one. This loop
2361 climbs up the tree. */
2362 while (tem = XWINDOW (window)->prev, NILP (tem))
2363 if (tem = XWINDOW (window)->parent, !NILP (tem))
2365 else /* window must be minibuffer window now */
2367 /* We have found the top window on the frame.
2368 Which frames are acceptable? */
2369 tem = WINDOW_FRAME (XWINDOW (window));
2371 if (! NILP (which_frames))
2372 /* It's actually important that we use previous_frame here,
2373 rather than next_frame. All the windows acceptable
2374 according to the given parameters should form a ring;
2375 Fnext_window and Fprevious_window should go back and
2376 forth around the ring. If we use next_frame here,
2377 then Fnext_window and Fprevious_window take different
2378 paths through the set of acceptable windows.
2379 window_loop assumes that these `ring' requirement are
2382 Lisp_Object tem1 = tem;
2383 tem = previous_frame (tem, which_frames, devices);
2384 /* In the case where the minibuffer is active,
2385 and we include its frame as well as the selected one,
2386 next_frame may get stuck in that frame.
2387 If that happens, go back to the selected frame
2388 so we can complete the cycle. */
2390 XSETFRAME (tem, selected_frame ());
2393 /* If this frame has a minibuffer, find that window first,
2394 because it is conceptually the last window in that frame. */
2395 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2396 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2398 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2405 /* If we're in a combination window, find its first child and
2406 recurse on that. Otherwise, we've found the window we want. */
2409 if (!NILP (XWINDOW (window)->hchild))
2410 window = XWINDOW (window)->hchild;
2411 else if (!NILP (XWINDOW (window)->vchild))
2412 window = XWINDOW (window)->vchild;
2414 while (tem = XWINDOW (window)->next, !NILP (tem))
2418 /* Which windows are acceptable?
2419 Exit the loop and accept this window if
2420 this isn't a minibuffer window,
2421 or we're accepting all minibuffer windows,
2422 or this is the active minibuffer and we are accepting that one, or
2423 we've come all the way around and we're back at the original window. */
2424 while (MINI_WINDOW_P (XWINDOW (window))
2425 && ! EQ (minibuf, Qt)
2426 && ! EQ (minibuf, window)
2427 && ! EQ (window, start_window));
2432 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2433 Return the next window which is vertically after WINDOW.
2438 struct window *w = decode_window (window);
2439 XSETWINDOW (window, w);
2441 if (MINI_WINDOW_P (XWINDOW (window)))
2444 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2446 if (EQ (window, root))
2449 if (!NILP (XWINDOW (window)->hchild))
2450 window = XWINDOW (window)->hchild;
2451 else if (!NILP (XWINDOW (window)->vchild))
2452 window = XWINDOW (window)->vchild;
2459 if (!NILP (XWINDOW (window)->parent) &&
2460 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2462 if (!NILP (XWINDOW (window)->next))
2463 return XWINDOW (window)->next;
2465 window = XWINDOW (window)->parent;
2468 window = XWINDOW (window)->parent;
2470 while (!EQ (window, root));
2473 if (!NILP (XWINDOW (window)->hchild))
2474 window = XWINDOW (window)->hchild;
2475 else if (!NILP (XWINDOW (window)->vchild))
2476 window = XWINDOW (window)->vchild;
2481 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2482 Select the COUNT'th different window on this frame.
2483 All windows on current frame are arranged in a cyclic order.
2484 This command selects the window COUNT steps away in that order.
2485 A negative COUNT moves in the opposite order.
2487 By default, only the windows in the selected frame are considered.
2488 The optional argument WHICH-FRAMES changes this behavior:
2489 WHICH-FRAMES = `visible' means search windows on all visible frames.
2490 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2491 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2492 WHICH-FRAMES = a frame means search only windows on that frame.
2493 Anything else means restrict to the selected frame.
2495 The optional argument WHICH-DEVICES further clarifies on which devices
2496 to search for frames as specified by WHICH-FRAMES. This value is only
2497 meaningful if WHICH-FRAMES is non-nil.
2498 If nil or omitted, search all devices on the selected console.
2499 If a device, only search that device.
2500 If a console, search all devices on that console.
2501 If a device type, search all devices of that type.
2502 If `window-system', search all window-system devices.
2503 Any other non-nil value means search all devices.
2505 (count, which_frames, which_devices))
2511 w = Fselected_window (Qnil);
2516 w = Fnext_window (w, Qnil, which_frames, which_devices);
2521 w = Fprevious_window (w, Qnil, which_frames, which_devices);
2524 Fselect_window (w, Qnil);
2529 /* Look at all windows, performing an operation specified by TYPE
2532 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2533 frame. If FRAMES is a frame, just look at windows on that frame.
2534 If MINI is non-zero, perform the operation on minibuffer windows too.
2540 GET_BUFFER_WINDOW, /* Arg is buffer */
2541 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2542 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2543 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2544 UNDEDICATE_BUFFER, /* Arg is buffer */
2546 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2547 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2551 window_loop (enum window_loop type,
2554 Lisp_Object which_frames,
2556 Lisp_Object which_devices)
2558 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2560 Lisp_Object best_window = Qnil;
2561 Lisp_Object next_window;
2562 Lisp_Object last_window;
2563 struct frame *frame;
2564 Lisp_Object frame_arg = Qt;
2565 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2566 /* #### I think the change of "precomputing" last_window and next_window
2567 * #### catch the lossage this is meant(?) to punt on...
2570 Lisp_Object devcons, concons;
2572 /* If we're only looping through windows on a particular frame,
2573 FRAME points to that frame. If we're looping through windows
2574 on all frames, FRAME is 0. */
2575 if (FRAMEP (which_frames))
2576 frame = XFRAME (which_frames);
2577 else if (NILP (which_frames))
2578 frame = selected_frame ();
2582 /* FRAME_ARG is Qlambda to stick to one frame,
2583 Qvisible to consider all visible frames,
2586 frame_arg = Qlambda;
2587 else if (ZEROP (which_frames))
2588 frame_arg = which_frames;
2589 else if (EQ (which_frames, Qvisible))
2590 frame_arg = which_frames;
2592 DEVICE_LOOP_NO_BREAK (devcons, concons)
2594 Lisp_Object device = XCAR (devcons);
2595 Lisp_Object the_frame;
2598 XSETFRAME (the_frame, frame);
2600 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2602 if (NILP (the_frame))
2605 if (!device_matches_device_spec (device,
2606 NILP (which_devices) ?
2607 FRAME_CONSOLE (XFRAME (the_frame)) :
2611 /* Pick a window to start with. */
2615 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2617 /* Figure out the last window we're going to mess with. Since
2618 Fnext_window, given the same options, is guaranteed to go in a
2619 ring, we can just use Fprevious_window to find the last one.
2621 We can't just wait until we hit the first window again,
2622 because it might be deleted. */
2624 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, device);
2629 struct window *p = XWINDOW (w);
2631 /* Pick the next window now, since some operations will delete
2632 the current window. */
2633 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
2635 /* #### Still needed ?? */
2636 /* Given the outstanding quality of the rest of this code,
2637 I feel no shame about putting this piece of shit in. */
2638 if (++lose_lose >= 500)
2640 /* Call to abort() added by Darryl Okahata (16 Nov. 2001),
2641 at Ben's request, to catch any remaining bugs.
2643 If you find that XEmacs is aborting here, and you
2644 need to be up and running ASAP, it should be safe to
2645 comment out the following abort(), as long as you
2646 leave the "break;" alone. */
2648 break; /* <--- KEEP THIS HERE! Do not delete! */
2651 /* Note that we do not pay attention here to whether
2652 the frame is visible, since Fnext_window skips non-visible frames
2653 if that is desired, under the control of frame_arg. */
2654 if (! MINI_WINDOW_P (p)
2655 || (mini && minibuf_level > 0))
2658 case GET_BUFFER_WINDOW:
2660 if (XBUFFER (p->buffer) == XBUFFER (obj))
2665 case GET_BUFFER_WINDOW_COUNT:
2667 if (XBUFFER (p->buffer) == XBUFFER (obj))
2672 case GET_LRU_WINDOW:
2674 /* t as arg means consider only full-width windows */
2676 && !window_full_width_p (p))
2678 /* Ignore dedicated windows and minibuffers. */
2679 if (MINI_WINDOW_P (p)
2680 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2682 if (NILP (best_window)
2683 || (XINT (XWINDOW (best_window)->use_time)
2684 > XINT (p->use_time)))
2689 case GET_BUFFER_MRU_WINDOW:
2691 /* #### what about the first check in GET_LRU_WINDOW? */
2692 /* Ignore dedicated windows and minibuffers. */
2693 if (MINI_WINDOW_P (p)
2694 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2697 if (XBUFFER (p->buffer) == XBUFFER (obj))
2699 if (NILP (best_window)
2700 || (XINT (XWINDOW (best_window)->use_time)
2701 < XINT (p->use_time)))
2707 case UNDEDICATE_BUFFER:
2709 if ((XBUFFER (p->buffer) == XBUFFER (obj)))
2710 p->dedicated = Qnil;
2714 case DELETE_OTHER_WINDOWS:
2716 /* Don't delete the last window on a frame; this can
2717 happen when the minibuffer is selected, and would
2718 cause the frame to be deleted. */
2719 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2720 Fdelete_window (w, Qnil);
2724 case DELETE_BUFFER_WINDOWS:
2726 if (EQ (p->buffer, obj))
2728 struct frame *f = XFRAME (WINDOW_FRAME (p));
2730 /* If this window is dedicated, and in a frame
2731 of its own, kill the frame. */
2732 if (EQ (w, FRAME_ROOT_WINDOW (f))
2733 && !NILP (p->dedicated)
2734 && other_visible_frames (f))
2736 /* Skip the other windows on this frame.
2737 There might be one, the minibuffer! */
2738 if (! EQ (w, last_window))
2739 while (f == XFRAME (WINDOW_FRAME
2740 (XWINDOW (next_window))))
2742 /* As we go, check for the end of the
2743 loop. We mustn't start going
2744 around a second time. */
2745 if (EQ (next_window, last_window))
2750 next_window = Fnext_window (next_window,
2754 /* Now we can safely delete the frame. */
2755 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2758 /* If we're deleting the buffer displayed in
2759 the only window on the frame, find a new
2760 buffer to display there. */
2761 if (NILP (p->parent))
2763 Lisp_Object new_buffer;
2764 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2765 if (NILP (new_buffer))
2766 new_buffer = Fget_buffer_create (QSscratch);
2767 Fset_window_buffer (w, new_buffer, Qnil);
2768 if (EQ (w, Fselected_window (Qnil)))
2769 Fset_buffer (p->buffer);
2772 Fdelete_window (w, Qnil);
2777 case GET_LARGEST_WINDOW:
2779 /* Ignore dedicated windows and minibuffers. */
2780 if (MINI_WINDOW_P (p)
2781 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2784 /* write the check as follows to avoid tripping
2785 error_check_window() --ben */
2786 struct window *b = NILP (best_window) ? 0 :
2787 XWINDOW (best_window);
2788 if (NILP (best_window)
2789 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2790 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2800 if (EQ (w, last_window))
2807 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2810 #if 0 /* not currently used */
2813 buffer_window_count (struct buffer *b, struct frame *f)
2815 Lisp_Object buffer, frame;
2817 XSETFRAME (frame, f);
2818 XSETBUFFER (buffer, b);
2820 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2825 buffer_window_mru (struct window *w)
2827 Lisp_Object window =
2828 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2832 else if (XWINDOW (window) == w)
2841 undedicate_windows (Lisp_Object buffer, Lisp_Object frame)
2843 window_loop (UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2847 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2848 Return the window least recently selected or used for display.
2850 By default, only the windows in the selected frame are considered.
2851 The optional argument WHICH-FRAMES changes this behavior:
2852 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2853 If WHICH-FRAMES is 0, search all visible and iconified frames.
2854 If WHICH-FRAMES is t, search all frames.
2855 If WHICH-FRAMES is nil, search only the selected frame.
2856 If WHICH-FRAMES is a frame, search only that frame.
2858 The optional argument WHICH-DEVICES further clarifies on which devices
2859 to search for frames as specified by WHICH-FRAMES. This value is only
2860 meaningful if WHICH-FRAMES is non-nil.
2861 If nil or omitted, search all devices on the selected console.
2862 If a device, only search that device.
2863 If a console, search all devices on that console.
2864 If a device type, search all devices of that type.
2865 If `window-system', search all devices on window-system consoles.
2866 Any other non-nil value means search all devices.
2868 (which_frames, which_devices))
2871 /* First try for a non-dedicated window that is full-width */
2872 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2873 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2876 /* Then try for any non-dedicated window */
2877 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices);
2878 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2882 /* FSFmacs never returns a dedicated window here. If we do,
2883 it makes `display-buffer' not work right. #### All of this
2884 shit is so disgusting and awful that it needs to be rethought
2886 /* then try for a dedicated window that is full-width */
2887 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2888 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2891 /* If none of them, then all windows, dedicated or not. */
2892 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
2894 /* At this point we damn well better have found something. */
2895 if (NILP (w)) abort ();
2901 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2902 Return the window largest in area.
2904 By default, only the windows in the selected frame are considered.
2905 The optional argument WHICH-FRAMES changes this behavior:
2906 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2907 If WHICH-FRAMES is 0, search all visible and iconified frames.
2908 If WHICH-FRAMES is t, search all frames.
2909 If WHICH-FRAMES is nil, search only the selected frame.
2910 If WHICH-FRAMES is a frame, search only that frame.
2912 The optional argument WHICH-DEVICES further clarifies on which devices
2913 to search for frames as specified by WHICH-FRAMES. This value is only
2914 meaningful if WHICH-FRAMES is non-nil.
2915 If nil or omitted, search all devices on the selected console.
2916 If a device, only search that device.
2917 If a console, search all devices on that console.
2918 If a device type, search all devices of that type.
2919 If `window-system', search all devices on window-system consoles.
2920 Any other non-nil value means search all devices.
2922 (which_frames, which_devices))
2924 /* Don't search dedicated windows because FSFmacs doesn't.
2925 This stuff is all black magic so don't try to apply common
2927 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2928 which_frames, 0, which_devices);
2931 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2932 Return a window currently displaying BUFFER, or nil if none.
2934 By default, only the windows in the selected frame are considered.
2935 The optional argument WHICH-FRAMES changes this behavior:
2936 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2937 If WHICH-FRAMES is 0, search all visible and iconified frames.
2938 If WHICH-FRAMES is t, search all frames.
2939 If WHICH-FRAMES is nil, search only the selected frame.
2940 If WHICH-FRAMES is a frame, search only that frame.
2942 The optional argument WHICH-DEVICES further clarifies on which devices
2943 to search for frames as specified by WHICH-FRAMES. This value is only
2944 meaningful if WHICH-FRAMES is non-nil.
2945 If nil or omitted, search all devices on the selected console.
2946 If a device, only search that device.
2947 If a console, search all devices on that console.
2948 If a device type, search all devices of that type.
2949 If `window-system', search all devices on window-system consoles.
2950 Any other non-nil value means search all devices.
2952 (buffer, which_frames, which_devices))
2954 buffer = Fget_buffer (buffer);
2955 if (BUFFERP (buffer))
2956 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2957 return window_loop (GET_BUFFER_WINDOW, buffer, 1,
2958 which_frames, 1, which_devices);
2963 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2964 but there is no sensible way to implement those functions, since
2965 you can't in general derive a window from a buffer. */
2967 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2969 Return the width in pixels of the left outside margin of window WINDOW.
2970 If WINDOW is nil, the selected window is assumed.
2974 return make_int (window_left_margin_width (decode_window (window)));
2977 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2979 Return the width in pixels of the right outside margin of window WINDOW.
2980 If WINDOW is nil, the selected window is assumed.
2984 return make_int (window_right_margin_width (decode_window (window)));
2987 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2988 Make WINDOW (or the selected window) fill its frame.
2989 Only the frame WINDOW is on is affected.
2990 This function tries to reduce display jumps
2991 by keeping the text previously visible in WINDOW
2992 in the same place on the frame. Doing this depends on
2993 the value of (window-start WINDOW), so if calling this function
2994 in a program gives strange scrolling, make sure the window-start
2995 value is reasonable when this function is called.
2999 struct window *w = decode_window (window);
3000 struct buffer *b = XBUFFER (w->buffer);
3002 int old_top = WINDOW_TOP (w);
3004 XSETWINDOW (window, w);
3006 if (MINI_WINDOW_P (w) && old_top > 0)
3007 error ("Can't expand minibuffer to full frame");
3009 /* Ignore dedicated windows. */
3010 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3012 start_pos = marker_position (w->start[CURRENT_DISP]);
3014 /* Try to minimize scrolling, by setting the window start to the
3015 point which will cause the text at the old window start to be at
3016 the same place on the frame. But don't try to do this if the
3017 window start is outside the visible portion (as might happen when
3018 the display is not current, due to typeahead). */
3019 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
3020 && !MINI_WINDOW_P (w))
3022 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
3024 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
3026 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
3028 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3030 /* We need to do this, so that the window-scroll-functions
3038 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3039 "bDelete windows on (buffer): ", /*
3040 Delete all windows showing BUFFER.
3042 Optional second argument WHICH-FRAMES controls which frames are affected.
3043 If nil or omitted, delete all windows showing BUFFER in any frame.
3044 If t, delete only windows showing BUFFER in the selected frame.
3045 If `visible', delete all windows showing BUFFER in any visible frame.
3046 If a frame, delete only windows showing BUFFER in that frame.
3047 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3048 except that the meanings of nil and t are reversed.
3050 The optional third argument WHICH-DEVICES further clarifies on which
3051 devices to search for frames as specified by WHICH-FRAMES. This value
3052 is only meaningful if WHICH-FRAMES is not t.
3053 If nil or omitted, search only the selected console.
3054 If a device, only search that device.
3055 If a console, search all devices on that console.
3056 If a device type, search all devices of that type.
3057 If `window-system', search all devices on a window system.
3058 Any other non-nil value means search all devices.
3060 (buffer, which_frames, which_devices))
3062 /* This function can GC */
3063 buffer = Fget_buffer (buffer);
3064 CHECK_BUFFER (buffer);
3066 /* WHICH-FRAMES values t and nil mean the opposite of what
3067 window_loop expects. */
3068 if (EQ (which_frames, Qnil))
3070 else if (EQ (which_frames, Qt))
3071 which_frames = Qnil;
3073 /* Ignore dedicated windows. */
3074 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0,
3075 which_frames, 0, which_devices);
3080 list_windows (struct window *w, Lisp_Object value)
3084 if (!NILP (w->hchild))
3085 value = list_windows (XWINDOW (w->hchild), value);
3086 else if (!NILP (w->vchild))
3087 value = list_windows (XWINDOW (w->vchild), value);
3091 XSETWINDOW (window, w);
3092 value = Fcons (window, value);
3096 w = XWINDOW (w->next);
3102 list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec)
3104 Lisp_Object devcons, concons;
3105 Lisp_Object retval = Qnil;
3107 DEVICE_LOOP_NO_BREAK (devcons, concons)
3109 Lisp_Object frame_list, the_window;
3110 Lisp_Object device, tail;
3112 device = XCAR (devcons);
3113 frame_list = DEVICE_FRAME_LIST (XDEVICE (device));
3115 LIST_LOOP (tail, frame_list)
3117 if ((NILP (frame_spec)
3118 && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device))))
3119 || (EQ (frame_spec, Qvisible)
3120 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail))))
3121 || (FRAMEP (frame_spec)
3122 && !EQ (frame_spec, XCAR (tail)))
3123 || (!NILP (frame_spec)
3124 && !device_matches_device_spec (device,
3125 NILP (device_spec) ?
3129 the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail)));
3130 retval = list_windows (XWINDOW (the_window), retval);
3133 return Fnreverse (retval);
3136 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3,
3137 "bReplace buffer in windows: ", /*
3138 Replace BUFFER with some other buffer in all windows showing it.
3140 Optional second argument WHICH-FRAMES controls which frames are affected.
3141 If nil or omitted, all frames are affected.
3142 If t, only the selected frame is affected.
3143 If `visible', all visible frames are affected.
3144 If a frame, only that frame is affected.
3145 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3146 except that the meanings of nil and t are reversed.
3148 The optional third argument WHICH-DEVICES further clarifies on which
3149 devices to search for frames as specified by WHICH-FRAMES. This value
3150 is only meaningful if WHICH-FRAMES is not t.
3151 If nil or omitted, search only the selected console.
3152 If a device, only search that device.
3153 If a console, search all devices on that console.
3154 If a device type, search all devices of that type.
3155 If `window-system', search all devices on a window system.
3156 Any other non-nil value means search all devices.
3158 (buffer, which_frames, which_devices))
3160 /* This function can GC */
3161 Lisp_Object window_list;
3163 struct gcpro gcpro1, gcpro2;
3165 if (EQ (which_frames, Qnil))
3167 else if (EQ (which_frames, Qt))
3168 which_frames = Qnil;
3169 window_list = list_all_windows (which_frames, which_devices);
3171 buffer = Fget_buffer (buffer);
3172 CHECK_BUFFER (buffer);
3174 GCPRO2 (window_list, buffer);
3175 LIST_LOOP (tail, window_list)
3177 Lisp_Object window = XCAR (tail);
3178 if (!MINI_WINDOW_P (XWINDOW (window))
3179 && EQ (XWINDOW (window)->buffer, buffer))
3181 Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil);
3182 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
3183 if (NILP (another_buffer))
3184 another_buffer = Fget_buffer_create (QSscratch);
3185 if (!NILP (XWINDOW (window)->dedicated)
3187 FRAME_ROOT_WINDOW (XFRAME (frame)))
3188 && other_visible_frames (XFRAME (frame)))
3190 delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */
3194 Fset_window_buffer (window, another_buffer, Qnil);
3195 if (EQ (window, Fselected_window (Qnil)))
3196 Fset_buffer (XWINDOW (window)->buffer);
3204 /* The smallest acceptable dimensions for a window. Anything smaller
3205 might crash Emacs. */
3206 #define MIN_SAFE_WINDOW_WIDTH (2)
3207 #define MIN_SAFE_WINDOW_HEIGHT (2)
3209 /* Make sure that window_min_height and window_min_width are
3210 not too small; if they are, set them to safe minima. */
3213 check_min_window_sizes (void)
3215 /* Smaller values might permit a crash. */
3216 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3217 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3218 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3219 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3223 frame_min_height (struct frame *frame)
3225 /* For height, we have to see whether the frame has a minibuffer, and
3226 whether it wants a modeline. */
3227 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3228 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3229 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3232 /* Return non-zero if both frame sizes are less than or equal to
3233 minimal allowed values. ROWS and COLS are in characters */
3235 frame_size_valid_p (struct frame *frame, int rows, int cols)
3237 return (rows >= frame_min_height (frame)
3238 && cols >= MIN_SAFE_WINDOW_WIDTH);
3241 /* Return non-zero if both frame sizes are less than or equal to
3242 minimal allowed values. WIDTH and HEIGHT are in pixels */
3244 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3247 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3248 return frame_size_valid_p (frame, rows, cols);
3251 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3252 minimum allowable size. */
3254 check_frame_size (struct frame *frame, int *rows, int *cols)
3256 int min_height = frame_min_height (frame);
3258 if (*rows < min_height)
3260 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3261 *cols = MIN_SAFE_WINDOW_WIDTH;
3264 /* Normally the window is deleted if it gets too small.
3265 nodelete nonzero means do not do this.
3266 (The caller should check later and do so if appropriate) */
3268 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3271 struct window *w = XWINDOW (window);
3272 struct frame *f = XFRAME (w->frame);
3274 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3275 Lisp_Object child, minor_kid, major_kid;
3278 int defheight, defwidth;
3280 /* #### This is very likely incorrect and instead the char_to_pixel_
3281 functions should be called. */
3282 default_face_height_and_width (window, &defheight, &defwidth);
3283 line_size = (set_height ? defheight : defwidth);
3285 check_min_window_sizes ();
3287 minsize = (set_height ? window_min_height : window_min_width);
3288 minsize *= line_size;
3291 && !TOP_LEVEL_WINDOW_P (w)
3292 && new_pixsize < minsize)
3294 Fdelete_window (window, Qnil);
3298 SET_LAST_MODIFIED (w, 0);
3299 SET_LAST_FACECHANGE (w);
3300 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3303 WINDOW_HEIGHT (w) = new_pixsize;
3304 major_kid = w->vchild;
3305 minor_kid = w->hchild;
3309 WINDOW_WIDTH (w) = new_pixsize;
3310 major_kid = w->hchild;
3311 minor_kid = w->vchild;
3314 if (!NILP (minor_kid))
3316 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3319 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3321 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3323 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3326 else if (!NILP (major_kid))
3328 int last_pos, last_old_pos, pos, old_pos, first;
3329 int pixel_adj_left = new_pixsize - old_pixsize;
3330 int div_val = old_pixsize << 1;
3333 * Previously we bailed out here if there was no size change.
3334 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3335 * toolbar appears or disappears, windows may not change size,
3336 * but their top and left coordinates need to be updated.
3338 * So we don't bail until after the loop below.
3341 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3344 for (child = major_kid; !NILP (child); child = c->next)
3346 c = XWINDOW (child);
3350 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3351 WINDOW_TOP (c) = last_pos;
3355 old_pos = last_old_pos + WINDOW_WIDTH (c);
3356 WINDOW_LEFT (c) = last_pos;
3359 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3360 /* All but the last window should have a height which is
3361 a multiple of the default line height. */
3362 if (!NILP (c->next))
3363 pos = (pos / line_size) * line_size;
3365 /* Avoid confusion: don't delete child if it becomes too small */
3366 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3368 last_pos = pos + first;
3369 last_old_pos = old_pos;
3372 /* Sometimes we may get called with our old size. In that case
3373 we don't need to do anything else. */
3374 if (!pixel_adj_left)
3377 /* Now delete any children that became too small. */
3379 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3382 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3384 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3389 /* Set the height of WINDOW and all its inferiors. */
3391 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3393 set_window_pixsize (window, new_pixheight, nodelete, 1);
3396 /* Recursively set width of WINDOW and its inferiors. */
3398 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3400 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3404 static int window_select_count;
3406 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3407 Make WINDOW display BUFFER as its contents.
3408 BUFFER can be a buffer or buffer name.
3410 With non-nil optional argument NORECORD, do not modify the
3411 global or per-frame buffer ordering.
3413 (window, buffer, norecord))
3416 struct window *w = decode_window (window);
3417 int old_buffer_local_face_property = 0;
3419 buffer = Fget_buffer (buffer);
3420 CHECK_BUFFER (buffer);
3422 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3423 error ("Attempt to display deleted buffer");
3427 error ("Window is deleted");
3429 /* While this seems like a logical thing to do, it causes problems
3430 because of saved window configurations. It is possible for a
3431 buffer to get restored into a window in which it is already being
3432 displayed, but start and point are actually at completely
3433 different locations. So we let this function complete fully and
3434 it will then make sure redisplay correctly updates things.
3436 #### This is a kludge. The correct approach is not to do this
3437 but to fix set-window-configuration. */
3439 else if (EQ (tem, buffer))
3442 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3443 is first being set up. */
3445 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3446 error ("Window is dedicated to buffer %s",
3447 XSTRING_DATA (XBUFFER (tem)->name));
3449 old_buffer_local_face_property =
3450 XBUFFER (w->buffer)->buffer_local_face_property;
3455 w->window_end_pos[CURRENT_DISP] = 0;
3457 w->modeline_hscroll = 0;
3458 Fset_marker (w->pointm[CURRENT_DISP],
3459 make_int (BUF_PT (XBUFFER (buffer))),
3461 set_marker_restricted (w->start[CURRENT_DISP],
3462 make_int (XBUFFER (buffer)->last_window_start),
3464 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3465 /* set start_at_line_beg correctly. GE */
3466 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3467 marker_position (w->start[CURRENT_DISP]));
3468 w->force_start = 0; /* Lucid fix */
3469 SET_LAST_MODIFIED (w, 1);
3470 SET_LAST_FACECHANGE (w);
3471 MARK_WINDOWS_CHANGED (w);
3473 int new_buffer_local_face_property =
3474 XBUFFER (w->buffer)->buffer_local_face_property;
3476 if (new_buffer_local_face_property
3477 || new_buffer_local_face_property != old_buffer_local_face_property)
3478 MARK_WINDOW_FACES_CHANGED (w);
3480 recompute_all_cached_specifiers_in_window (w);
3481 if (EQ (window, Fselected_window (Qnil)))
3483 if (NILP (norecord))
3484 Frecord_buffer (buffer);
3486 Fset_buffer (buffer);
3491 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3492 Select WINDOW. Most editing will apply to WINDOW's buffer.
3493 The main editor command loop selects the buffer of the selected window
3494 before each command.
3496 With non-nil optional argument NORECORD, do not modify the
3497 global or per-frame buffer ordering.
3502 Lisp_Object old_selected_window = Fselected_window (Qnil);
3504 CHECK_LIVE_WINDOW (window);
3505 w = XWINDOW (window);
3507 /* we have already caught dead-window errors */
3508 if (!NILP (w->hchild) || !NILP (w->vchild))
3509 error ("Trying to select non-leaf window");
3511 w->use_time = make_int (++window_select_count);
3513 if (EQ (window, old_selected_window))
3516 /* deselect the old window, if it exists (it might not exist if
3517 the selected device has no frames, which occurs at startup) */
3518 if (!NILP (old_selected_window))
3520 struct window *ow = XWINDOW (old_selected_window);
3522 Fset_marker (ow->pointm[CURRENT_DISP],
3523 make_int (BUF_PT (XBUFFER (ow->buffer))),
3526 MARK_WINDOWS_CHANGED (ow);
3529 /* now select the window's frame */
3530 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3532 select_frame_1 (WINDOW_FRAME (w));
3534 /* also select the window's buffer */
3535 if (NILP (norecord))
3536 Frecord_buffer (w->buffer);
3537 Fset_buffer (w->buffer);
3539 /* Go to the point recorded in the window.
3540 This is important when the buffer is in more
3541 than one window. It also matters when
3542 redisplay_window has altered point after scrolling,
3543 because it makes the change only in the window. */
3545 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3546 if (new_point < BUF_BEGV (current_buffer))
3547 new_point = BUF_BEGV (current_buffer);
3548 else if (new_point > BUF_ZV (current_buffer))
3549 new_point = BUF_ZV (current_buffer);
3551 BUF_SET_PT (current_buffer, new_point);
3554 MARK_WINDOWS_CHANGED (w);
3560 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3561 Lisp_Object override_frame)
3563 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3567 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3569 /* This function can GC */
3572 struct buffer *b = XBUFFER (buf);
3574 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3575 widen_buffer (b, 0);
3576 BUF_SET_PT (b, BUF_BEG (b));
3578 if (!NILP (Vtemp_buffer_show_function))
3579 call1 (Vtemp_buffer_show_function, buf);
3582 window = display_buffer (buf, Qnil, same_frame);
3584 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3585 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3587 Vminibuffer_scroll_window = window;
3588 w = XWINDOW (window);
3590 w->modeline_hscroll = 0;
3591 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3592 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3593 set_marker_restricted (w->sb_point, make_int (1), buf);
3595 /* Run temp-buffer-show-hook, with the chosen window selected. */
3596 if (!preparing_for_armageddon)
3599 tem = Fboundp (Qtemp_buffer_show_hook);
3602 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3605 int count = specpdl_depth ();
3607 /* Select the window that was chosen, for running
3609 record_unwind_protect (save_window_excursion_unwind,
3610 Fcurrent_window_configuration (Qnil));
3612 Fselect_window (window, Qnil);
3613 run_hook (Qtemp_buffer_show_hook);
3614 unbind_to (count, Qnil);
3622 make_dummy_parent (Lisp_Object window)
3625 struct window *o = XWINDOW (window);
3626 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3628 XSETWINDOW (new, p);
3629 copy_lcrecord (p, o);
3631 /* Don't copy the pointers to the line start cache or the face
3633 p->line_start_cache = Dynarr_new (line_start_cache);
3634 p->face_cachels = Dynarr_new (face_cachel);
3635 p->glyph_cachels = Dynarr_new (glyph_cachel);
3636 p->subwindow_instance_cache =
3637 make_image_instance_cache_hash_table ();
3639 /* Put new into window structure in place of window */
3640 replace_window (window, new);
3648 p->start[CURRENT_DISP] = Qnil;
3649 p->start[DESIRED_DISP] = Qnil;
3650 p->start[CMOTION_DISP] = Qnil;
3651 p->pointm[CURRENT_DISP] = Qnil;
3652 p->pointm[DESIRED_DISP] = Qnil;
3653 p->pointm[CMOTION_DISP] = Qnil;
3658 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3659 Split WINDOW, putting SIZE lines in the first of the pair.
3660 WINDOW defaults to the selected one and SIZE to half its size.
3661 If optional third arg HORFLAG is non-nil, split side by side and put
3662 SIZE columns in the first of the pair. The newly created window is
3665 (window, size, horflag))
3668 struct window *o, *p;
3674 window = Fselected_window (Qnil);
3676 CHECK_LIVE_WINDOW (window);
3678 o = XWINDOW (window);
3679 f = XFRAME (WINDOW_FRAME (o));
3683 if (!NILP (horflag))
3684 /* In the new scheme, we are symmetric with respect to separators
3685 so there is no need to do weird things here. */
3687 psize = (WINDOW_WIDTH (o) + window_divider_width (o)) >> 1;
3688 csize = window_pixel_width_to_char_width (o, psize, 0);
3692 psize = WINDOW_HEIGHT (o) >> 1;
3693 csize = window_pixel_height_to_char_height (o, psize, 1);
3699 csize = XINT (size);
3700 if (!NILP (horflag))
3701 psize = window_char_width_to_pixel_width (o, csize, 0);
3703 psize = window_char_height_to_pixel_height (o, csize, 1);
3706 if (MINI_WINDOW_P (o))
3707 error ("Attempt to split minibuffer window");
3708 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3709 error ("Attempt to split unsplittable frame");
3711 check_min_window_sizes ();
3715 if (csize < window_min_height)
3716 error ("Window height %d too small (after splitting)", csize);
3717 if (csize + window_min_height > window_char_height (o, 1))
3718 error ("Window height %d too small (after splitting)",
3719 window_char_height (o, 1) - csize);
3720 if (NILP (o->parent)
3721 || NILP (XWINDOW (o->parent)->vchild))
3723 make_dummy_parent (window);
3725 /* #### I can't understand why you have to reset face
3726 cachels here. This can cause crash so let's disable it
3727 and see the difference. See redisplay-tests.el --yh */
3728 reset_face_cachels (XWINDOW (window));
3731 XWINDOW (new)->vchild = window;
3732 XFRAME (o->frame)->mirror_dirty = 1;
3737 if (csize < window_min_width)
3738 error ("Window width %d too small (after splitting)", csize);
3739 if (csize + window_min_width > window_char_width (o, 0))
3740 error ("Window width %d too small (after splitting)",
3741 window_char_width (o, 0) - csize);
3742 if (NILP (o->parent)
3743 || NILP (XWINDOW (o->parent)->hchild))
3745 make_dummy_parent (window);
3747 /* #### See above. */
3748 reset_face_cachels (XWINDOW (window));
3751 XWINDOW (new)->hchild = window;
3752 XFRAME (o->frame)->mirror_dirty = 1;
3756 /* Now we know that window's parent is a vertical combination
3757 if we are dividing vertically, or a horizontal combination
3758 if we are making side-by-side windows */
3760 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3761 new = allocate_window ();
3764 p->frame = o->frame;
3766 if (!NILP (p->next))
3767 XWINDOW (p->next)->prev = new;
3770 p->parent = o->parent;
3773 reset_face_cachels (p);
3774 reset_glyph_cachels (p);
3777 /* Apportion the available frame space among the two new windows */
3779 if (!NILP (horflag))
3781 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3782 WINDOW_TOP (p) = WINDOW_TOP (o);
3783 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3784 WINDOW_WIDTH (o) = psize;
3785 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3789 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3790 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3791 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3792 WINDOW_HEIGHT (o) = psize;
3793 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3796 XFRAME (p->frame)->mirror_dirty = 1;
3797 /* do this last (after the window is completely initialized and
3798 the mirror-dirty flag is set) so that specifier recomputation
3799 caused as a result of this will work properly and not abort. */
3800 Fset_window_buffer (new, o->buffer, Qt);
3805 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3806 Make the selected window COUNT lines taller.
3807 From program, optional second arg HORIZONTALP non-nil means grow
3808 sideways COUNT columns, and optional third arg WINDOW specifies the
3809 window to change instead of the selected window.
3811 (count, horizontalp, window))
3814 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0);
3818 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3819 Make the selected window COUNT pixels taller.
3820 From program, optional second arg HORIZONTALP non-nil means grow
3821 sideways COUNT pixels, and optional third arg WINDOW specifies the
3822 window to change instead of the selected window.
3824 (count, horizontalp, window))
3827 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1);
3831 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3832 Make the selected window COUNT lines shorter.
3833 From program, optional second arg HORIZONTALP non-nil means shrink
3834 sideways COUNT columns, and optional third arg WINDOW specifies the
3835 window to change instead of the selected window.
3837 (count, horizontalp, window))
3840 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0);
3844 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3845 Make the selected window COUNT pixels smaller.
3846 From program, optional second arg HORIZONTALP non-nil means shrink
3847 sideways COUNT pixels, and optional third arg WINDOW specifies the
3848 window to change instead of the selected window.
3850 (count, horizontalp, window))
3853 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1);
3858 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3859 int include_gutters_p)
3862 int defheight, defwidth;
3866 XSETWINDOW (window, w);
3868 avail_height = (pixel_height -
3869 (include_gutters_p ? 0 :
3870 window_top_window_gutter_height (w) +
3871 window_bottom_window_gutter_height (w)));
3873 default_face_height_and_width (window, &defheight, &defwidth);
3875 char_height = avail_height / defheight;
3877 /* It's the calling function's responsibility to check these values
3878 and make sure they're not out of range.
3880 #### We need to go through the calling functions and actually
3882 return max (0, char_height);
3886 window_char_height_to_pixel_height (struct window *w, int char_height,
3887 int include_gutters_p)
3890 int defheight, defwidth;
3895 XSETWINDOW (window, w);
3897 default_face_height_and_width (window, &defheight, &defwidth);
3899 avail_height = char_height * defheight;
3900 pixel_height = (avail_height +
3901 (include_gutters_p ? 0 :
3902 window_top_window_gutter_height (w) +
3903 window_bottom_window_gutter_height (w)));
3905 /* It's the calling function's responsibility to check these values
3906 and make sure they're not out of range.
3908 #### We need to go through the calling functions and actually
3910 return max (0, pixel_height);
3913 /* Return number of default lines of text can fit in the window W.
3914 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3915 horizontal scrollbar) in the space that is used for the calculation.
3916 This doesn't include space used by the frame gutters.
3919 window_char_height (struct window *w, int include_gutters_p)
3921 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3926 * Return number of lines currently displayed in window w. If
3927 * end-of-buffer is displayed then the area below end-of-buffer is assume
3928 * to be blank lines of default height.
3929 * Does not include the modeline.
3932 window_displayed_height (struct window *w)
3934 struct buffer *b = XBUFFER (w->buffer);
3935 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3937 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3939 : w->window_end_pos[CURRENT_DISP]);
3941 if (!Dynarr_length (dla))
3942 return window_char_height (w, 0);
3944 num_lines = Dynarr_length (dla);
3946 /* #### Document and assert somewhere that w->window_end_pos == -1
3947 indicates that end-of-buffer is being displayed. */
3950 struct display_line *dl = Dynarr_atp (dla, 0);
3951 int ypos1 = dl->ypos + dl->descent;
3952 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3954 int defheight, defwidth;
3956 XSETWINDOW (window, w);
3962 if (Dynarr_length (dla) == 1)
3963 ypos1 = WINDOW_TEXT_TOP (w);
3966 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3967 /* If this line is clipped then we know that there is no
3968 blank room between eob and the modeline. If we are
3969 scrolling on clipped lines just know off the clipped
3971 if (scroll_on_clipped_lines && dl->clip)
3972 return num_lines - 1;
3973 ypos1 = dl->ypos + dl->descent - dl->clip;
3977 default_face_height_and_width (window, &defheight, &defwidth);
3978 /* #### This probably needs to know about the clipping area once a
3979 final definition is decided on. */
3980 num_lines += ((ypos2 - ypos1) / defheight);
3984 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3987 if (scroll_on_clipped_lines
3988 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3996 window_pixel_width (Lisp_Object window)
3998 return WINDOW_WIDTH (XWINDOW (window));
4001 /* Calculate the pixel of a window, optionally including margin space
4002 but no vertical gutters. */
4004 window_pixel_width_to_char_width (struct window *w, int pixel_width,
4005 int include_margins_p)
4009 int defheight, defwidth;
4012 XSETWINDOW (window, w);
4014 avail_width = (pixel_width -
4015 window_left_gutter_width (w, 0) -
4016 window_right_gutter_width (w, 0) -
4017 (include_margins_p ? 0 : window_left_margin_width (w)) -
4018 (include_margins_p ? 0 : window_right_margin_width (w)));
4020 default_face_height_and_width (window, &defheight, &defwidth);
4022 char_width = (avail_width / defwidth);
4024 /* It's the calling function's responsibility to check these values
4025 and make sure they're not out of range.
4027 #### We need to go through the calling functions and actually
4029 return max (0, char_width);
4033 window_char_width_to_pixel_width (struct window *w, int char_width,
4034 int include_margins_p)
4038 int defheight, defwidth;
4041 XSETWINDOW (window, w);
4043 default_face_height_and_width (window, &defheight, &defwidth);
4045 avail_width = char_width * defwidth;
4046 pixel_width = (avail_width +
4047 window_left_window_gutter_width (w, 0) +
4048 window_right_window_gutter_width (w, 0) +
4049 (include_margins_p ? 0 : window_left_margin_width (w)) +
4050 (include_margins_p ? 0 : window_right_margin_width (w)));
4052 /* It's the calling function's responsibility to check these values
4053 and make sure they're not out of range.
4055 #### We need to go through the calling functions and actually
4057 return max (0, pixel_width);
4060 /* This returns the usable space which doesn't include space needed by
4061 scrollbars or divider lines. */
4063 window_char_width (struct window *w, int include_margins_p)
4065 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
4069 #define MINSIZE(w) \
4071 ? window_min_width * defwidth \
4072 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4075 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4077 #define CURSIZE(w) \
4078 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4080 #define CURCHARSIZE(w) \
4081 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4083 #define MINCHARSIZE(window) \
4084 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4085 ? 1 : window_min_height)
4088 window_pixheight (Lisp_Object w)
4090 return window_pixel_height (XWINDOW (w));
4093 /* Unlike set_window_pixheight, this function
4094 also changes the heights of the siblings so as to
4095 keep everything consistent. */
4098 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp,
4101 struct window *win = decode_window (window);
4102 int widthflag = !NILP (horizontalp);
4107 int (*sizefun) (Lisp_Object) = (widthflag
4108 ? window_pixel_width
4109 : window_pixheight);
4110 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4111 ? set_window_pixwidth
4112 : set_window_pixheight);
4114 int defheight, defwidth;
4119 check_min_window_sizes ();
4121 XSETWINDOW (window, win);
4122 f = XFRAME (win->frame);
4123 if (EQ (window, FRAME_ROOT_WINDOW (f)))
4124 error ("Won't change only window");
4126 /* #### This is very likely incorrect and instead the char_to_pixel_
4127 functions should be called. */
4128 default_face_height_and_width (window, &defheight, &defwidth);
4132 w = XWINDOW (window);
4137 error ("No other window to side of this one");
4141 ? !NILP (XWINDOW (parent)->hchild)
4142 : !NILP (XWINDOW (parent)->vchild))
4147 sizep = &CURSIZE (w);
4148 dim = CURCHARSIZE (w);
4150 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4151 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4153 if (MINI_WINDOW_P (XWINDOW (window)))
4155 else if (!NILP (parent))
4157 Fdelete_window (window, Qnil);
4163 delta *= (widthflag ? defwidth : defheight);
4168 maxdelta = ((!NILP (parent))
4169 ? (*sizefun) (parent) - *sizep
4170 : ((!NILP (w->next))
4171 ? (*sizefun) (w->next) - MINSIZE (w->next)
4172 : ((!NILP (w->prev))
4173 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4174 /* This is a frame with only one window,
4175 a minibuffer-only or a minibufferless frame. */
4178 if (delta > maxdelta)
4179 /* This case traps trying to make the minibuffer
4180 the full frame, or make the only window aside from the
4181 minibuffer the full frame. */
4188 /* #### Chuck: is this correct? */
4189 if (*sizep + delta < MINSIZE (window))
4191 Fdelete_window (window);
4197 if (!NILP (w->next) &&
4198 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4200 CURBEG (XWINDOW (w->next)) += delta;
4201 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4202 (*setsizefun) (window, *sizep + delta, 0);
4204 else if (!NILP (w->prev) &&
4205 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4207 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4208 CURBEG (w) -= delta;
4209 (*setsizefun) (window, *sizep + delta, 0);
4214 int opht = (*sizefun) (parent);
4216 /* If trying to grow this window to or beyond size of the parent,
4217 make delta1 so big that, on shrinking back down,
4218 all the siblings end up with less than one line and are deleted. */
4219 if (opht <= *sizep + delta)
4220 delta1 = opht * opht * 2;
4221 /* Otherwise, make delta1 just right so that if we add delta1
4222 lines to this window and to the parent, and then shrink
4223 the parent back to its original size, the new proportional
4224 size of this window will increase by delta. */
4226 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4228 /* Add delta1 lines or columns to this window, and to the parent,
4229 keeping things consistent while not affecting siblings. */
4230 CURSIZE (XWINDOW (parent)) = opht + delta1;
4231 (*setsizefun) (window, *sizep + delta1, 0);
4233 /* Squeeze out delta1 lines or columns from our parent,
4234 shrinking this window and siblings proportionately.
4235 This brings parent back to correct size.
4236 Delta1 was calculated so this makes this window the desired size,
4237 taking it all out of the siblings. */
4238 (*setsizefun) (parent, opht, 0);
4241 SET_LAST_MODIFIED (w, 0);
4242 SET_LAST_FACECHANGE (w);
4243 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4244 /* overkill maybe, but better to be correct */
4245 MARK_FRAME_GUTTERS_CHANGED (f);
4255 /* Scroll contents of window WINDOW up COUNT lines.
4256 If COUNT < (top line height / average line height) then we just adjust
4259 window_scroll (Lisp_Object window, Lisp_Object count, int direction,
4260 Error_behavior errb)
4262 struct window *w = XWINDOW (window);
4263 struct buffer *b = XBUFFER (w->buffer);
4264 int selected = EQ (window, Fselected_window (Qnil));
4266 Lisp_Object point, tem;
4267 display_line_dynarr *dla;
4268 int fheight, fwidth, modeline = 0;
4269 struct display_line* dl;
4272 point = make_int (BUF_PT (b));
4275 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4277 if (pos < BUF_BEGV (b))
4279 else if (pos > BUF_ZV (b))
4282 point = make_int (pos);
4285 /* Always set force_start so that redisplay_window will run
4286 the window-scroll-functions. */
4289 /* #### When the fuck does this happen? I'm so glad that history has
4290 completely documented the behavior of the scrolling functions under
4291 all circumstances. */
4292 tem = Fpos_visible_in_window_p (point, window);
4295 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4297 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4298 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4299 WINDOW_TEXT_TOP_CLIP (w) = 0;
4300 MARK_WINDOWS_CHANGED (w);
4305 if (EQ (count, Qminus))
4309 count = Fprefix_numeric_value (count);
4310 value = XINT (count) * direction;
4313 return; /* someone just made a pointless call */
4317 /* If the user didn't specify how far to scroll then we have to figure it
4318 out by ourselves. */
4319 if (NILP (count) || EQ (count, Qminus))
4321 /* Going forwards is easy. If that is what we are doing then just
4322 set value and the section which handles the user specifying a
4323 positive value will work. */
4326 value = window_displayed_height (w) - next_screen_context_lines;
4327 value = (value < 1 ? 1 : value);
4330 /* Going backwards is hard. We can't use the same loop used if the
4331 user specified a negative value because we care about
4332 next_screen_context_lines. In a variable height world you don't
4333 know how many lines above you can actually be displayed and still
4334 have the context lines appear. So we leave value set to 0 and add
4335 a separate section to deal with this. */
4339 if (direction == 1 && !value)
4344 /* Determine parameters to test for partial line scrolling with. */
4345 dla = window_display_lines (w, CURRENT_DISP);
4347 if (INTP (Vwindow_pixel_scroll_increment))
4348 fheight = XINT (Vwindow_pixel_scroll_increment);
4349 else if (!NILP (Vwindow_pixel_scroll_increment))
4350 default_face_height_and_width (window, &fheight, &fwidth);
4352 if (Dynarr_length (dla) >= 1)
4353 modeline = Dynarr_atp (dla, 0)->modeline;
4355 dl = Dynarr_atp (dla, modeline);
4359 /* Go for partial display line scrolling. This just means bumping
4360 the clip by a reasonable amount and redisplaying, everything else
4361 remains unchanged. */
4362 if (!NILP (Vwindow_pixel_scroll_increment)
4364 Dynarr_length (dla) >= (1 + modeline)
4366 (dl->ascent - dl->top_clip) > fheight * value)
4368 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4369 MARK_WINDOWS_CHANGED (w);
4374 Bufpos startp, old_start;
4376 if (WINDOW_TEXT_TOP_CLIP (w))
4378 WINDOW_TEXT_TOP_CLIP (w) = 0;
4379 MARK_WINDOWS_CHANGED (w);
4382 old_start = marker_position (w->start[CURRENT_DISP]);
4383 startp = vmotion (w, old_start, value, &vtarget);
4385 if (vtarget < value &&
4386 (w->window_end_pos[CURRENT_DISP] == -1
4387 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4389 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4394 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4397 w->start_at_line_beg = beginning_of_line_p (b, startp);
4398 MARK_WINDOWS_CHANGED (w);
4400 if (!point_would_be_visible (w, startp, XINT (point)))
4403 BUF_SET_PT (b, startp);
4405 set_marker_restricted (w->pointm[CURRENT_DISP],
4414 /* Go for partial display line scrolling. This just means bumping
4415 the clip by a reasonable amount and redisplaying, everything else
4416 remains unchanged. */
4417 if (!NILP (Vwindow_pixel_scroll_increment)
4419 Dynarr_length (dla) >= (1 + modeline)
4421 (dl->ascent - dl->top_clip) - fheight * value <
4422 (dl->ascent + dl->descent - dl->clip)
4424 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4426 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4427 MARK_WINDOWS_CHANGED (w);
4432 Bufpos startp, old_start;
4434 if (WINDOW_TEXT_TOP_CLIP (w))
4436 WINDOW_TEXT_TOP_CLIP (w) = 0;
4437 MARK_WINDOWS_CHANGED (w);
4440 old_start = marker_position (w->start[CURRENT_DISP]);
4441 startp = vmotion (w, old_start, value, &vtarget);
4444 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4446 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4451 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4454 w->start_at_line_beg = beginning_of_line_p (b, startp);
4455 MARK_WINDOWS_CHANGED (w);
4457 /* #### Scroll back by less than a line. This code was
4458 originally for scrolling over large pixmaps and it
4459 loses when a line being *exposed* at the top of the
4460 window is bigger than the current one. However, for
4461 pixel based scrolling in general we can guess that
4462 the line we are going to display is probably the same
4463 size as the one we are on. In that instance we can
4464 have a reasonable stab at a suitable top clip. Fixing
4465 this properly is hard (and probably slow) as we would
4466 have to call redisplay to figure out the exposed line
4468 if (!NILP (Vwindow_pixel_scroll_increment)
4469 && Dynarr_length (dla) >= (1 + modeline)
4470 && dl->ascent + fheight * value > 0)
4472 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4475 if (!point_would_be_visible (w, startp, XINT (point)))
4479 if (MINI_WINDOW_P (w))
4482 new_point = start_of_last_line (w, startp);
4485 BUF_SET_PT (b, new_point);
4487 set_marker_restricted (w->pointm[CURRENT_DISP],
4488 make_int (new_point),
4494 else /* value == 0 && direction == -1 */
4496 if (WINDOW_TEXT_TOP_CLIP (w))
4498 WINDOW_TEXT_TOP_CLIP (w) = 0;
4499 MARK_WINDOWS_CHANGED (w);
4501 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4503 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4509 int movement = next_screen_context_lines - 1;
4510 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4511 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4513 start_with_point_on_display_line (w, bottom,
4514 -1 - (movement - vtarget));
4516 if (startp >= old_startp)
4517 startp = vmotion (w, old_startp, -1, NULL);
4519 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4522 w->start_at_line_beg = beginning_of_line_p (b, startp);
4523 MARK_WINDOWS_CHANGED (w);
4525 if (!point_would_be_visible (w, startp, XINT (point)))
4527 Bufpos new_point = start_of_last_line (w, startp);
4530 BUF_SET_PT (b, new_point);
4532 set_marker_restricted (w->pointm[CURRENT_DISP],
4533 make_int (new_point),
4540 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4541 Scroll text of current window up COUNT lines; or near full screen if no arg.
4542 A near full screen is `next-screen-context-lines' less than a full screen.
4543 Negative COUNT means scroll downward.
4544 When calling from a program, supply an integer as argument or nil.
4545 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4546 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4549 The characters that are moved over may be added to the current selection
4550 \(i.e. active region) if the Shift key is held down, a motion key is used
4551 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4552 the documentation for this variable for more details.
4556 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME);
4560 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4561 Scroll text of current window down COUNT lines; or near full screen if no arg.
4562 A near full screen is `next-screen-context-lines' less than a full screen.
4563 Negative COUNT means scroll upward.
4564 When calling from a program, supply a number as argument or nil.
4565 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4566 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4569 The characters that are moved over may be added to the current selection
4570 \(i.e. active region) if the Shift key is held down, a motion key is used
4571 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4572 the documentation for this variable for more details.
4576 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME);
4580 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4581 Return the other window for "other window scroll" commands.
4582 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4583 specifies the window.
4584 If `other-window-scroll-buffer' is non-nil, a window
4585 showing that buffer is used.
4590 Lisp_Object selected_window = Fselected_window (Qnil);
4592 if (MINI_WINDOW_P (XWINDOW (selected_window))
4593 && !NILP (Vminibuffer_scroll_window))
4594 window = Vminibuffer_scroll_window;
4595 /* If buffer is specified, scroll that buffer. */
4596 else if (!NILP (Vother_window_scroll_buffer))
4598 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4600 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4604 /* Nothing specified; look for a neighboring window on the same
4606 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4608 if (EQ (window, selected_window))
4609 /* That didn't get us anywhere; look for a window on another
4612 window = Fnext_window (window, Qnil, Qt, Qnil);
4613 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4614 && ! EQ (window, selected_window));
4617 CHECK_LIVE_WINDOW (window);
4619 if (EQ (window, selected_window))
4620 error ("There is no other window");
4625 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4626 Scroll next window upward COUNT lines; or near full frame if no arg.
4627 The next window is the one below the current one; or the one at the top
4628 if the current one is at the bottom. Negative COUNT means scroll downward.
4629 When calling from a program, supply a number as argument or nil.
4631 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4632 specifies the window to scroll.
4633 If `other-window-scroll-buffer' is non-nil, scroll the window
4634 showing that buffer, popping the buffer up if necessary.
4638 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME);
4642 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4643 Scroll selected window display COUNT columns left.
4644 Default for COUNT is window width minus 2.
4646 The characters that are moved over may be added to the current selection
4647 \(i.e. active region) if the Shift key is held down, a motion key is used
4648 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4649 the documentation for this variable for more details.
4653 Lisp_Object window = Fselected_window (Qnil);
4654 struct window *w = XWINDOW (window);
4655 int n = (NILP (count) ?
4656 window_char_width (w, 0) - 2 :
4657 XINT (Fprefix_numeric_value (count)));
4659 return Fset_window_hscroll (window, make_int (w->hscroll + n));
4662 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4663 Scroll selected window display COUNT columns right.
4664 Default for COUNT is window width minus 2.
4666 The characters that are moved over may be added to the current selection
4667 \(i.e. active region) if the Shift key is held down, a motion key is used
4668 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4669 the documentation for this variable for more details.
4673 Lisp_Object window = Fselected_window (Qnil);
4674 struct window *w = XWINDOW (window);
4675 int n = (NILP (count) ?
4676 window_char_width (w, 0) - 2 :
4677 XINT (Fprefix_numeric_value (count)));
4679 return Fset_window_hscroll (window, make_int (w->hscroll - n));
4682 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4683 Center point in WINDOW. With N, put point on line N.
4684 The desired position of point is always relative to the window.
4685 If WINDOW is nil, the selected window is used.
4689 struct window *w = decode_window (window);
4690 struct buffer *b = XBUFFER (w->buffer);
4691 Bufpos opoint = BUF_PT (b);
4695 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4698 n = Fprefix_numeric_value (n);
4700 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4703 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4705 w->start_at_line_beg = beginning_of_line_p (b, startp);
4707 MARK_WINDOWS_CHANGED (w);
4711 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4712 Position point relative to WINDOW.
4713 With no argument, position text at center of window.
4714 An argument specifies window line; zero means top of window,
4715 negative means relative to bottom of window.
4716 If WINDOW is nil, the selected window is used.
4723 Bufpos start, new_point;
4726 /* Don't use decode_window() because we need the new value of
4729 window = Fselected_window (Qnil);
4731 CHECK_LIVE_WINDOW (window);
4732 w = XWINDOW (window);
4733 b = XBUFFER (w->buffer);
4735 height = window_displayed_height (w);
4736 selected = EQ (window, Fselected_window (w->frame));
4742 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4743 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4745 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4748 BUF_SET_PT (b, new_point);
4750 Fset_window_point (window, make_int (new_point));
4752 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4756 start = marker_position (w->start[CURRENT_DISP]);
4757 if (start < BUF_BEGV (b))
4758 start = BUF_BEGV (b);
4759 else if (start > BUF_ZV (b))
4763 new_point = BUF_PT (b);
4765 new_point = marker_position (w->pointm[CURRENT_DISP]);
4767 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4770 BUF_SET_PT (b, new_point);
4772 Fset_window_point (window, make_int (new_point));
4774 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4777 return make_int (retval);
4781 /* #### Is this going to work right when at eob? */
4782 arg = Fprefix_numeric_value (arg);
4784 XSETINT (arg, XINT (arg) + height);
4787 start = marker_position (w->start[CURRENT_DISP]);
4788 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4791 new_point = BUF_PT (b);
4793 new_point = marker_position (w->pointm[CURRENT_DISP]);
4795 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4798 BUF_SET_PT (b, new_point);
4800 Fset_window_point (window, make_int (new_point));
4802 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4804 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4810 BUF_SET_PT (b, start);
4812 Fset_window_point (window, make_int (start));
4816 return Fvertical_motion (arg, window, Qnil);
4820 new_point = vmotion (XWINDOW (window),
4821 marker_position (w->pointm[CURRENT_DISP]),
4823 Fset_window_point (window, make_int (new_point));
4824 return make_int (vpos);
4830 map_windows_1 (Lisp_Object window,
4831 int (*mapfun) (struct window *w, void *closure),
4834 for (; !NILP (window); window = XWINDOW (window)->next)
4837 struct window *w = XWINDOW (window);
4839 if (!NILP (w->vchild))
4840 retval = map_windows_1 (w->vchild, mapfun, closure);
4841 else if (!NILP (w->hchild))
4842 retval = map_windows_1 (w->hchild, mapfun, closure);
4844 retval = (mapfun) (w, closure);
4853 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4854 invocation of MAPFUN. If any invocation of MAPFUN returns
4855 non-zero, the mapping is halted. Otherwise, map_windows() maps
4856 over all windows in F.
4858 If MAPFUN creates or deletes windows, the behavior is undefined. */
4861 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4865 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4868 Lisp_Object frmcons, devcons, concons;
4870 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4872 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4884 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4887 w->shadow_thickness_changed = 1;
4888 MARK_WINDOWS_CHANGED (w);
4892 vertical_divider_changed_in_window (Lisp_Object specifier,
4896 MARK_WINDOWS_CHANGED (w);
4897 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4900 /* also used in scrollbar.c */
4902 some_window_value_changed (Lisp_Object specifier, struct window *w,
4905 MARK_WINDOWS_CHANGED (w);
4908 #ifdef MEMORY_USAGE_STATS
4914 #ifdef HAVE_SCROLLBARS
4918 int other_redisplay;
4923 compute_window_mirror_usage (struct window_mirror *mir,
4924 struct window_stats *stats,
4925 struct overhead_stats *ovstats)
4929 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4931 #ifdef HAVE_SCROLLBARS
4933 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4936 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4939 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4942 #endif /* HAVE_SCROLLBARS */
4943 stats->other_redisplay +=
4944 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4945 stats->other_redisplay +=
4946 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4950 compute_window_usage (struct window *w, struct window_stats *stats,
4951 struct overhead_stats *ovstats)
4954 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4955 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4956 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4957 stats->line_start +=
4958 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4959 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4962 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4963 Return stats about the memory usage of window WINDOW.
4964 The values returned are in the form of an alist of usage types and byte
4965 counts. The byte counts attempt to encompass all the memory used
4966 by the window (separate from the memory logically associated with a
4967 buffer or frame), including internal structures and any malloc()
4968 overhead associated with them. In practice, the byte counts are
4969 underestimated because certain memory usage is very hard to determine
4970 \(e.g. the amount of memory used inside the Xt library or inside the
4971 X server) and because there is other stuff that might logically
4972 be associated with a window, buffer, or frame (e.g. window configurations,
4973 glyphs) but should not obviously be included in the usage counts.
4975 Multiple slices of the total memory usage may be returned, separated
4976 by a nil. Each slice represents a particular view of the memory, a
4977 particular way of partitioning it into groups. Within a slice, there
4978 is no overlap between the groups of memory, and each slice collectively
4979 represents all the memory concerned.
4983 struct window_stats stats;
4984 struct overhead_stats ovstats;
4985 Lisp_Object val = Qnil;
4987 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4989 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4991 val = acons (Qface_cache, make_int (stats.face), val);
4992 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4993 #ifdef HAVE_SCROLLBARS
4994 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4996 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4997 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4998 val = acons (Qother, make_int (stats.other), val);
4999 val = Fcons (Qnil, val);
5000 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
5001 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
5002 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
5004 return Fnreverse (val);
5007 #endif /* MEMORY_USAGE_STATS */
5010 /************************************************************************/
5011 /* Window configurations */
5012 /************************************************************************/
5014 /* #### This window configuration stuff has had serious bugs lurking in it
5015 for years; it would be a -huge- win if this was reimplemented in lisp.
5018 /* If you add anything to this structure make sure saved_window_equal
5022 Lisp_Object window; /* window */
5023 Lisp_Object buffer; /* buffer */
5024 Lisp_Object start; /* copied marker */
5025 Lisp_Object pointm; /* copied marker */
5026 Lisp_Object sb_point; /* copied marker */
5027 Lisp_Object mark; /* copied marker */
5033 Charcount modeline_hscroll;
5034 int parent_index; /* index into saved_windows */
5035 int prev_index; /* index into saved_windows */
5036 char start_at_line_beg; /* boolean */
5038 #define WINDOW_SLOT_DECLARATION
5039 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5040 #include "winslots.h"
5043 /* If you add anything to this structure make sure window_config_equal
5045 struct window_config
5047 struct lcrecord_header header;
5048 /* int frame_width; No longer needed, JV
5049 int frame_height; */
5051 Lisp_Object selected_frame;
5053 Lisp_Object current_window;
5054 Lisp_Object current_buffer;
5055 Lisp_Object minibuffer_scroll_window;
5056 Lisp_Object root_window;
5057 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5058 /* Record the values of window-min-width and window-min-height
5059 so that window sizes remain consistent with them. */
5060 int min_width, min_height;
5061 unsigned int saved_windows_count;
5062 /* Zero-sized arrays aren't ANSI C */
5063 struct saved_window saved_windows[1];
5066 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5067 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5068 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5069 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5070 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5073 mark_window_config (Lisp_Object obj)
5075 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5077 mark_object (config->current_window);
5078 mark_object (config->current_buffer);
5079 mark_object (config->minibuffer_scroll_window);
5080 mark_object (config->root_window);
5082 for (i = 0; i < config->saved_windows_count; i++)
5084 struct saved_window *s = SAVED_WINDOW_N (config, i);
5085 mark_object (s->window);
5086 mark_object (s->buffer);
5087 mark_object (s->start);
5088 mark_object (s->pointm);
5089 mark_object (s->sb_point);
5090 mark_object (s->mark);
5092 /* #### This looked like this. I do not see why specifier cached
5093 values should not be marked, as such specifiers as toolbars
5094 might have GC-able instances. Freed configs are not marked,
5095 aren't they? -- kkm */
5096 mark_object (s->dedicated);
5098 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5099 #include "winslots.h"
5105 inline static size_t
5106 sizeof_window_config_for_n_windows (unsigned int n)
5108 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (struct window_config,
5109 struct saved_window, saved_windows, n);
5113 sizeof_window_config (const void *h)
5115 const struct window_config *c = (const struct window_config *) h;
5116 return sizeof_window_config_for_n_windows (c->saved_windows_count);
5120 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5122 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5125 error ("printing unreadable object #<window-configuration 0x%x>",
5126 config->header.uid);
5127 write_c_string ("#<window-configuration ", printcharfun);
5128 sprintf (buf, "0x%x>", config->header.uid);
5129 write_c_string (buf, printcharfun);
5132 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
5133 window_configuration,
5135 print_window_config,
5136 0, 0, 0, 0, sizeof_window_config,
5137 struct window_config);
5140 /* Returns a boolean indicating whether the two saved windows are
5143 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
5145 #define WINDOW_SLOT(slot, compare) \
5146 if (!compare (win1->slot, win2->slot)) \
5148 #include "winslots.h"
5151 EQ (win1->window, win2->window) &&
5152 EQ (win1->buffer, win2->buffer) &&
5153 internal_equal (win1->start, win2->start, 0) &&
5154 internal_equal (win1->pointm, win2->pointm, 0) &&
5155 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5156 internal_equal (win1->mark, win2->mark, 0) &&
5157 win1->pixel_left == win2->pixel_left &&
5158 win1->pixel_top == win2->pixel_top &&
5159 win1->pixel_width == win2->pixel_width &&
5160 win1->pixel_height == win2->pixel_height &&
5161 win1->hscroll == win2->hscroll &&
5162 win1->modeline_hscroll == win2->modeline_hscroll &&
5163 win1->parent_index == win2->parent_index &&
5164 win1->prev_index == win2->prev_index &&
5165 win1->start_at_line_beg == win2->start_at_line_beg;
5168 /* Returns a boolean indicating whether the two given configurations
5171 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5173 struct window_config *fig1, *fig2;
5176 /* First check if they are truly the same. */
5177 if (EQ (conf1, conf2))
5180 fig1 = XWINDOW_CONFIGURATION (conf1);
5181 fig2 = XWINDOW_CONFIGURATION (conf2);
5183 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5184 EQ (fig1->current_window, fig2->current_window) &&
5185 EQ (fig1->current_buffer, fig2->current_buffer) &&
5186 EQ (fig1->root_window, fig2->root_window) &&
5187 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5189 fig1->frame_width == fig2->frame_width &&
5190 fig1->frame_height == fig2->frame_height)) */
5193 for (i = 0; i < fig1->saved_windows_count; i++)
5195 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5196 SAVED_WINDOW_N (fig2, i)))
5203 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5204 Return t if OBJECT is a window-configuration object.
5208 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5212 mark_windows_in_use_closure (struct window *w, void *closure)
5214 int mark = *(int *)closure;
5215 w->config_mark = mark;
5220 mark_windows_in_use (struct frame *f, int mark)
5222 map_windows (f, mark_windows_in_use_closure, &mark);
5225 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5227 free_window_configuration (Lisp_Object window_config)
5230 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5232 /* Free all the markers. It's not completely necessary that
5233 we do this (window configs sitting in a free list aren't
5234 marked normally so the markers wouldn't be marked anyway)
5235 but it's more efficient. */
5236 for (i = 0; i < config->saved_windows_count; i++)
5238 struct saved_window *p = SAVED_WINDOW_N (config, i);
5240 if (!NILP (p->pointm))
5242 free_marker (XMARKER (p->pointm));
5245 if (!NILP (p->start))
5247 free_marker (XMARKER (p->start));
5250 if (!NILP (p->sb_point))
5252 free_marker (XMARKER (p->sb_point));
5255 if (!NILP (p->mark))
5257 free_marker (XMARKER (p->mark));
5262 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5263 free_managed_lcrecord (Vwindow_configuration_free_list
5264 [config->saved_windows_count - 1],
5270 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5271 Set the configuration of windows and buffers as specified by CONFIGURATION.
5272 CONFIGURATION must be a value previously returned
5273 by `current-window-configuration' (which see).
5278 struct window_config *config;
5279 struct saved_window *p;
5280 Lisp_Object new_current_buffer;
5284 struct gcpro gcpro1;
5285 Lisp_Object old_window_config;
5286 /* int previous_frame_height;
5287 int previous_frame_width;*/
5288 int previous_pixel_top;
5289 int previous_pixel_height;
5290 int previous_pixel_left;
5291 int previous_pixel_width;
5292 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5293 int real_font_height;
5294 int converted_minibuf_height,target_minibuf_height;
5295 int specpdl_count = specpdl_depth ();
5297 GCPRO1 (configuration);
5299 CHECK_WINDOW_CONFIGURATION (configuration);
5300 config = XWINDOW_CONFIGURATION (configuration);
5302 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5305 /* Do not signal an error here if the frame was deleted. There are
5306 reasonable cases where we could get here with a deleted frame and
5307 just want to do close to nothing instead. */
5309 if (FRAME_LIVE_P (f))
5311 /* restore the frame characteristics */
5313 new_current_buffer = config->current_buffer;
5314 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5315 new_current_buffer = Qnil;
5318 * Assumed precondition: w->config_mark = 0 for all w
5319 * This procedure should ensure this is true by the time it exits
5320 * to ensure the precondition for future calls.
5322 * We use w->config_mark to know whether we're modifying a
5323 * window that is currently visible on the frame (#### we
5324 * should just be able to check whether the window is dead
5325 * or not, but this way is safer?). As we process each
5326 * window, we set its config_mark to 0. At the end, we
5327 * go through all the windows that used to be on the frame,
5328 * set each one's config_mark to 0 (to maintain the
5329 * assumed precondition) and delete each one that's no
5332 * #### Using a window-configuration to keep track of
5333 * the current windows is wasteful. All we need is the
5334 * list of windows, so we could just use a dynarr.
5336 old_window_config = Fcurrent_window_configuration (frame);
5338 /* If the new configuration is already equal to the old, then stop
5339 right here. This saves the work below and it also saves
5340 triggering a full redisplay of this window. This is a huge win
5341 when using the mouse since the mode motion code uses
5342 save-window-excursion extensively but will rarely cause the
5343 configuration to actually change. */
5344 if (window_config_equal (configuration, old_window_config))
5346 free_window_configuration (old_window_config);
5351 /* We can't quit or even check for quit because that may cause
5352 investigation of the frame state, which may crash if the frame is
5353 in an inconsistent state. */
5354 begin_dont_check_for_quit ();
5355 record_unwind_protect (free_window_configuration, old_window_config);
5357 mark_windows_in_use (f, 1);
5358 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5359 /* Force subwindows to be remapped. This is overkill but saves
5360 us having to rely on the redisplay code to unmap any extant
5363 #### It does cause some extra flashing though which we could
5364 possibly avoid. So consider trying to get redisplay to work
5367 Removing the instances from the frame cache is wrong because
5368 an instance is only put in the frame cache when it is
5369 instantiated. So if we do this there is a chance that stuff
5370 will never get put back in the frame cache. */
5371 reset_frame_subwindow_instance_cache (f);
5374 /* JV: This is bogus,
5375 First of all, the units are inconsistent. The frame sizes are measured
5376 in characters but the window sizes are stored in pixels. So if a
5377 font size change happened between saving and restoring, the
5378 frame "sizes" maybe equal but the windows still should be
5379 resized. This is tickled a lot by the new "character size
5380 stays constant" policy in 21.0. It leads to very weird
5381 glitches (and possibly crashes when asserts are tickled).
5383 Just changing the units doesn't help because changing the
5384 toolbar configuration can also change the pixel positions.
5385 Luckily there is a much simpler way of doing this, see below.
5387 previous_frame_width = FRAME_WIDTH (f);
5388 previous_frame_height = FRAME_HEIGHT (f);
5389 /* If the frame has been resized since this window configuration was
5390 made, we change the frame to the size specified in the
5391 configuration, restore the configuration, and then resize it
5392 back. We keep track of the prevailing height in these variables. */
5393 if (config->frame_height != FRAME_HEIGHT (f)
5394 || config->frame_width != FRAME_WIDTH (f))
5395 change_frame_size (f, config->frame_height, config->frame_width, 0);
5398 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5399 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5400 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5401 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5403 /* remember some properties of the minibuffer */
5405 default_face_height_and_width (frame, &real_font_height, 0);
5406 assert(real_font_height > 0);
5408 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5410 previous_minibuf_height
5411 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5412 previous_minibuf_top
5413 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5414 previous_minibuf_width
5415 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5419 previous_minibuf_height = 0;
5420 previous_minibuf_top = 0;
5421 previous_minibuf_width = 0;
5423 converted_minibuf_height =
5424 (previous_minibuf_height % real_font_height) == 0 ?
5425 - (previous_minibuf_height / real_font_height ) : /* lines */
5426 previous_minibuf_height; /* pixels */
5428 /* Temporarily avoid any problems with windows that are smaller
5429 than they are supposed to be. */
5430 window_min_height = 1;
5431 window_min_width = 1;
5433 /* OK, now restore all the windows in the window config.
5434 This may involve "undeleting" windows, since the
5435 windows in the window config may be deleted.
5437 for (k = 0; k < config->saved_windows_count; k++)
5439 p = SAVED_WINDOW_N (config, k);
5440 w = XWINDOW (p->window);
5443 /* The window might be dead. In this case, its redisplay
5444 structures were freed, so we need to reallocate them. */
5445 if (!w->face_cachels)
5447 w->face_cachels = Dynarr_new (face_cachel);
5448 reset_face_cachels (w);
5450 if (!w->glyph_cachels)
5451 w->glyph_cachels = Dynarr_new (glyph_cachel);
5452 if (!w->line_start_cache)
5453 w->line_start_cache = Dynarr_new (line_start_cache);
5454 w->gutter_extent_modiff[0] = 0;
5455 w->gutter_extent_modiff[1] = 0;
5456 w->gutter_extent_modiff[2] = 0;
5457 w->gutter_extent_modiff[3] = 0;
5460 if (p->parent_index >= 0)
5461 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5465 if (p->prev_index >= 0)
5467 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5469 /* This is true for a minibuffer-only frame. */
5470 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5473 XWINDOW (w->prev)->next = p->window;
5478 if (!NILP (w->parent))
5480 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5482 XWINDOW (w->parent)->vchild = p->window;
5483 XWINDOW (w->parent)->hchild = Qnil;
5487 XWINDOW (w->parent)->hchild = p->window;
5488 XWINDOW (w->parent)->vchild = Qnil;
5492 if (!w->config_mark)
5494 /* #### This should be equivalent to the window previously
5495 having been dead. If we're brave, we'll put in an
5496 assertion to this effect. */
5497 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5499 else /* if (!EQ (w->buffer, p->buffer)) */
5501 /* With the new redisplay we let it know that a change has
5502 been made and it will take care of the rest. If we don't
5503 tell it something has possibly changed it could lead to
5504 incorrect display. */
5505 MARK_WINDOWS_CHANGED (w);
5508 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5509 WINDOW_TOP (w) = WINDOW_TOP (p);
5510 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5511 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5512 w->hscroll = p->hscroll;
5513 w->modeline_hscroll = p->modeline_hscroll;
5514 w->line_cache_last_updated = Qzero;
5515 /* When we restore a window's configuration, the identity of
5516 the window hasn't actually changed - so there is no
5517 reason why we shouldn't preserve the instance cache for
5518 it - unless it was originally deleted. This will often
5519 buy us something as we will not have to re-instantiate
5520 all the instances. This is because this is an instance
5521 cache - not a display cache. Preserving the display cache
5522 would definitely be wrong.
5524 We specifically want to do this for tabs, since for some
5525 reason finding a file will cause the configuration to be
5527 if (NILP (w->subwindow_instance_cache))
5528 w->subwindow_instance_cache =
5529 make_image_instance_cache_hash_table ();
5531 SET_LAST_MODIFIED (w, 1);
5532 SET_LAST_FACECHANGE (w);
5535 /* #### Consider making the instance cache a winslot. */
5536 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5537 #include "winslots.h"
5539 /* Reinstall the saved buffer and pointers into it. */
5540 if (NILP (p->buffer))
5541 w->buffer = p->buffer;
5544 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5545 /* If saved buffer is alive, install it. */
5547 w->buffer = p->buffer;
5548 w->start_at_line_beg = p->start_at_line_beg;
5549 set_marker_restricted (w->start[CURRENT_DISP],
5550 Fmarker_position (p->start),
5552 set_marker_restricted (w->pointm[CURRENT_DISP],
5553 Fmarker_position (p->pointm),
5555 set_marker_restricted (w->sb_point,
5556 Fmarker_position (p->sb_point),
5558 Fset_marker (XBUFFER (w->buffer)->mark,
5559 Fmarker_position (p->mark), w->buffer);
5561 /* As documented in Fcurrent_window_configuration, don't
5562 save the location of point in the buffer which was current
5563 when the window configuration was recorded. */
5564 if (!EQ (p->buffer, new_current_buffer) &&
5565 XBUFFER (p->buffer) == current_buffer)
5566 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5568 else if (NILP (w->buffer) ||
5569 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5570 /* Else if window's old buffer is dead too, get a live one. */
5572 /* #### The following line makes me nervous... */
5573 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5574 w->buffer = Fget_buffer_create (QSscratch);
5575 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5576 /* This will set the markers to beginning of visible
5578 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5579 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5581 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5582 w->start_at_line_beg = 1;
5585 /* Keeping window's old buffer; make sure the markers
5588 /* Set window markers at start of visible range. */
5589 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5590 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5592 if (XMARKER (w->sb_point)->buffer == 0)
5593 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5594 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5595 set_marker_restricted (w->pointm[CURRENT_DISP],
5597 (BUF_PT (XBUFFER (w->buffer))),
5599 w->start_at_line_beg = 1;
5604 FRAME_ROOT_WINDOW (f) = config->root_window;
5605 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5606 then calls do_switch_frame() below to select the frame that was
5607 recorded in the window config as being selected.
5609 Instead, we don't ever change the selected frame, and either
5610 call Fselect_window() below if the window config's frame is
5611 currently selected, or just set the selected window of the
5612 window config's frame. */
5615 /* Set the frame height to the value it had before this function. */
5616 if (previous_frame_height != FRAME_HEIGHT (f)
5617 || previous_frame_width != FRAME_WIDTH (f))
5618 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5620 /* We just reset the size and position of the minibuffer, to its old
5621 value, which needn't be valid. So we do some magic to see which value
5622 to actually take. Then we set it.
5625 We take the old value if is in the same units but differs from the
5628 #### Now we get more cases correct then ever before, but
5629 are we treating all? For instance what if the frames minibuf window
5630 is no longer the same one?
5632 target_minibuf_height = previous_minibuf_height;
5633 if (converted_minibuf_height &&
5634 (converted_minibuf_height * config->minibuf_height) > 0 &&
5635 (converted_minibuf_height != config->minibuf_height))
5637 target_minibuf_height = config->minibuf_height < 0 ?
5638 - (config->minibuf_height * real_font_height) :
5639 config->minibuf_height;
5640 target_minibuf_height =
5641 max(target_minibuf_height,real_font_height);
5643 if (previous_minibuf_height)
5645 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5646 = previous_minibuf_top -
5647 (target_minibuf_height - previous_minibuf_height);
5648 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5649 target_minibuf_height, 0);
5650 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5651 previous_minibuf_width, 0);
5654 /* This is a better way to deal with frame resizing, etc.
5655 What we _actually_ want is for the old (just restored)
5657 into the place of the new one. So we just do that. Simple! */
5658 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5659 /* Note that this function also updates the subwindow
5661 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5662 previous_pixel_height -
5663 (target_minibuf_height - previous_minibuf_height), 0);
5664 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5665 /* Note that this function also updates the subwindow
5667 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5669 /* If restoring in the current frame make the window current,
5670 otherwise just update the frame selected_window slot to be
5671 the restored current_window. */
5672 if (f == selected_frame ())
5675 /* When using `pop-window-configuration', often the minibuffer
5676 ends up as the selected window even though it's not active ...
5677 I really don't know the cause of this, but it should never
5678 happen. This kludge should fix it.
5680 #### Find out why this is really going wrong. */
5681 if (!minibuf_level &&
5682 MINI_WINDOW_P (XWINDOW (config->current_window)))
5683 window_to_select = Fnext_window (config->current_window,
5686 window_to_select = config->current_window;
5688 /* Do this last so that buffer stacking is calculated
5690 Fselect_window (config->current_window, Qnil);
5692 if (!NILP (new_current_buffer))
5694 Fset_buffer (new_current_buffer);
5695 Frecord_buffer (new_current_buffer);
5699 Fset_buffer (XWINDOW (config->current_window)->buffer);
5700 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5704 set_frame_selected_window (f, config->current_window);
5707 old_window_config = Qnil; /* Warning suppression */
5709 /* Restore the minimum heights recorded in the configuration. */
5710 window_min_height = config->min_height;
5711 window_min_width = config->min_width;
5714 /* see above comment */
5715 /* Fselect_window will have made f the selected frame, so we
5716 reselect the proper frame here. Fhandle_switch_frame will change the
5717 selected window too, but that doesn't make the call to
5718 Fselect_window above totally superfluous; it still sets f's
5720 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5721 do_switch_frame (config->selected_frame, Qnil, 0);
5724 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5726 if (FRAME_LIVE_P (f))
5728 /* Do this before calling recompute_all_cached_specifiers_in_window()
5729 so that things like redisplay_redraw_cursor() won't abort due
5730 to no window mirror present. */
5731 f->mirror_dirty = 1;
5733 config = XWINDOW_CONFIGURATION (old_window_config);
5734 for (k = 0; k < config->saved_windows_count; k++)
5736 p = SAVED_WINDOW_N (config, k);
5737 w = XWINDOW (p->window);
5738 /* Remember, we set w->config_mark on all currently visible
5739 windows, and reset it on all newly visible windows.
5740 Any windows still marked need to be deleted. */
5743 mark_window_as_deleted (w);
5748 /* We just potentially changed the window's buffer and
5749 potentially turned a dead window into a live one,
5750 so we need to recompute the cached specifier values. */
5751 recompute_all_cached_specifiers_in_window (w);
5756 /* Now restore things, when everything else if OK. */
5758 unbind_to (specpdl_count, Qnil);
5765 /* Mark all subwindows of a window as deleted. The argument
5766 W is actually the subwindow tree of the window in question. */
5769 delete_all_subwindows (struct window *w)
5771 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5772 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5773 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5775 mark_window_as_deleted (w);
5780 count_windows (struct window *window)
5783 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5784 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5785 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5789 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5792 for (j = 0; j < lim; j++)
5794 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5798 return 0; /* suppress compiler warning */
5802 save_window_save (Lisp_Object window, struct window_config *config, int i)
5806 for (; !NILP (window); window = w->next)
5808 struct saved_window *p = SAVED_WINDOW_N (config, i);
5810 w = XWINDOW (window);
5813 p->buffer = w->buffer;
5814 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5815 WINDOW_TOP (p) = WINDOW_TOP (w);
5816 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5817 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5818 p->hscroll = w->hscroll;
5819 p->modeline_hscroll = w->modeline_hscroll;
5821 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5822 #include "winslots.h"
5824 if (!NILP (w->buffer))
5826 /* Save w's value of point in the window configuration.
5827 If w is the selected window, then get the value of point
5828 from the buffer; pointm is garbage in the selected window. */
5829 if (EQ (window, Fselected_window (Qnil)))
5831 p->pointm = noseeum_make_marker ();
5832 Fset_marker (p->pointm,
5833 make_int (BUF_PT (XBUFFER (w->buffer))),
5837 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5839 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5840 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5841 p->start_at_line_beg = w->start_at_line_beg;
5843 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5851 p->start_at_line_beg = 0;
5854 if (NILP (w->parent))
5855 p->parent_index = -1;
5857 p->parent_index = saved_window_index (w->parent, config, i);
5861 p->prev_index = saved_window_index (w->prev, config, i);
5862 if (!NILP (w->vchild))
5863 i = save_window_save (w->vchild, config, i);
5864 if (!NILP (w->hchild))
5865 i = save_window_save (w->hchild, config, i);
5872 /* Added to doc string:
5874 This also records the currently selected frame, and FRAME's focus
5875 redirection (see `redirect-frame-focus').
5880 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5881 Return an object representing the current window configuration of FRAME.
5882 If FRAME is nil or omitted, use the selected frame.
5883 This describes the number of windows, their sizes and current buffers,
5884 and for each window on FRAME the displayed buffer, where display
5885 starts, and the positions of point and mark.
5886 An exception is made for point in the current buffer:
5887 its value is -not- saved.
5892 struct frame *f = decode_frame (frame);
5893 struct window_config *config;
5894 unsigned int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5896 int real_font_height;
5898 if (n_windows <= countof (Vwindow_configuration_free_list))
5899 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5900 (Vwindow_configuration_free_list
5903 /* More than ten windows; just allocate directly */
5904 config = (struct window_config *)
5905 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5906 &lrecord_window_configuration);
5907 XSETWINDOW_CONFIGURATION (result, config);
5909 config->frame_width = FRAME_WIDTH (f);
5910 config->frame_height = FRAME_HEIGHT (f); */
5911 /* #### When using `push-window-configuration', often the minibuffer ends
5912 up as the selected window because functions run as the result of
5913 user interaction e.g. hyper-apropos. It seems to me the sensible
5914 thing to do is not record the minibuffer here.
5916 #### Unfortunately this is a change to previous behaviour, however logical
5917 it may be, so revert for the moment. */
5919 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5920 config->current_window = FRAME_SELECTED_WINDOW (f);
5922 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5924 config->current_window = FRAME_SELECTED_WINDOW (f);
5925 XSETBUFFER (config->current_buffer, current_buffer);
5926 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5927 config->root_window = FRAME_ROOT_WINDOW (f);
5928 config->min_height = window_min_height;
5929 config->min_width = window_min_width;
5930 config->saved_windows_count = n_windows;
5931 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5933 /* save the minibuffer height using the heuristics from
5934 change_frame_size_1 */
5936 XSETFRAME (frame, f); /* frame could have been nil ! */
5937 default_face_height_and_width (frame, &real_font_height, 0);
5938 assert(real_font_height > 0);
5940 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5941 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5944 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5945 - (minibuf_height / real_font_height ) : /* lines */
5946 minibuf_height; /* pixels */
5952 save_window_excursion_unwind (Lisp_Object window_config)
5954 Lisp_Object val = Fset_window_configuration (window_config);
5955 free_window_configuration (window_config);
5959 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5960 Execute body, preserving window sizes and contents.
5961 Restores which buffer appears in which window, where display starts,
5962 as well as the current buffer.
5963 Does not restore the value of point in current buffer.
5967 /* This function can GC */
5969 int speccount = specpdl_depth ();
5971 record_unwind_protect (save_window_excursion_unwind,
5972 Fcurrent_window_configuration (Qnil));
5973 val = Fprogn (args);
5974 return unbind_to (speccount, val);
5977 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5978 Return the horizontal pixel position of POS in window.
5979 Beginning of line is column 0. This is calculated using the redisplay
5980 display tables. If WINDOW is nil, the current window is assumed.
5981 If POS is nil, point is assumed. Note that POS must be visible for
5982 a non-nil result to be returned.
5986 struct window* w = decode_window (window);
5987 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5989 struct display_line *dl = 0;
5990 struct display_block *db = 0;
5991 struct rune* rb = 0;
5992 int y = w->last_point_y[CURRENT_DISP];
5993 int x = w->last_point_x[CURRENT_DISP];
5995 if (MINI_WINDOW_P (w))
5998 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
6004 pos = Fwindow_point (window);
6009 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
6014 for (i = first_line; i < Dynarr_length (dla); i++)
6016 dl = Dynarr_atp (dla, i);
6017 /* find the vertical location first */
6018 if (point >= dl->bufpos && point <= dl->end_bufpos)
6020 db = get_display_block_from_line (dl, TEXT);
6021 for (i = 0; i < Dynarr_length (db->runes); i++)
6023 rb = Dynarr_atp (db->runes, i);
6024 if (point <= rb->bufpos)
6036 /* optimized case */
6037 dl = Dynarr_atp (dla, y);
6038 db = get_display_block_from_line (dl, TEXT);
6040 if (x >= Dynarr_length (db->runes))
6043 rb = Dynarr_atp (db->runes, x);
6046 return make_int (rb->xpos - WINDOW_LEFT (w));
6051 /* This is short and simple in elisp, but... it was written to debug
6052 problems purely on the C side. That is where we need to call it so
6055 debug_print_window (Lisp_Object window, int level)
6058 Lisp_Object child = Fwindow_first_vchild (window);
6061 child = Fwindow_first_hchild (window);
6063 for (i = level; i > 0; i--)
6066 stderr_out ("#<window");
6068 Lisp_Object buffer = XWINDOW (window)->buffer;
6069 if (!NILP (buffer) && BUFFERP (buffer))
6070 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
6072 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
6074 while (!NILP (child))
6076 debug_print_window (child, level + 1);
6077 child = Fwindow_next_child (child);
6081 void debug_print_windows (struct frame *f);
6083 debug_print_windows (struct frame *f)
6085 debug_print_window (f->root_window, 0);
6086 putc ('\n', stderr);
6088 #endif /* DEBUG_XEMACS */
6091 /************************************************************************/
6092 /* initialization */
6093 /************************************************************************/
6096 syms_of_window (void)
6098 INIT_LRECORD_IMPLEMENTATION (window);
6099 INIT_LRECORD_IMPLEMENTATION (window_configuration);
6101 defsymbol (&Qwindowp, "windowp");
6102 defsymbol (&Qwindow_live_p, "window-live-p");
6103 defsymbol (&Qwindow_configurationp, "window-configuration-p");
6104 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6105 defsymbol (&Qdisplay_buffer, "display-buffer");
6107 #ifdef MEMORY_USAGE_STATS
6108 defsymbol (&Qface_cache, "face-cache");
6109 defsymbol (&Qglyph_cache, "glyph-cache");
6110 defsymbol (&Qline_start_cache, "line-start-cache");
6111 #ifdef HAVE_SCROLLBARS
6112 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
6114 defsymbol (&Qother_redisplay, "other-redisplay");
6115 /* Qother in general.c */
6118 DEFSYMBOL (Qtruncate_partial_width_windows);
6120 DEFSUBR (Fselected_window);
6121 DEFSUBR (Flast_nonminibuf_window);
6122 DEFSUBR (Fminibuffer_window);
6123 DEFSUBR (Fwindow_minibuffer_p);
6125 DEFSUBR (Fwindow_live_p);
6126 DEFSUBR (Fwindow_first_hchild);
6127 DEFSUBR (Fwindow_first_vchild);
6128 DEFSUBR (Fwindow_next_child);
6129 DEFSUBR (Fwindow_previous_child);
6130 DEFSUBR (Fwindow_parent);
6131 DEFSUBR (Fwindow_lowest_p);
6132 DEFSUBR (Fwindow_truncated_p);
6133 DEFSUBR (Fwindow_highest_p);
6134 DEFSUBR (Fwindow_leftmost_p);
6135 DEFSUBR (Fwindow_rightmost_p);
6136 DEFSUBR (Fpos_visible_in_window_p);
6137 DEFSUBR (Fwindow_buffer);
6138 DEFSUBR (Fwindow_frame);
6139 DEFSUBR (Fwindow_height);
6140 DEFSUBR (Fwindow_displayed_height);
6141 DEFSUBR (Fwindow_width);
6142 DEFSUBR (Fwindow_full_width);
6143 DEFSUBR (Fwindow_pixel_height);
6144 DEFSUBR (Fwindow_pixel_width);
6145 DEFSUBR (Fwindow_text_area_height);
6146 DEFSUBR (Fwindow_text_area_pixel_height);
6147 DEFSUBR (Fwindow_displayed_text_pixel_height);
6148 DEFSUBR (Fwindow_text_area_pixel_width);
6149 DEFSUBR (Fwindow_hscroll);
6150 DEFSUBR (Fset_window_hscroll);
6151 DEFSUBR (Fmodeline_hscroll);
6152 DEFSUBR (Fset_modeline_hscroll);
6153 #if 0 /* bogus FSF crock */
6154 DEFSUBR (Fwindow_redisplay_end_trigger);
6155 DEFSUBR (Fset_window_redisplay_end_trigger);
6157 DEFSUBR (Fwindow_pixel_edges);
6158 DEFSUBR (Fwindow_text_area_pixel_edges);
6159 DEFSUBR (Fwindow_point);
6160 DEFSUBR (Fwindow_start);
6161 DEFSUBR (Fwindow_end);
6162 DEFSUBR (Fwindow_last_line_visible_height);
6163 DEFSUBR (Fset_window_point);
6164 DEFSUBR (Fset_window_start);
6165 DEFSUBR (Fwindow_dedicated_p);
6166 DEFSUBR (Fset_window_dedicated_p);
6167 DEFSUBR (Fnext_window);
6168 DEFSUBR (Fprevious_window);
6169 DEFSUBR (Fnext_vertical_window);
6170 DEFSUBR (Fother_window);
6171 DEFSUBR (Fget_lru_window);
6172 DEFSUBR (Fget_largest_window);
6173 DEFSUBR (Fget_buffer_window);
6174 DEFSUBR (Fwindow_left_margin_pixel_width);
6175 DEFSUBR (Fwindow_right_margin_pixel_width);
6176 DEFSUBR (Fdelete_other_windows);
6177 DEFSUBR (Fdelete_windows_on);
6178 DEFSUBR (Freplace_buffer_in_windows);
6179 DEFSUBR (Fdelete_window);
6180 DEFSUBR (Fset_window_buffer);
6181 DEFSUBR (Fselect_window);
6182 DEFSUBR (Fsplit_window);
6183 DEFSUBR (Fenlarge_window);
6184 DEFSUBR (Fenlarge_window_pixels);
6185 DEFSUBR (Fshrink_window);
6186 DEFSUBR (Fshrink_window_pixels);
6187 DEFSUBR (Fscroll_up);
6188 DEFSUBR (Fscroll_down);
6189 DEFSUBR (Fscroll_left);
6190 DEFSUBR (Fscroll_right);
6191 DEFSUBR (Fother_window_for_scrolling);
6192 DEFSUBR (Fscroll_other_window);
6193 DEFSUBR (Fcenter_to_window_line);
6194 DEFSUBR (Fmove_to_window_line);
6195 #ifdef MEMORY_USAGE_STATS
6196 DEFSUBR (Fwindow_memory_usage);
6198 DEFSUBR (Fwindow_configuration_p);
6199 DEFSUBR (Fset_window_configuration);
6200 DEFSUBR (Fcurrent_window_configuration);
6201 DEFSUBR (Fsave_window_excursion);
6202 DEFSUBR (Fcurrent_pixel_column);
6206 reinit_vars_of_window (void)
6209 /* Make sure all windows get marked */
6210 minibuf_window = Qnil;
6211 staticpro_nodump (&minibuf_window);
6213 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6215 Vwindow_configuration_free_list[i] =
6216 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6217 &lrecord_window_configuration);
6218 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6223 vars_of_window (void)
6225 reinit_vars_of_window ();
6227 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6228 *Non-nil means to scroll if point lands on a line which is clipped.
6230 scroll_on_clipped_lines = 1;
6232 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6233 See `temp-buffer-show-function'.
6235 Vtemp_buffer_show_hook = Qnil;
6237 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6238 Non-nil means call as function to display a help buffer.
6239 The function is called with one argument, the buffer to be displayed.
6240 Used by `with-output-to-temp-buffer'.
6241 If this function is used, then it must do the entire job of showing
6242 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6243 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6245 Vtemp_buffer_show_function = Qnil;
6247 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6248 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6250 Vminibuffer_scroll_window = Qnil;
6252 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6253 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6255 Vother_window_scroll_buffer = Qnil;
6257 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6258 *Number of pixels to scroll by per requested line.
6259 If nil then normal line scrolling occurs regardless of line height.
6260 If t then scrolling is done in increments equal to the height of the default face.
6262 Vwindow_pixel_scroll_increment = Qt;
6264 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6265 *Number of lines of continuity when scrolling by screenfuls.
6267 next_screen_context_lines = 2;
6269 DEFVAR_INT ("window-min-height", &window_min_height /*
6270 *Delete any window less than this tall (including its modeline).
6272 window_min_height = 4;
6274 DEFVAR_INT ("window-min-width", &window_min_width /*
6275 *Delete any window less than this wide.
6277 window_min_width = 10;
6281 specifier_vars_of_window (void)
6283 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6284 *How thick to draw 3D shadows around modelines.
6285 If this is set to 0, modelines will be the traditional 2D. Sizes above
6286 10 will be accepted but the maximum thickness that will be drawn is 10.
6287 This is a specifier; use `set-specifier' to change it.
6289 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6290 /* The initial value for modeline-shadow-thickness is 2, but if the
6291 user removes all specifications we provide a fallback value of 0,
6292 which is probably what was expected. */
6293 set_specifier_fallback (Vmodeline_shadow_thickness,
6294 list1 (Fcons (Qnil, Qzero)));
6295 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6297 set_specifier_caching (Vmodeline_shadow_thickness,
6298 offsetof (struct window, modeline_shadow_thickness),
6299 modeline_shadow_thickness_changed,
6302 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6303 *Whether the modeline should be displayed.
6304 This is a specifier; use `set-specifier' to change it.
6306 Vhas_modeline_p = Fmake_specifier (Qboolean);
6307 set_specifier_fallback (Vhas_modeline_p,
6308 list1 (Fcons (Qnil, Qt)));
6309 set_specifier_caching (Vhas_modeline_p,
6310 offsetof (struct window, has_modeline_p),
6311 /* #### It's strange that we need a special
6312 flag to indicate that the shadow-thickness
6313 has changed, but not one to indicate that
6314 the modeline has been turned off or on. */
6315 some_window_value_changed,
6318 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6319 &Vvertical_divider_always_visible_p /*
6320 *Should XEmacs always display vertical dividers between windows.
6322 When this is non-nil, vertical dividers are always shown, and are
6323 draggable. When it is nil, vertical dividers are shown only when
6324 there are no scrollbars in between windows, and are not draggable.
6326 This is a specifier; use `set-specifier' to change it.
6328 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6329 set_specifier_fallback (Vvertical_divider_always_visible_p,
6330 list1 (Fcons (Qnil, Qt)));
6331 set_specifier_caching (Vvertical_divider_always_visible_p,
6332 offsetof (struct window,
6333 vertical_divider_always_visible_p),
6334 vertical_divider_changed_in_window,
6337 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6338 *How thick to draw 3D shadows around vertical dividers.
6339 This is a specifier; use `set-specifier' to change it.
6341 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6342 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6343 list1 (Fcons (Qnil, Qzero)));
6344 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6346 set_specifier_caching (Vvertical_divider_shadow_thickness,
6347 offsetof (struct window,
6348 vertical_divider_shadow_thickness),
6349 vertical_divider_changed_in_window,
6351 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6352 *The width of the vertical dividers, not including shadows.
6354 For TTY windows, divider line is always one character wide. When
6355 instance of this specifier is zero in a TTY window, no divider is
6356 drawn at all between windows. When non-zero, a one character wide
6357 divider is displayed.
6359 This is a specifier; use `set-specifier' to change it.
6362 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6364 Lisp_Object fb = Qnil;
6366 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6369 fb = Fcons (Fcons (list1 (Qgtk), make_int (3)), fb);
6371 #ifdef HAVE_X_WINDOWS
6372 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6374 #ifdef HAVE_MS_WINDOWS
6375 /* #### This should be made magic and made to obey system settings */
6376 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6378 set_specifier_fallback (Vvertical_divider_line_width, fb);
6380 set_specifier_caching (Vvertical_divider_line_width,
6381 offsetof (struct window,
6382 vertical_divider_line_width),
6383 vertical_divider_changed_in_window,
6386 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6387 *How much space to leave around the vertical dividers.
6389 In TTY windows, spacing is always zero, and the value of this
6390 specifier is ignored.
6392 This is a specifier; use `set-specifier' to change it.
6394 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6396 Lisp_Object fb = Qnil;
6398 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6400 #ifdef HAVE_X_WINDOWS
6401 /* #### 3D dividers look great on MS Windows with spacing = 0.
6402 Should not the same value be the fallback under X? - kkm */
6403 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6406 fb = Fcons (Fcons (list1 (Qgtk), Qzero), fb);
6408 #ifdef HAVE_MS_WINDOWS
6409 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6411 set_specifier_fallback (Vvertical_divider_spacing, fb);
6413 set_specifier_caching (Vvertical_divider_spacing,
6414 offsetof (struct window, vertical_divider_spacing),
6415 vertical_divider_changed_in_window,