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 mark_window_as_deleted (w);
2114 f->mirror_dirty = 1;
2119 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2120 Return the next window after WINDOW in the canonical ordering of windows.
2121 If omitted, WINDOW defaults to the selected window.
2123 Optional second arg MINIBUF t means count the minibuffer window even
2124 if not active. MINIBUF nil or omitted means count the minibuffer iff
2125 it is active. MINIBUF neither t nor nil means not to count the
2126 minibuffer even if it is active.
2128 Several frames may share a single minibuffer; if the minibuffer
2129 counts, all windows on all frames that share that minibuffer count
2130 too. Therefore, `next-window' can be used to iterate through the
2131 set of windows even when the minibuffer is on another frame. If the
2132 minibuffer does not count, only windows from WINDOW's frame count.
2134 By default, only the windows in the selected frame are considered.
2135 The optional argument WHICH-FRAMES changes this behavior:
2136 WHICH-FRAMES = `visible' means search windows on all visible frames.
2137 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2138 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2139 WHICH-FRAMES = a frame means search only windows on that frame.
2140 Anything else means restrict to the selected frame.
2142 The optional fourth argument WHICH-DEVICES further clarifies on which
2143 devices to search for frames as specified by WHICH-FRAMES. This value
2144 is only meaningful if WHICH-FRAMES is non-nil.
2145 If nil or omitted, search all devices on the selected console.
2146 If a device, only search that device.
2147 If a console, search all devices on that console.
2148 If a device type, search all devices of that type.
2149 If `window-system', search all window-system devices.
2150 Any other non-nil value means search all devices.
2152 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2153 you can use `next-window' to iterate through the entire cycle of
2154 acceptable windows, eventually ending up back at the window you started with.
2155 `previous-window' traverses the same cycle, in the reverse order.
2157 (window, minibuf, which_frames, which_devices))
2160 Lisp_Object start_window;
2163 window = Fselected_window (Qnil);
2165 CHECK_LIVE_WINDOW (window);
2167 start_window = window;
2169 /* minibuf == nil may or may not include minibuffers.
2170 Decide if it does. */
2172 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2173 else if (! EQ (minibuf, Qt))
2175 /* Now `minibuf' is one of:
2176 t => count all minibuffer windows
2177 lambda => count none of them
2178 or a specific minibuffer window (the active one) to count. */
2180 /* which_frames == nil doesn't specify which frames to include. */
2181 if (NILP (which_frames))
2182 which_frames = (! EQ (minibuf, Qlambda)
2183 ? (FRAME_MINIBUF_WINDOW
2186 (XWINDOW (window)))))
2188 else if (EQ (which_frames, Qvisible))
2190 else if (ZEROP (which_frames))
2192 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2193 /* If which_frames is a frame and window arg isn't on that frame, just
2194 return the first window on the frame. */
2195 return frame_first_window (XFRAME (which_frames));
2196 else if (! EQ (which_frames, Qt))
2197 which_frames = Qnil;
2198 /* Now `which_frames' is one of:
2199 t => search all frames
2200 nil => search just the current frame
2201 visible => search just visible frames
2202 0 => search visible and iconified frames
2203 a window => search the frame that window belongs to. */
2205 /* Do this loop at least once, to get the next window, and perhaps
2206 again, if we hit the minibuffer and that is not acceptable. */
2209 /* Find a window that actually has a next one. This loop
2210 climbs up the tree. */
2211 while (tem = XWINDOW (window)->next, NILP (tem))
2212 if (tem = XWINDOW (window)->parent, !NILP (tem))
2214 else /* window must be minibuffer window now */
2216 /* We've reached the end of this frame.
2217 Which other frames are acceptable? */
2218 tem = WINDOW_FRAME (XWINDOW (window));
2220 if (! NILP (which_frames))
2222 Lisp_Object tem1 = tem;
2223 tem = next_frame (tem, which_frames, which_devices);
2225 /* In the case where the minibuffer is active,
2226 and we include its frame as well as the selected one,
2227 next_frame may get stuck in that frame.
2228 If that happens, go back to the selected frame
2229 so we can complete the cycle. */
2231 XSETFRAME (tem, selected_frame ());
2234 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2240 /* If we're in a combination window, find its first child and
2241 recurse on that. Otherwise, we've found the window we want. */
2244 if (!NILP (XWINDOW (window)->hchild))
2245 window = XWINDOW (window)->hchild;
2246 else if (!NILP (XWINDOW (window)->vchild))
2247 window = XWINDOW (window)->vchild;
2251 /* Which windows are acceptable?
2252 Exit the loop and accept this window if
2253 this isn't a minibuffer window,
2254 or we're accepting all minibuffer windows,
2255 or this is the active minibuffer and we are accepting that one, or
2256 we've come all the way around and we're back at the original window. */
2257 while (MINI_WINDOW_P (XWINDOW (window))
2258 && ! EQ (minibuf, Qt)
2259 && ! EQ (minibuf, window)
2260 && ! EQ (window, start_window));
2265 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2266 Return the window preceding WINDOW in the canonical ordering of windows.
2267 If omitted, WINDOW defaults to the selected window.
2269 Optional second arg MINIBUF t means count the minibuffer window even
2270 if not active. MINIBUF nil or omitted means count the minibuffer iff
2271 it is active. MINIBUF neither t nor nil means not to count the
2272 minibuffer even if it is active.
2274 Several frames may share a single minibuffer; if the minibuffer
2275 counts, all windows on all frames that share that minibuffer count
2276 too. Therefore, `previous-window' can be used to iterate through
2277 the set of windows even when the minibuffer is on another frame. If
2278 the minibuffer does not count, only windows from WINDOW's frame count.
2280 By default, only the windows in the selected frame are considered.
2281 The optional argument WHICH-FRAMES changes this behavior:
2282 WHICH-FRAMES = `visible' means search windows on all visible frames.
2283 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2284 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2285 WHICH-FRAMES = a frame means search only windows on that frame.
2286 Anything else means restrict to the selected frame.
2288 The optional fourth argument WHICH-DEVICES further clarifies on which
2289 devices to search for frames as specified by WHICH-FRAMES. This value
2290 is only meaningful if WHICH-FRAMES is non-nil.
2291 If nil or omitted, search all devices on the selected console.
2292 If a device, only search that device.
2293 If a console, search all devices on that console.
2294 If a device type, search all devices of that type.
2295 If `window-system', search all window-system devices.
2296 Any other non-nil value means search all devices.
2298 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES,
2299 you can use `previous-window' to iterate through the entire cycle of
2300 acceptable windows, eventually ending up back at the window you started with.
2301 `next-window' traverses the same cycle, in the reverse order.
2303 (window, minibuf, which_frames, devices))
2306 Lisp_Object start_window;
2309 window = Fselected_window (Qnil);
2311 CHECK_LIVE_WINDOW (window);
2313 start_window = window;
2315 /* minibuf == nil may or may not include minibuffers.
2316 Decide if it does. */
2318 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2319 else if (! EQ (minibuf, Qt))
2321 /* Now `minibuf' is one of:
2322 t => count all minibuffer windows
2323 lambda => count none of them
2324 or a specific minibuffer window (the active one) to count. */
2326 /* which_frames == nil doesn't specify which frames to include.
2327 Decide which frames it includes. */
2328 if (NILP (which_frames))
2329 which_frames = (! EQ (minibuf, Qlambda)
2330 ? (FRAME_MINIBUF_WINDOW
2333 (XWINDOW (window)))))
2335 else if (EQ (which_frames, Qvisible))
2337 else if (ZEROP (which_frames))
2339 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window)))
2340 /* If which_frames is a frame and window arg isn't on that frame, just
2341 return the first window on the frame. */
2342 return frame_first_window (XFRAME (which_frames));
2343 else if (! EQ (which_frames, Qt))
2344 which_frames = Qnil;
2345 /* Now `which_frames' is one of:
2346 t => search all frames
2347 nil => search just the current frame
2348 visible => search just visible frames
2349 0 => search visible and iconified frames
2350 a window => search the frame that window belongs to. */
2352 /* Do this loop at least once, to get the next window, and perhaps
2353 again, if we hit the minibuffer and that is not acceptable. */
2356 /* Find a window that actually has a next one. This loop
2357 climbs up the tree. */
2358 while (tem = XWINDOW (window)->prev, NILP (tem))
2359 if (tem = XWINDOW (window)->parent, !NILP (tem))
2361 else /* window must be minibuffer window now */
2363 /* We have found the top window on the frame.
2364 Which frames are acceptable? */
2365 tem = WINDOW_FRAME (XWINDOW (window));
2367 if (! NILP (which_frames))
2368 /* It's actually important that we use previous_frame here,
2369 rather than next_frame. All the windows acceptable
2370 according to the given parameters should form a ring;
2371 Fnext_window and Fprevious_window should go back and
2372 forth around the ring. If we use next_frame here,
2373 then Fnext_window and Fprevious_window take different
2374 paths through the set of acceptable windows.
2375 window_loop assumes that these `ring' requirement are
2378 Lisp_Object tem1 = tem;
2379 tem = previous_frame (tem, which_frames, devices);
2380 /* In the case where the minibuffer is active,
2381 and we include its frame as well as the selected one,
2382 next_frame may get stuck in that frame.
2383 If that happens, go back to the selected frame
2384 so we can complete the cycle. */
2386 XSETFRAME (tem, selected_frame ());
2389 /* If this frame has a minibuffer, find that window first,
2390 because it is conceptually the last window in that frame. */
2391 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2392 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2394 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2401 /* If we're in a combination window, find its first child and
2402 recurse on that. Otherwise, we've found the window we want. */
2405 if (!NILP (XWINDOW (window)->hchild))
2406 window = XWINDOW (window)->hchild;
2407 else if (!NILP (XWINDOW (window)->vchild))
2408 window = XWINDOW (window)->vchild;
2410 while (tem = XWINDOW (window)->next, !NILP (tem))
2414 /* Which windows are acceptable?
2415 Exit the loop and accept this window if
2416 this isn't a minibuffer window,
2417 or we're accepting all minibuffer windows,
2418 or this is the active minibuffer and we are accepting that one, or
2419 we've come all the way around and we're back at the original window. */
2420 while (MINI_WINDOW_P (XWINDOW (window))
2421 && ! EQ (minibuf, Qt)
2422 && ! EQ (minibuf, window)
2423 && ! EQ (window, start_window));
2428 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2429 Return the next window which is vertically after WINDOW.
2434 struct window *w = decode_window (window);
2435 XSETWINDOW (window, w);
2437 if (MINI_WINDOW_P (XWINDOW (window)))
2440 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2442 if (EQ (window, root))
2445 if (!NILP (XWINDOW (window)->hchild))
2446 window = XWINDOW (window)->hchild;
2447 else if (!NILP (XWINDOW (window)->vchild))
2448 window = XWINDOW (window)->vchild;
2455 if (!NILP (XWINDOW (window)->parent) &&
2456 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2458 if (!NILP (XWINDOW (window)->next))
2459 return XWINDOW (window)->next;
2461 window = XWINDOW (window)->parent;
2464 window = XWINDOW (window)->parent;
2466 while (!EQ (window, root));
2469 if (!NILP (XWINDOW (window)->hchild))
2470 window = XWINDOW (window)->hchild;
2471 else if (!NILP (XWINDOW (window)->vchild))
2472 window = XWINDOW (window)->vchild;
2477 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2478 Select the COUNT'th different window on this frame.
2479 All windows on current frame are arranged in a cyclic order.
2480 This command selects the window COUNT steps away in that order.
2481 A negative COUNT moves in the opposite order.
2483 By default, only the windows in the selected frame are considered.
2484 The optional argument WHICH-FRAMES changes this behavior:
2485 WHICH-FRAMES = `visible' means search windows on all visible frames.
2486 WHICH-FRAMES = 0 means search windows on all visible and iconified frames.
2487 WHICH-FRAMES = t means search windows on all frames including invisible frames.
2488 WHICH-FRAMES = a frame means search only windows on that frame.
2489 Anything else means restrict to the selected frame.
2491 The optional argument WHICH-DEVICES further clarifies on which devices
2492 to search for frames as specified by WHICH-FRAMES. This value is only
2493 meaningful if WHICH-FRAMES is non-nil.
2494 If nil or omitted, search all devices on the selected console.
2495 If a device, only search that device.
2496 If a console, search all devices on that console.
2497 If a device type, search all devices of that type.
2498 If `window-system', search all window-system devices.
2499 Any other non-nil value means search all devices.
2501 (count, which_frames, which_devices))
2507 w = Fselected_window (Qnil);
2512 w = Fnext_window (w, Qnil, which_frames, which_devices);
2517 w = Fprevious_window (w, Qnil, which_frames, which_devices);
2520 Fselect_window (w, Qnil);
2525 /* Look at all windows, performing an operation specified by TYPE
2528 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2529 frame. If FRAMES is a frame, just look at windows on that frame.
2530 If MINI is non-zero, perform the operation on minibuffer windows too.
2536 GET_BUFFER_WINDOW, /* Arg is buffer */
2537 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2538 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2539 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2540 UNDEDICATE_BUFFER, /* Arg is buffer */
2542 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2543 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2547 window_loop (enum window_loop type,
2550 Lisp_Object which_frames,
2552 Lisp_Object which_devices)
2554 /* This function can GC if type == DELETE_BUFFER_WINDOWS */
2556 Lisp_Object best_window = Qnil;
2557 Lisp_Object next_window;
2558 Lisp_Object last_window;
2559 struct frame *frame;
2560 Lisp_Object frame_arg = Qt;
2561 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2562 /* #### I think the change of "precomputing" last_window and next_window
2563 * #### catch the lossage this is meant(?) to punt on...
2566 Lisp_Object devcons, concons;
2568 /* If we're only looping through windows on a particular frame,
2569 FRAME points to that frame. If we're looping through windows
2570 on all frames, FRAME is 0. */
2571 if (FRAMEP (which_frames))
2572 frame = XFRAME (which_frames);
2573 else if (NILP (which_frames))
2574 frame = selected_frame ();
2578 /* FRAME_ARG is Qlambda to stick to one frame,
2579 Qvisible to consider all visible frames,
2582 frame_arg = Qlambda;
2583 else if (ZEROP (which_frames))
2584 frame_arg = which_frames;
2585 else if (EQ (which_frames, Qvisible))
2586 frame_arg = which_frames;
2588 DEVICE_LOOP_NO_BREAK (devcons, concons)
2590 Lisp_Object device = XCAR (devcons);
2591 Lisp_Object the_frame;
2594 XSETFRAME (the_frame, frame);
2596 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2598 if (NILP (the_frame))
2601 if (!device_matches_device_spec (device,
2602 NILP (which_devices) ?
2603 FRAME_CONSOLE (XFRAME (the_frame)) :
2607 /* Pick a window to start with. */
2611 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2613 /* Figure out the last window we're going to mess with. Since
2614 Fnext_window, given the same options, is guaranteed to go in a
2615 ring, we can just use Fprevious_window to find the last one.
2617 We can't just wait until we hit the first window again,
2618 because it might be deleted. */
2620 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, device);
2625 struct window *p = XWINDOW (w);
2627 /* Pick the next window now, since some operations will delete
2628 the current window. */
2629 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
2631 /* #### Still needed ?? */
2632 /* Given the outstanding quality of the rest of this code,
2633 I feel no shame about putting this piece of shit in. */
2634 if (++lose_lose >= 500)
2636 /* Call to abort() added by Darryl Okahata (16 Nov. 2001),
2637 at Ben's request, to catch any remaining bugs.
2639 If you find that XEmacs is aborting here, and you
2640 need to be up and running ASAP, it should be safe to
2641 comment out the following abort(), as long as you
2642 leave the "break;" alone. */
2644 break; /* <--- KEEP THIS HERE! Do not delete! */
2647 /* Note that we do not pay attention here to whether
2648 the frame is visible, since Fnext_window skips non-visible frames
2649 if that is desired, under the control of frame_arg. */
2650 if (! MINI_WINDOW_P (p)
2651 || (mini && minibuf_level > 0))
2654 case GET_BUFFER_WINDOW:
2656 if (XBUFFER (p->buffer) == XBUFFER (obj))
2661 case GET_BUFFER_WINDOW_COUNT:
2663 if (XBUFFER (p->buffer) == XBUFFER (obj))
2668 case GET_LRU_WINDOW:
2670 /* t as arg means consider only full-width windows */
2672 && !window_full_width_p (p))
2674 /* Ignore dedicated windows and minibuffers. */
2675 if (MINI_WINDOW_P (p)
2676 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2678 if (NILP (best_window)
2679 || (XINT (XWINDOW (best_window)->use_time)
2680 > XINT (p->use_time)))
2685 case GET_BUFFER_MRU_WINDOW:
2687 /* #### what about the first check in GET_LRU_WINDOW? */
2688 /* Ignore dedicated windows and minibuffers. */
2689 if (MINI_WINDOW_P (p)
2690 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2693 if (XBUFFER (p->buffer) == XBUFFER (obj))
2695 if (NILP (best_window)
2696 || (XINT (XWINDOW (best_window)->use_time)
2697 < XINT (p->use_time)))
2703 case UNDEDICATE_BUFFER:
2705 if ((XBUFFER (p->buffer) == XBUFFER (obj)))
2706 p->dedicated = Qnil;
2710 case DELETE_OTHER_WINDOWS:
2712 /* Don't delete the last window on a frame; this can
2713 happen when the minibuffer is selected, and would
2714 cause the frame to be deleted. */
2715 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2716 Fdelete_window (w, Qnil);
2720 case DELETE_BUFFER_WINDOWS:
2722 if (EQ (p->buffer, obj))
2724 struct frame *f = XFRAME (WINDOW_FRAME (p));
2726 /* If this window is dedicated, and in a frame
2727 of its own, kill the frame. */
2728 if (EQ (w, FRAME_ROOT_WINDOW (f))
2729 && !NILP (p->dedicated)
2730 && other_visible_frames (f))
2732 /* Skip the other windows on this frame.
2733 There might be one, the minibuffer! */
2734 if (! EQ (w, last_window))
2735 while (f == XFRAME (WINDOW_FRAME
2736 (XWINDOW (next_window))))
2738 /* As we go, check for the end of the
2739 loop. We mustn't start going
2740 around a second time. */
2741 if (EQ (next_window, last_window))
2746 next_window = Fnext_window (next_window,
2750 /* Now we can safely delete the frame. */
2751 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2754 /* If we're deleting the buffer displayed in
2755 the only window on the frame, find a new
2756 buffer to display there. */
2757 if (NILP (p->parent))
2759 Lisp_Object new_buffer;
2760 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2761 if (NILP (new_buffer))
2762 new_buffer = Fget_buffer_create (QSscratch);
2763 Fset_window_buffer (w, new_buffer, Qnil);
2764 if (EQ (w, Fselected_window (Qnil)))
2765 Fset_buffer (p->buffer);
2768 Fdelete_window (w, Qnil);
2773 case GET_LARGEST_WINDOW:
2775 /* Ignore dedicated windows and minibuffers. */
2776 if (MINI_WINDOW_P (p)
2777 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2780 /* write the check as follows to avoid tripping
2781 error_check_window() --ben */
2782 struct window *b = NILP (best_window) ? 0 :
2783 XWINDOW (best_window);
2784 if (NILP (best_window)
2785 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2786 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2796 if (EQ (w, last_window))
2803 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2806 #if 0 /* not currently used */
2809 buffer_window_count (struct buffer *b, struct frame *f)
2811 Lisp_Object buffer, frame;
2813 XSETFRAME (frame, f);
2814 XSETBUFFER (buffer, b);
2816 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2821 buffer_window_mru (struct window *w)
2823 Lisp_Object window =
2824 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2828 else if (XWINDOW (window) == w)
2837 undedicate_windows (Lisp_Object buffer, Lisp_Object frame)
2839 window_loop (UNDEDICATE_BUFFER, buffer, 0, frame, 1, Qnil);
2843 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2844 Return the window least recently selected or used for display.
2846 By default, only the windows in the selected frame are considered.
2847 The optional argument WHICH-FRAMES changes this behavior:
2848 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2849 If WHICH-FRAMES is 0, search all visible and iconified frames.
2850 If WHICH-FRAMES is t, search all frames.
2851 If WHICH-FRAMES is nil, search only the selected frame.
2852 If WHICH-FRAMES is a frame, search only that frame.
2854 The optional argument WHICH-DEVICES further clarifies on which devices
2855 to search for frames as specified by WHICH-FRAMES. This value is only
2856 meaningful if WHICH-FRAMES is non-nil.
2857 If nil or omitted, search all devices on the selected console.
2858 If a device, only search that device.
2859 If a console, search all devices on that console.
2860 If a device type, search all devices of that type.
2861 If `window-system', search all devices on window-system consoles.
2862 Any other non-nil value means search all devices.
2864 (which_frames, which_devices))
2867 /* First try for a non-dedicated window that is full-width */
2868 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices);
2869 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2872 /* Then try for any non-dedicated window */
2873 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices);
2874 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2878 /* FSFmacs never returns a dedicated window here. If we do,
2879 it makes `display-buffer' not work right. #### All of this
2880 shit is so disgusting and awful that it needs to be rethought
2882 /* then try for a dedicated window that is full-width */
2883 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices);
2884 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2887 /* If none of them, then all windows, dedicated or not. */
2888 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
2890 /* At this point we damn well better have found something. */
2891 if (NILP (w)) abort ();
2897 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2898 Return the window largest in area.
2900 By default, only the windows in the selected frame are considered.
2901 The optional argument WHICH-FRAMES changes this behavior:
2902 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2903 If WHICH-FRAMES is 0, search all visible and iconified frames.
2904 If WHICH-FRAMES is t, search all frames.
2905 If WHICH-FRAMES is nil, search only the selected frame.
2906 If WHICH-FRAMES is a frame, search only that frame.
2908 The optional argument WHICH-DEVICES further clarifies on which devices
2909 to search for frames as specified by WHICH-FRAMES. This value is only
2910 meaningful if WHICH-FRAMES is non-nil.
2911 If nil or omitted, search all devices on the selected console.
2912 If a device, only search that device.
2913 If a console, search all devices on that console.
2914 If a device type, search all devices of that type.
2915 If `window-system', search all devices on window-system consoles.
2916 Any other non-nil value means search all devices.
2918 (which_frames, which_devices))
2920 /* Don't search dedicated windows because FSFmacs doesn't.
2921 This stuff is all black magic so don't try to apply common
2923 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2924 which_frames, 0, which_devices);
2927 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2928 Return a window currently displaying BUFFER, or nil if none.
2930 By default, only the windows in the selected frame are considered.
2931 The optional argument WHICH-FRAMES changes this behavior:
2932 If optional argument WHICH-FRAMES is `visible', search all visible frames.
2933 If WHICH-FRAMES is 0, search all visible and iconified frames.
2934 If WHICH-FRAMES is t, search all frames.
2935 If WHICH-FRAMES is nil, search only the selected frame.
2936 If WHICH-FRAMES is a frame, search only that frame.
2938 The optional argument WHICH-DEVICES further clarifies on which devices
2939 to search for frames as specified by WHICH-FRAMES. This value is only
2940 meaningful if WHICH-FRAMES is non-nil.
2941 If nil or omitted, search all devices on the selected console.
2942 If a device, only search that device.
2943 If a console, search all devices on that console.
2944 If a device type, search all devices of that type.
2945 If `window-system', search all devices on window-system consoles.
2946 Any other non-nil value means search all devices.
2948 (buffer, which_frames, which_devices))
2950 buffer = Fget_buffer (buffer);
2951 if (BUFFERP (buffer))
2952 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2953 return window_loop (GET_BUFFER_WINDOW, buffer, 1,
2954 which_frames, 1, which_devices);
2959 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2960 but there is no sensible way to implement those functions, since
2961 you can't in general derive a window from a buffer. */
2963 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2965 Return the width in pixels of the left outside margin of window WINDOW.
2966 If WINDOW is nil, the selected window is assumed.
2970 return make_int (window_left_margin_width (decode_window (window)));
2973 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2975 Return the width in pixels of the right outside margin of window WINDOW.
2976 If WINDOW is nil, the selected window is assumed.
2980 return make_int (window_right_margin_width (decode_window (window)));
2983 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2984 Make WINDOW (or the selected window) fill its frame.
2985 Only the frame WINDOW is on is affected.
2986 This function tries to reduce display jumps
2987 by keeping the text previously visible in WINDOW
2988 in the same place on the frame. Doing this depends on
2989 the value of (window-start WINDOW), so if calling this function
2990 in a program gives strange scrolling, make sure the window-start
2991 value is reasonable when this function is called.
2995 struct window *w = decode_window (window);
2996 struct buffer *b = XBUFFER (w->buffer);
2998 int old_top = WINDOW_TOP (w);
3000 XSETWINDOW (window, w);
3002 if (MINI_WINDOW_P (w) && old_top > 0)
3003 error ("Can't expand minibuffer to full frame");
3005 /* Ignore dedicated windows. */
3006 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
3008 start_pos = marker_position (w->start[CURRENT_DISP]);
3010 /* Try to minimize scrolling, by setting the window start to the
3011 point which will cause the text at the old window start to be at
3012 the same place on the frame. But don't try to do this if the
3013 window start is outside the visible portion (as might happen when
3014 the display is not current, due to typeahead). */
3015 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
3016 && !MINI_WINDOW_P (w))
3018 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
3020 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
3022 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
3024 w->start_at_line_beg = beginning_of_line_p (b, new_start);
3026 /* We need to do this, so that the window-scroll-functions
3034 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
3035 "bDelete windows on (buffer): ", /*
3036 Delete all windows showing BUFFER.
3038 Optional second argument WHICH-FRAMES controls which frames are affected.
3039 If nil or omitted, delete all windows showing BUFFER in any frame.
3040 If t, delete only windows showing BUFFER in the selected frame.
3041 If `visible', delete all windows showing BUFFER in any visible frame.
3042 If a frame, delete only windows showing BUFFER in that frame.
3043 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3044 except that the meanings of nil and t are reversed.
3046 The optional third argument WHICH-DEVICES further clarifies on which
3047 devices to search for frames as specified by WHICH-FRAMES. This value
3048 is only meaningful if WHICH-FRAMES is not t.
3049 If nil or omitted, search only the selected console.
3050 If a device, only search that device.
3051 If a console, search all devices on that console.
3052 If a device type, search all devices of that type.
3053 If `window-system', search all devices on a window system.
3054 Any other non-nil value means search all devices.
3056 (buffer, which_frames, which_devices))
3058 /* This function can GC */
3059 buffer = Fget_buffer (buffer);
3060 CHECK_BUFFER (buffer);
3062 /* WHICH-FRAMES values t and nil mean the opposite of what
3063 window_loop expects. */
3064 if (EQ (which_frames, Qnil))
3066 else if (EQ (which_frames, Qt))
3067 which_frames = Qnil;
3069 /* Ignore dedicated windows. */
3070 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0,
3071 which_frames, 0, which_devices);
3076 list_windows (struct window *w, Lisp_Object value)
3080 if (!NILP (w->hchild))
3081 value = list_windows (XWINDOW (w->hchild), value);
3082 else if (!NILP (w->vchild))
3083 value = list_windows (XWINDOW (w->vchild), value);
3087 XSETWINDOW (window, w);
3088 value = Fcons (window, value);
3092 w = XWINDOW (w->next);
3098 list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec)
3100 Lisp_Object devcons, concons;
3101 Lisp_Object retval = Qnil;
3103 DEVICE_LOOP_NO_BREAK (devcons, concons)
3105 Lisp_Object frame_list, the_window;
3106 Lisp_Object device, tail;
3108 device = XCAR (devcons);
3109 frame_list = DEVICE_FRAME_LIST (XDEVICE (device));
3111 LIST_LOOP (tail, frame_list)
3113 if ((NILP (frame_spec)
3114 && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device))))
3115 || (EQ (frame_spec, Qvisible)
3116 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail))))
3117 || (FRAMEP (frame_spec)
3118 && !EQ (frame_spec, XCAR (tail)))
3119 || (!NILP (frame_spec)
3120 && !device_matches_device_spec (device,
3121 NILP (device_spec) ?
3125 the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail)));
3126 retval = list_windows (XWINDOW (the_window), retval);
3129 return Fnreverse (retval);
3132 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3,
3133 "bReplace buffer in windows: ", /*
3134 Replace BUFFER with some other buffer in all windows showing it.
3136 Optional second argument WHICH-FRAMES controls which frames are affected.
3137 If nil or omitted, all frames are affected.
3138 If t, only the selected frame is affected.
3139 If `visible', all visible frames are affected.
3140 If a frame, only that frame is affected.
3141 Warning: WHICH-FRAMES has the same meaning as with `next-window',
3142 except that the meanings of nil and t are reversed.
3144 The optional third argument WHICH-DEVICES further clarifies on which
3145 devices to search for frames as specified by WHICH-FRAMES. This value
3146 is only meaningful if WHICH-FRAMES is not t.
3147 If nil or omitted, search only the selected console.
3148 If a device, only search that device.
3149 If a console, search all devices on that console.
3150 If a device type, search all devices of that type.
3151 If `window-system', search all devices on a window system.
3152 Any other non-nil value means search all devices.
3154 (buffer, which_frames, which_devices))
3156 /* This function can GC */
3157 Lisp_Object window_list;
3159 struct gcpro gcpro1, gcpro2;
3161 if (EQ (which_frames, Qnil))
3163 else if (EQ (which_frames, Qt))
3164 which_frames = Qnil;
3165 window_list = list_all_windows (which_frames, which_devices);
3167 buffer = Fget_buffer (buffer);
3168 CHECK_BUFFER (buffer);
3170 GCPRO2 (window_list, buffer);
3171 LIST_LOOP (tail, window_list)
3173 Lisp_Object window = XCAR (tail);
3174 if (!MINI_WINDOW_P (XWINDOW (window))
3175 && EQ (XWINDOW (window)->buffer, buffer))
3177 Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil);
3178 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window));
3179 if (NILP (another_buffer))
3180 another_buffer = Fget_buffer_create (QSscratch);
3181 if (!NILP (XWINDOW (window)->dedicated)
3183 FRAME_ROOT_WINDOW (XFRAME (frame)))
3184 && other_visible_frames (XFRAME (frame)))
3186 delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */
3190 Fset_window_buffer (window, another_buffer, Qnil);
3191 if (EQ (window, Fselected_window (Qnil)))
3192 Fset_buffer (XWINDOW (window)->buffer);
3200 /* The smallest acceptable dimensions for a window. Anything smaller
3201 might crash Emacs. */
3202 #define MIN_SAFE_WINDOW_WIDTH (2)
3203 #define MIN_SAFE_WINDOW_HEIGHT (2)
3205 /* Make sure that window_min_height and window_min_width are
3206 not too small; if they are, set them to safe minima. */
3209 check_min_window_sizes (void)
3211 /* Smaller values might permit a crash. */
3212 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
3213 window_min_width = MIN_SAFE_WINDOW_WIDTH;
3214 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3215 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3219 frame_min_height (struct frame *frame)
3221 /* For height, we have to see whether the frame has a minibuffer, and
3222 whether it wants a modeline. */
3223 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3224 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3225 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3228 /* Return non-zero if both frame sizes are less than or equal to
3229 minimal allowed values. ROWS and COLS are in characters */
3231 frame_size_valid_p (struct frame *frame, int rows, int cols)
3233 return (rows >= frame_min_height (frame)
3234 && cols >= MIN_SAFE_WINDOW_WIDTH);
3237 /* Return non-zero if both frame sizes are less than or equal to
3238 minimal allowed values. WIDTH and HEIGHT are in pixels */
3240 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3243 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3244 return frame_size_valid_p (frame, rows, cols);
3247 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3248 minimum allowable size. */
3250 check_frame_size (struct frame *frame, int *rows, int *cols)
3252 int min_height = frame_min_height (frame);
3254 if (*rows < min_height)
3256 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3257 *cols = MIN_SAFE_WINDOW_WIDTH;
3260 /* Normally the window is deleted if it gets too small.
3261 nodelete nonzero means do not do this.
3262 (The caller should check later and do so if appropriate) */
3264 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3267 struct window *w = XWINDOW (window);
3268 struct frame *f = XFRAME (w->frame);
3270 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3271 Lisp_Object child, minor_kid, major_kid;
3274 int defheight, defwidth;
3276 /* #### This is very likely incorrect and instead the char_to_pixel_
3277 functions should be called. */
3278 default_face_height_and_width (window, &defheight, &defwidth);
3279 line_size = (set_height ? defheight : defwidth);
3281 check_min_window_sizes ();
3283 minsize = (set_height ? window_min_height : window_min_width);
3284 minsize *= line_size;
3287 && !TOP_LEVEL_WINDOW_P (w)
3288 && new_pixsize < minsize)
3290 Fdelete_window (window, Qnil);
3294 SET_LAST_MODIFIED (w, 0);
3295 SET_LAST_FACECHANGE (w);
3296 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3299 WINDOW_HEIGHT (w) = new_pixsize;
3300 major_kid = w->vchild;
3301 minor_kid = w->hchild;
3305 WINDOW_WIDTH (w) = new_pixsize;
3306 major_kid = w->hchild;
3307 minor_kid = w->vchild;
3310 if (!NILP (minor_kid))
3312 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3315 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3317 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3319 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3322 else if (!NILP (major_kid))
3324 int last_pos, last_old_pos, pos, old_pos, first;
3325 int pixel_adj_left = new_pixsize - old_pixsize;
3326 int div_val = old_pixsize << 1;
3329 * Previously we bailed out here if there was no size change.
3330 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3331 * toolbar appears or disappears, windows may not change size,
3332 * but their top and left coordinates need to be updated.
3334 * So we don't bail until after the loop below.
3337 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3340 for (child = major_kid; !NILP (child); child = c->next)
3342 c = XWINDOW (child);
3346 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3347 WINDOW_TOP (c) = last_pos;
3351 old_pos = last_old_pos + WINDOW_WIDTH (c);
3352 WINDOW_LEFT (c) = last_pos;
3355 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3356 /* All but the last window should have a height which is
3357 a multiple of the default line height. */
3358 if (!NILP (c->next))
3359 pos = (pos / line_size) * line_size;
3361 /* Avoid confusion: don't delete child if it becomes too small */
3362 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3364 last_pos = pos + first;
3365 last_old_pos = old_pos;
3368 /* Sometimes we may get called with our old size. In that case
3369 we don't need to do anything else. */
3370 if (!pixel_adj_left)
3373 /* Now delete any children that became too small. */
3375 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3378 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3380 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3385 /* Set the height of WINDOW and all its inferiors. */
3387 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3389 set_window_pixsize (window, new_pixheight, nodelete, 1);
3392 /* Recursively set width of WINDOW and its inferiors. */
3394 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3396 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3400 static int window_select_count;
3402 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3403 Make WINDOW display BUFFER as its contents.
3404 BUFFER can be a buffer or buffer name.
3406 With non-nil optional argument NORECORD, do not modify the
3407 global or per-frame buffer ordering.
3409 (window, buffer, norecord))
3412 struct window *w = decode_window (window);
3413 int old_buffer_local_face_property = 0;
3415 buffer = Fget_buffer (buffer);
3416 CHECK_BUFFER (buffer);
3418 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3419 error ("Attempt to display deleted buffer");
3423 error ("Window is deleted");
3425 /* While this seems like a logical thing to do, it causes problems
3426 because of saved window configurations. It is possible for a
3427 buffer to get restored into a window in which it is already being
3428 displayed, but start and point are actually at completely
3429 different locations. So we let this function complete fully and
3430 it will then make sure redisplay correctly updates things.
3432 #### This is a kludge. The correct approach is not to do this
3433 but to fix set-window-configuration. */
3435 else if (EQ (tem, buffer))
3438 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3439 is first being set up. */
3441 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3442 error ("Window is dedicated to buffer %s",
3443 XSTRING_DATA (XBUFFER (tem)->name));
3445 old_buffer_local_face_property =
3446 XBUFFER (w->buffer)->buffer_local_face_property;
3451 w->window_end_pos[CURRENT_DISP] = 0;
3453 w->modeline_hscroll = 0;
3454 Fset_marker (w->pointm[CURRENT_DISP],
3455 make_int (BUF_PT (XBUFFER (buffer))),
3457 set_marker_restricted (w->start[CURRENT_DISP],
3458 make_int (XBUFFER (buffer)->last_window_start),
3460 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3461 /* set start_at_line_beg correctly. GE */
3462 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3463 marker_position (w->start[CURRENT_DISP]));
3464 w->force_start = 0; /* Lucid fix */
3465 SET_LAST_MODIFIED (w, 1);
3466 SET_LAST_FACECHANGE (w);
3467 MARK_WINDOWS_CHANGED (w);
3469 int new_buffer_local_face_property =
3470 XBUFFER (w->buffer)->buffer_local_face_property;
3472 if (new_buffer_local_face_property
3473 || new_buffer_local_face_property != old_buffer_local_face_property)
3474 MARK_WINDOW_FACES_CHANGED (w);
3476 recompute_all_cached_specifiers_in_window (w);
3477 if (EQ (window, Fselected_window (Qnil)))
3479 if (NILP (norecord))
3480 Frecord_buffer (buffer);
3482 Fset_buffer (buffer);
3487 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3488 Select WINDOW. Most editing will apply to WINDOW's buffer.
3489 The main editor command loop selects the buffer of the selected window
3490 before each command.
3492 With non-nil optional argument NORECORD, do not modify the
3493 global or per-frame buffer ordering.
3498 Lisp_Object old_selected_window = Fselected_window (Qnil);
3500 CHECK_LIVE_WINDOW (window);
3501 w = XWINDOW (window);
3503 /* we have already caught dead-window errors */
3504 if (!NILP (w->hchild) || !NILP (w->vchild))
3505 error ("Trying to select non-leaf window");
3507 w->use_time = make_int (++window_select_count);
3509 if (EQ (window, old_selected_window))
3512 /* deselect the old window, if it exists (it might not exist if
3513 the selected device has no frames, which occurs at startup) */
3514 if (!NILP (old_selected_window))
3516 struct window *ow = XWINDOW (old_selected_window);
3518 Fset_marker (ow->pointm[CURRENT_DISP],
3519 make_int (BUF_PT (XBUFFER (ow->buffer))),
3522 MARK_WINDOWS_CHANGED (ow);
3525 /* now select the window's frame */
3526 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3528 select_frame_1 (WINDOW_FRAME (w));
3530 /* also select the window's buffer */
3531 if (NILP (norecord))
3532 Frecord_buffer (w->buffer);
3533 Fset_buffer (w->buffer);
3535 /* Go to the point recorded in the window.
3536 This is important when the buffer is in more
3537 than one window. It also matters when
3538 redisplay_window has altered point after scrolling,
3539 because it makes the change only in the window. */
3541 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3542 if (new_point < BUF_BEGV (current_buffer))
3543 new_point = BUF_BEGV (current_buffer);
3544 else if (new_point > BUF_ZV (current_buffer))
3545 new_point = BUF_ZV (current_buffer);
3547 BUF_SET_PT (current_buffer, new_point);
3550 MARK_WINDOWS_CHANGED (w);
3556 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3557 Lisp_Object override_frame)
3559 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3563 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3565 /* This function can GC */
3568 struct buffer *b = XBUFFER (buf);
3570 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3571 widen_buffer (b, 0);
3572 BUF_SET_PT (b, BUF_BEG (b));
3574 if (!NILP (Vtemp_buffer_show_function))
3575 call1 (Vtemp_buffer_show_function, buf);
3578 window = display_buffer (buf, Qnil, same_frame);
3580 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3581 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3583 Vminibuffer_scroll_window = window;
3584 w = XWINDOW (window);
3586 w->modeline_hscroll = 0;
3587 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3588 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3589 set_marker_restricted (w->sb_point, make_int (1), buf);
3591 /* Run temp-buffer-show-hook, with the chosen window selected. */
3592 if (!preparing_for_armageddon)
3595 tem = Fboundp (Qtemp_buffer_show_hook);
3598 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3601 int count = specpdl_depth ();
3603 /* Select the window that was chosen, for running
3605 record_unwind_protect (save_window_excursion_unwind,
3606 Fcurrent_window_configuration (Qnil));
3608 Fselect_window (window, Qnil);
3609 run_hook (Qtemp_buffer_show_hook);
3610 unbind_to (count, Qnil);
3618 make_dummy_parent (Lisp_Object window)
3621 struct window *o = XWINDOW (window);
3622 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3624 XSETWINDOW (new, p);
3625 copy_lcrecord (p, o);
3627 /* Don't copy the pointers to the line start cache or the face
3629 p->line_start_cache = Dynarr_new (line_start_cache);
3630 p->face_cachels = Dynarr_new (face_cachel);
3631 p->glyph_cachels = Dynarr_new (glyph_cachel);
3632 p->subwindow_instance_cache =
3633 make_image_instance_cache_hash_table ();
3635 /* Put new into window structure in place of window */
3636 replace_window (window, new);
3644 p->start[CURRENT_DISP] = Qnil;
3645 p->start[DESIRED_DISP] = Qnil;
3646 p->start[CMOTION_DISP] = Qnil;
3647 p->pointm[CURRENT_DISP] = Qnil;
3648 p->pointm[DESIRED_DISP] = Qnil;
3649 p->pointm[CMOTION_DISP] = Qnil;
3654 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3655 Split WINDOW, putting SIZE lines in the first of the pair.
3656 WINDOW defaults to the selected one and SIZE to half its size.
3657 If optional third arg HORFLAG is non-nil, split side by side and put
3658 SIZE columns in the first of the pair. The newly created window is
3661 (window, size, horflag))
3664 struct window *o, *p;
3670 window = Fselected_window (Qnil);
3672 CHECK_LIVE_WINDOW (window);
3674 o = XWINDOW (window);
3675 f = XFRAME (WINDOW_FRAME (o));
3679 if (!NILP (horflag))
3680 /* In the new scheme, we are symmetric with respect to separators
3681 so there is no need to do weird things here. */
3683 psize = (WINDOW_WIDTH (o) + window_divider_width (o)) >> 1;
3684 csize = window_pixel_width_to_char_width (o, psize, 0);
3688 psize = WINDOW_HEIGHT (o) >> 1;
3689 csize = window_pixel_height_to_char_height (o, psize, 1);
3695 csize = XINT (size);
3696 if (!NILP (horflag))
3697 psize = window_char_width_to_pixel_width (o, csize, 0);
3699 psize = window_char_height_to_pixel_height (o, csize, 1);
3702 if (MINI_WINDOW_P (o))
3703 error ("Attempt to split minibuffer window");
3704 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3705 error ("Attempt to split unsplittable frame");
3707 check_min_window_sizes ();
3711 if (csize < window_min_height)
3712 error ("Window height %d too small (after splitting)", csize);
3713 if (csize + window_min_height > window_char_height (o, 1))
3714 error ("Window height %d too small (after splitting)",
3715 window_char_height (o, 1) - csize);
3716 if (NILP (o->parent)
3717 || NILP (XWINDOW (o->parent)->vchild))
3719 make_dummy_parent (window);
3721 /* #### I can't understand why you have to reset face
3722 cachels here. This can cause crash so let's disable it
3723 and see the difference. See redisplay-tests.el --yh */
3724 reset_face_cachels (XWINDOW (window));
3727 XWINDOW (new)->vchild = window;
3728 XFRAME (o->frame)->mirror_dirty = 1;
3733 if (csize < window_min_width)
3734 error ("Window width %d too small (after splitting)", csize);
3735 if (csize + window_min_width > window_char_width (o, 0))
3736 error ("Window width %d too small (after splitting)",
3737 window_char_width (o, 0) - csize);
3738 if (NILP (o->parent)
3739 || NILP (XWINDOW (o->parent)->hchild))
3741 make_dummy_parent (window);
3743 /* #### See above. */
3744 reset_face_cachels (XWINDOW (window));
3747 XWINDOW (new)->hchild = window;
3748 XFRAME (o->frame)->mirror_dirty = 1;
3752 /* Now we know that window's parent is a vertical combination
3753 if we are dividing vertically, or a horizontal combination
3754 if we are making side-by-side windows */
3756 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3757 new = allocate_window ();
3760 p->frame = o->frame;
3762 if (!NILP (p->next))
3763 XWINDOW (p->next)->prev = new;
3766 p->parent = o->parent;
3769 reset_face_cachels (p);
3770 reset_glyph_cachels (p);
3773 /* Apportion the available frame space among the two new windows */
3775 if (!NILP (horflag))
3777 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3778 WINDOW_TOP (p) = WINDOW_TOP (o);
3779 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3780 WINDOW_WIDTH (o) = psize;
3781 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3785 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3786 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3787 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3788 WINDOW_HEIGHT (o) = psize;
3789 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3792 XFRAME (p->frame)->mirror_dirty = 1;
3793 /* do this last (after the window is completely initialized and
3794 the mirror-dirty flag is set) so that specifier recomputation
3795 caused as a result of this will work properly and not abort. */
3796 Fset_window_buffer (new, o->buffer, Qt);
3801 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3802 Make the selected window COUNT lines taller.
3803 From program, optional second arg HORIZONTALP non-nil means grow
3804 sideways COUNT columns, and optional third arg WINDOW specifies the
3805 window to change instead of the selected window.
3807 (count, horizontalp, window))
3810 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0);
3814 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3815 Make the selected window COUNT pixels taller.
3816 From program, optional second arg HORIZONTALP non-nil means grow
3817 sideways COUNT pixels, and optional third arg WINDOW specifies the
3818 window to change instead of the selected window.
3820 (count, horizontalp, window))
3823 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1);
3827 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3828 Make the selected window COUNT lines shorter.
3829 From program, optional second arg HORIZONTALP non-nil means shrink
3830 sideways COUNT columns, and optional third arg WINDOW specifies the
3831 window to change instead of the selected window.
3833 (count, horizontalp, window))
3836 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0);
3840 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3841 Make the selected window COUNT pixels smaller.
3842 From program, optional second arg HORIZONTALP non-nil means shrink
3843 sideways COUNT pixels, and optional third arg WINDOW specifies the
3844 window to change instead of the selected window.
3846 (count, horizontalp, window))
3849 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1);
3854 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3855 int include_gutters_p)
3858 int defheight, defwidth;
3862 XSETWINDOW (window, w);
3864 avail_height = (pixel_height -
3865 (include_gutters_p ? 0 :
3866 window_top_window_gutter_height (w) +
3867 window_bottom_window_gutter_height (w)));
3869 default_face_height_and_width (window, &defheight, &defwidth);
3871 char_height = avail_height / defheight;
3873 /* It's the calling function's responsibility to check these values
3874 and make sure they're not out of range.
3876 #### We need to go through the calling functions and actually
3878 return max (0, char_height);
3882 window_char_height_to_pixel_height (struct window *w, int char_height,
3883 int include_gutters_p)
3886 int defheight, defwidth;
3891 XSETWINDOW (window, w);
3893 default_face_height_and_width (window, &defheight, &defwidth);
3895 avail_height = char_height * defheight;
3896 pixel_height = (avail_height +
3897 (include_gutters_p ? 0 :
3898 window_top_window_gutter_height (w) +
3899 window_bottom_window_gutter_height (w)));
3901 /* It's the calling function's responsibility to check these values
3902 and make sure they're not out of range.
3904 #### We need to go through the calling functions and actually
3906 return max (0, pixel_height);
3909 /* Return number of default lines of text can fit in the window W.
3910 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3911 horizontal scrollbar) in the space that is used for the calculation.
3912 This doesn't include space used by the frame gutters.
3915 window_char_height (struct window *w, int include_gutters_p)
3917 return window_pixel_height_to_char_height (w, window_pixel_height (w),
3922 * Return number of lines currently displayed in window w. If
3923 * end-of-buffer is displayed then the area below end-of-buffer is assume
3924 * to be blank lines of default height.
3925 * Does not include the modeline.
3928 window_displayed_height (struct window *w)
3930 struct buffer *b = XBUFFER (w->buffer);
3931 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3933 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3935 : w->window_end_pos[CURRENT_DISP]);
3937 if (!Dynarr_length (dla))
3938 return window_char_height (w, 0);
3940 num_lines = Dynarr_length (dla);
3942 /* #### Document and assert somewhere that w->window_end_pos == -1
3943 indicates that end-of-buffer is being displayed. */
3946 struct display_line *dl = Dynarr_atp (dla, 0);
3947 int ypos1 = dl->ypos + dl->descent;
3948 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3950 int defheight, defwidth;
3952 XSETWINDOW (window, w);
3958 if (Dynarr_length (dla) == 1)
3959 ypos1 = WINDOW_TEXT_TOP (w);
3962 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3963 /* If this line is clipped then we know that there is no
3964 blank room between eob and the modeline. If we are
3965 scrolling on clipped lines just know off the clipped
3967 if (scroll_on_clipped_lines && dl->clip)
3968 return num_lines - 1;
3969 ypos1 = dl->ypos + dl->descent - dl->clip;
3973 default_face_height_and_width (window, &defheight, &defwidth);
3974 /* #### This probably needs to know about the clipping area once a
3975 final definition is decided on. */
3976 num_lines += ((ypos2 - ypos1) / defheight);
3980 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3983 if (scroll_on_clipped_lines
3984 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3992 window_pixel_width (Lisp_Object window)
3994 return WINDOW_WIDTH (XWINDOW (window));
3997 /* Calculate the pixel of a window, optionally including margin space
3998 but no vertical gutters. */
4000 window_pixel_width_to_char_width (struct window *w, int pixel_width,
4001 int include_margins_p)
4005 int defheight, defwidth;
4008 XSETWINDOW (window, w);
4010 avail_width = (pixel_width -
4011 window_left_gutter_width (w, 0) -
4012 window_right_gutter_width (w, 0) -
4013 (include_margins_p ? 0 : window_left_margin_width (w)) -
4014 (include_margins_p ? 0 : window_right_margin_width (w)));
4016 default_face_height_and_width (window, &defheight, &defwidth);
4018 char_width = (avail_width / defwidth);
4020 /* It's the calling function's responsibility to check these values
4021 and make sure they're not out of range.
4023 #### We need to go through the calling functions and actually
4025 return max (0, char_width);
4029 window_char_width_to_pixel_width (struct window *w, int char_width,
4030 int include_margins_p)
4034 int defheight, defwidth;
4037 XSETWINDOW (window, w);
4039 default_face_height_and_width (window, &defheight, &defwidth);
4041 avail_width = char_width * defwidth;
4042 pixel_width = (avail_width +
4043 window_left_window_gutter_width (w, 0) +
4044 window_right_window_gutter_width (w, 0) +
4045 (include_margins_p ? 0 : window_left_margin_width (w)) +
4046 (include_margins_p ? 0 : window_right_margin_width (w)));
4048 /* It's the calling function's responsibility to check these values
4049 and make sure they're not out of range.
4051 #### We need to go through the calling functions and actually
4053 return max (0, pixel_width);
4056 /* This returns the usable space which doesn't include space needed by
4057 scrollbars or divider lines. */
4059 window_char_width (struct window *w, int include_margins_p)
4061 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
4065 #define MINSIZE(w) \
4067 ? window_min_width * defwidth \
4068 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
4071 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
4073 #define CURSIZE(w) \
4074 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
4076 #define CURCHARSIZE(w) \
4077 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
4079 #define MINCHARSIZE(window) \
4080 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
4081 ? 1 : window_min_height)
4084 window_pixheight (Lisp_Object w)
4086 return window_pixel_height (XWINDOW (w));
4089 /* Unlike set_window_pixheight, this function
4090 also changes the heights of the siblings so as to
4091 keep everything consistent. */
4094 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp,
4097 struct window *win = decode_window (window);
4098 int widthflag = !NILP (horizontalp);
4103 int (*sizefun) (Lisp_Object) = (widthflag
4104 ? window_pixel_width
4105 : window_pixheight);
4106 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
4107 ? set_window_pixwidth
4108 : set_window_pixheight);
4110 int defheight, defwidth;
4115 check_min_window_sizes ();
4117 XSETWINDOW (window, win);
4118 f = XFRAME (win->frame);
4119 if (EQ (window, FRAME_ROOT_WINDOW (f)))
4120 error ("Won't change only window");
4122 /* #### This is very likely incorrect and instead the char_to_pixel_
4123 functions should be called. */
4124 default_face_height_and_width (window, &defheight, &defwidth);
4128 w = XWINDOW (window);
4133 error ("No other window to side of this one");
4137 ? !NILP (XWINDOW (parent)->hchild)
4138 : !NILP (XWINDOW (parent)->vchild))
4143 sizep = &CURSIZE (w);
4144 dim = CURCHARSIZE (w);
4146 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
4147 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
4149 if (MINI_WINDOW_P (XWINDOW (window)))
4151 else if (!NILP (parent))
4153 Fdelete_window (window, Qnil);
4159 delta *= (widthflag ? defwidth : defheight);
4164 maxdelta = ((!NILP (parent))
4165 ? (*sizefun) (parent) - *sizep
4166 : ((!NILP (w->next))
4167 ? (*sizefun) (w->next) - MINSIZE (w->next)
4168 : ((!NILP (w->prev))
4169 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
4170 /* This is a frame with only one window,
4171 a minibuffer-only or a minibufferless frame. */
4174 if (delta > maxdelta)
4175 /* This case traps trying to make the minibuffer
4176 the full frame, or make the only window aside from the
4177 minibuffer the full frame. */
4184 /* #### Chuck: is this correct? */
4185 if (*sizep + delta < MINSIZE (window))
4187 Fdelete_window (window);
4193 if (!NILP (w->next) &&
4194 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
4196 CURBEG (XWINDOW (w->next)) += delta;
4197 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
4198 (*setsizefun) (window, *sizep + delta, 0);
4200 else if (!NILP (w->prev) &&
4201 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
4203 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
4204 CURBEG (w) -= delta;
4205 (*setsizefun) (window, *sizep + delta, 0);
4210 int opht = (*sizefun) (parent);
4212 /* If trying to grow this window to or beyond size of the parent,
4213 make delta1 so big that, on shrinking back down,
4214 all the siblings end up with less than one line and are deleted. */
4215 if (opht <= *sizep + delta)
4216 delta1 = opht * opht * 2;
4217 /* Otherwise, make delta1 just right so that if we add delta1
4218 lines to this window and to the parent, and then shrink
4219 the parent back to its original size, the new proportional
4220 size of this window will increase by delta. */
4222 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
4224 /* Add delta1 lines or columns to this window, and to the parent,
4225 keeping things consistent while not affecting siblings. */
4226 CURSIZE (XWINDOW (parent)) = opht + delta1;
4227 (*setsizefun) (window, *sizep + delta1, 0);
4229 /* Squeeze out delta1 lines or columns from our parent,
4230 shrinking this window and siblings proportionately.
4231 This brings parent back to correct size.
4232 Delta1 was calculated so this makes this window the desired size,
4233 taking it all out of the siblings. */
4234 (*setsizefun) (parent, opht, 0);
4237 SET_LAST_MODIFIED (w, 0);
4238 SET_LAST_FACECHANGE (w);
4239 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4240 /* overkill maybe, but better to be correct */
4241 MARK_FRAME_GUTTERS_CHANGED (f);
4251 /* Scroll contents of window WINDOW up COUNT lines.
4252 If COUNT < (top line height / average line height) then we just adjust
4255 window_scroll (Lisp_Object window, Lisp_Object count, int direction,
4256 Error_behavior errb)
4258 struct window *w = XWINDOW (window);
4259 struct buffer *b = XBUFFER (w->buffer);
4260 int selected = EQ (window, Fselected_window (Qnil));
4262 Lisp_Object point, tem;
4263 display_line_dynarr *dla;
4264 int fheight, fwidth, modeline = 0;
4265 struct display_line* dl;
4268 point = make_int (BUF_PT (b));
4271 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4273 if (pos < BUF_BEGV (b))
4275 else if (pos > BUF_ZV (b))
4278 point = make_int (pos);
4281 /* Always set force_start so that redisplay_window will run
4282 the window-scroll-functions. */
4285 /* #### When the fuck does this happen? I'm so glad that history has
4286 completely documented the behavior of the scrolling functions under
4287 all circumstances. */
4288 tem = Fpos_visible_in_window_p (point, window);
4291 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4293 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4294 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4295 WINDOW_TEXT_TOP_CLIP (w) = 0;
4296 MARK_WINDOWS_CHANGED (w);
4301 if (EQ (count, Qminus))
4305 count = Fprefix_numeric_value (count);
4306 value = XINT (count) * direction;
4309 return; /* someone just made a pointless call */
4313 /* If the user didn't specify how far to scroll then we have to figure it
4314 out by ourselves. */
4315 if (NILP (count) || EQ (count, Qminus))
4317 /* Going forwards is easy. If that is what we are doing then just
4318 set value and the section which handles the user specifying a
4319 positive value will work. */
4322 value = window_displayed_height (w) - next_screen_context_lines;
4323 value = (value < 1 ? 1 : value);
4326 /* Going backwards is hard. We can't use the same loop used if the
4327 user specified a negative value because we care about
4328 next_screen_context_lines. In a variable height world you don't
4329 know how many lines above you can actually be displayed and still
4330 have the context lines appear. So we leave value set to 0 and add
4331 a separate section to deal with this. */
4335 if (direction == 1 && !value)
4340 /* Determine parameters to test for partial line scrolling with. */
4341 dla = window_display_lines (w, CURRENT_DISP);
4343 if (INTP (Vwindow_pixel_scroll_increment))
4344 fheight = XINT (Vwindow_pixel_scroll_increment);
4345 else if (!NILP (Vwindow_pixel_scroll_increment))
4346 default_face_height_and_width (window, &fheight, &fwidth);
4348 if (Dynarr_length (dla) >= 1)
4349 modeline = Dynarr_atp (dla, 0)->modeline;
4351 dl = Dynarr_atp (dla, modeline);
4355 /* Go for partial display line scrolling. This just means bumping
4356 the clip by a reasonable amount and redisplaying, everything else
4357 remains unchanged. */
4358 if (!NILP (Vwindow_pixel_scroll_increment)
4360 Dynarr_length (dla) >= (1 + modeline)
4362 (dl->ascent - dl->top_clip) > fheight * value)
4364 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4365 MARK_WINDOWS_CHANGED (w);
4370 Bufpos startp, old_start;
4372 if (WINDOW_TEXT_TOP_CLIP (w))
4374 WINDOW_TEXT_TOP_CLIP (w) = 0;
4375 MARK_WINDOWS_CHANGED (w);
4378 old_start = marker_position (w->start[CURRENT_DISP]);
4379 startp = vmotion (w, old_start, value, &vtarget);
4381 if (vtarget < value &&
4382 (w->window_end_pos[CURRENT_DISP] == -1
4383 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4385 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4390 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4393 w->start_at_line_beg = beginning_of_line_p (b, startp);
4394 MARK_WINDOWS_CHANGED (w);
4396 if (!point_would_be_visible (w, startp, XINT (point)))
4399 BUF_SET_PT (b, startp);
4401 set_marker_restricted (w->pointm[CURRENT_DISP],
4410 /* Go for partial display line scrolling. This just means bumping
4411 the clip by a reasonable amount and redisplaying, everything else
4412 remains unchanged. */
4413 if (!NILP (Vwindow_pixel_scroll_increment)
4415 Dynarr_length (dla) >= (1 + modeline)
4417 (dl->ascent - dl->top_clip) - fheight * value <
4418 (dl->ascent + dl->descent - dl->clip)
4420 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4422 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4423 MARK_WINDOWS_CHANGED (w);
4428 Bufpos startp, old_start;
4430 if (WINDOW_TEXT_TOP_CLIP (w))
4432 WINDOW_TEXT_TOP_CLIP (w) = 0;
4433 MARK_WINDOWS_CHANGED (w);
4436 old_start = marker_position (w->start[CURRENT_DISP]);
4437 startp = vmotion (w, old_start, value, &vtarget);
4440 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4442 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4447 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4450 w->start_at_line_beg = beginning_of_line_p (b, startp);
4451 MARK_WINDOWS_CHANGED (w);
4453 /* #### Scroll back by less than a line. This code was
4454 originally for scrolling over large pixmaps and it
4455 loses when a line being *exposed* at the top of the
4456 window is bigger than the current one. However, for
4457 pixel based scrolling in general we can guess that
4458 the line we are going to display is probably the same
4459 size as the one we are on. In that instance we can
4460 have a reasonable stab at a suitable top clip. Fixing
4461 this properly is hard (and probably slow) as we would
4462 have to call redisplay to figure out the exposed line
4464 if (!NILP (Vwindow_pixel_scroll_increment)
4465 && Dynarr_length (dla) >= (1 + modeline)
4466 && dl->ascent + fheight * value > 0)
4468 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4471 if (!point_would_be_visible (w, startp, XINT (point)))
4475 if (MINI_WINDOW_P (w))
4478 new_point = start_of_last_line (w, startp);
4481 BUF_SET_PT (b, new_point);
4483 set_marker_restricted (w->pointm[CURRENT_DISP],
4484 make_int (new_point),
4490 else /* value == 0 && direction == -1 */
4492 if (WINDOW_TEXT_TOP_CLIP (w))
4494 WINDOW_TEXT_TOP_CLIP (w) = 0;
4495 MARK_WINDOWS_CHANGED (w);
4497 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4499 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4505 int movement = next_screen_context_lines - 1;
4506 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4507 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4509 start_with_point_on_display_line (w, bottom,
4510 -1 - (movement - vtarget));
4512 if (startp >= old_startp)
4513 startp = vmotion (w, old_startp, -1, NULL);
4515 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4518 w->start_at_line_beg = beginning_of_line_p (b, startp);
4519 MARK_WINDOWS_CHANGED (w);
4521 if (!point_would_be_visible (w, startp, XINT (point)))
4523 Bufpos new_point = start_of_last_line (w, startp);
4526 BUF_SET_PT (b, new_point);
4528 set_marker_restricted (w->pointm[CURRENT_DISP],
4529 make_int (new_point),
4536 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4537 Scroll text of current window up COUNT lines; or near full screen if no arg.
4538 A near full screen is `next-screen-context-lines' less than a full screen.
4539 Negative COUNT means scroll downward.
4540 When calling from a program, supply an integer as argument or nil.
4541 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4542 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4545 The characters that are moved over may be added to the current selection
4546 \(i.e. active region) if the Shift key is held down, a motion key is used
4547 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4548 the documentation for this variable for more details.
4552 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME);
4556 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4557 Scroll text of current window down COUNT lines; or near full screen if no arg.
4558 A near full screen is `next-screen-context-lines' less than a full screen.
4559 Negative COUNT means scroll upward.
4560 When calling from a program, supply a number as argument or nil.
4561 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4562 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4565 The characters that are moved over may be added to the current selection
4566 \(i.e. active region) if the Shift key is held down, a motion key is used
4567 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4568 the documentation for this variable for more details.
4572 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME);
4576 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4577 Return the other window for "other window scroll" commands.
4578 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4579 specifies the window.
4580 If `other-window-scroll-buffer' is non-nil, a window
4581 showing that buffer is used.
4586 Lisp_Object selected_window = Fselected_window (Qnil);
4588 if (MINI_WINDOW_P (XWINDOW (selected_window))
4589 && !NILP (Vminibuffer_scroll_window))
4590 window = Vminibuffer_scroll_window;
4591 /* If buffer is specified, scroll that buffer. */
4592 else if (!NILP (Vother_window_scroll_buffer))
4594 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4596 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4600 /* Nothing specified; look for a neighboring window on the same
4602 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4604 if (EQ (window, selected_window))
4605 /* That didn't get us anywhere; look for a window on another
4608 window = Fnext_window (window, Qnil, Qt, Qnil);
4609 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4610 && ! EQ (window, selected_window));
4613 CHECK_LIVE_WINDOW (window);
4615 if (EQ (window, selected_window))
4616 error ("There is no other window");
4621 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4622 Scroll next window upward COUNT lines; or near full frame if no arg.
4623 The next window is the one below the current one; or the one at the top
4624 if the current one is at the bottom. Negative COUNT means scroll downward.
4625 When calling from a program, supply a number as argument or nil.
4627 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4628 specifies the window to scroll.
4629 If `other-window-scroll-buffer' is non-nil, scroll the window
4630 showing that buffer, popping the buffer up if necessary.
4634 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME);
4638 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4639 Scroll selected window display COUNT columns left.
4640 Default for COUNT is window width minus 2.
4642 The characters that are moved over may be added to the current selection
4643 \(i.e. active region) if the Shift key is held down, a motion key is used
4644 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4645 the documentation for this variable for more details.
4649 Lisp_Object window = Fselected_window (Qnil);
4650 struct window *w = XWINDOW (window);
4651 int n = (NILP (count) ?
4652 window_char_width (w, 0) - 2 :
4653 XINT (Fprefix_numeric_value (count)));
4655 return Fset_window_hscroll (window, make_int (w->hscroll + n));
4658 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4659 Scroll selected window display COUNT columns right.
4660 Default for COUNT is window width minus 2.
4662 The characters that are moved over may be added to the current selection
4663 \(i.e. active region) if the Shift key is held down, a motion key is used
4664 to invoke this command, and `shifted-motion-keys-select-region' is t; see
4665 the documentation for this variable for more details.
4669 Lisp_Object window = Fselected_window (Qnil);
4670 struct window *w = XWINDOW (window);
4671 int n = (NILP (count) ?
4672 window_char_width (w, 0) - 2 :
4673 XINT (Fprefix_numeric_value (count)));
4675 return Fset_window_hscroll (window, make_int (w->hscroll - n));
4678 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4679 Center point in WINDOW. With N, put point on line N.
4680 The desired position of point is always relative to the window.
4681 If WINDOW is nil, the selected window is used.
4685 struct window *w = decode_window (window);
4686 struct buffer *b = XBUFFER (w->buffer);
4687 Bufpos opoint = BUF_PT (b);
4691 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4694 n = Fprefix_numeric_value (n);
4696 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4699 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4701 w->start_at_line_beg = beginning_of_line_p (b, startp);
4703 MARK_WINDOWS_CHANGED (w);
4707 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4708 Position point relative to WINDOW.
4709 With no argument, position text at center of window.
4710 An argument specifies window line; zero means top of window,
4711 negative means relative to bottom of window.
4712 If WINDOW is nil, the selected window is used.
4719 Bufpos start, new_point;
4722 /* Don't use decode_window() because we need the new value of
4725 window = Fselected_window (Qnil);
4727 CHECK_LIVE_WINDOW (window);
4728 w = XWINDOW (window);
4729 b = XBUFFER (w->buffer);
4731 height = window_displayed_height (w);
4732 selected = EQ (window, Fselected_window (w->frame));
4738 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4739 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4741 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4744 BUF_SET_PT (b, new_point);
4746 Fset_window_point (window, make_int (new_point));
4748 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4752 start = marker_position (w->start[CURRENT_DISP]);
4753 if (start < BUF_BEGV (b))
4754 start = BUF_BEGV (b);
4755 else if (start > BUF_ZV (b))
4759 new_point = BUF_PT (b);
4761 new_point = marker_position (w->pointm[CURRENT_DISP]);
4763 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4766 BUF_SET_PT (b, new_point);
4768 Fset_window_point (window, make_int (new_point));
4770 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4773 return make_int (retval);
4777 /* #### Is this going to work right when at eob? */
4778 arg = Fprefix_numeric_value (arg);
4780 XSETINT (arg, XINT (arg) + height);
4783 start = marker_position (w->start[CURRENT_DISP]);
4784 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4787 new_point = BUF_PT (b);
4789 new_point = marker_position (w->pointm[CURRENT_DISP]);
4791 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4794 BUF_SET_PT (b, new_point);
4796 Fset_window_point (window, make_int (new_point));
4798 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4800 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4806 BUF_SET_PT (b, start);
4808 Fset_window_point (window, make_int (start));
4812 return Fvertical_motion (arg, window, Qnil);
4816 new_point = vmotion (XWINDOW (window),
4817 marker_position (w->pointm[CURRENT_DISP]),
4819 Fset_window_point (window, make_int (new_point));
4820 return make_int (vpos);
4826 map_windows_1 (Lisp_Object window,
4827 int (*mapfun) (struct window *w, void *closure),
4830 for (; !NILP (window); window = XWINDOW (window)->next)
4833 struct window *w = XWINDOW (window);
4835 if (!NILP (w->vchild))
4836 retval = map_windows_1 (w->vchild, mapfun, closure);
4837 else if (!NILP (w->hchild))
4838 retval = map_windows_1 (w->hchild, mapfun, closure);
4840 retval = (mapfun) (w, closure);
4849 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4850 invocation of MAPFUN. If any invocation of MAPFUN returns
4851 non-zero, the mapping is halted. Otherwise, map_windows() maps
4852 over all windows in F.
4854 If MAPFUN creates or deletes windows, the behavior is undefined. */
4857 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4861 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4864 Lisp_Object frmcons, devcons, concons;
4866 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4868 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4880 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4883 w->shadow_thickness_changed = 1;
4884 MARK_WINDOWS_CHANGED (w);
4888 vertical_divider_changed_in_window (Lisp_Object specifier,
4892 MARK_WINDOWS_CHANGED (w);
4893 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4896 /* also used in scrollbar.c */
4898 some_window_value_changed (Lisp_Object specifier, struct window *w,
4901 MARK_WINDOWS_CHANGED (w);
4904 #ifdef MEMORY_USAGE_STATS
4910 #ifdef HAVE_SCROLLBARS
4914 int other_redisplay;
4919 compute_window_mirror_usage (struct window_mirror *mir,
4920 struct window_stats *stats,
4921 struct overhead_stats *ovstats)
4925 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4927 #ifdef HAVE_SCROLLBARS
4929 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4932 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4935 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4938 #endif /* HAVE_SCROLLBARS */
4939 stats->other_redisplay +=
4940 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4941 stats->other_redisplay +=
4942 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4946 compute_window_usage (struct window *w, struct window_stats *stats,
4947 struct overhead_stats *ovstats)
4950 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4951 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4952 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4953 stats->line_start +=
4954 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4955 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4958 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4959 Return stats about the memory usage of window WINDOW.
4960 The values returned are in the form of an alist of usage types and byte
4961 counts. The byte counts attempt to encompass all the memory used
4962 by the window (separate from the memory logically associated with a
4963 buffer or frame), including internal structures and any malloc()
4964 overhead associated with them. In practice, the byte counts are
4965 underestimated because certain memory usage is very hard to determine
4966 \(e.g. the amount of memory used inside the Xt library or inside the
4967 X server) and because there is other stuff that might logically
4968 be associated with a window, buffer, or frame (e.g. window configurations,
4969 glyphs) but should not obviously be included in the usage counts.
4971 Multiple slices of the total memory usage may be returned, separated
4972 by a nil. Each slice represents a particular view of the memory, a
4973 particular way of partitioning it into groups. Within a slice, there
4974 is no overlap between the groups of memory, and each slice collectively
4975 represents all the memory concerned.
4979 struct window_stats stats;
4980 struct overhead_stats ovstats;
4981 Lisp_Object val = Qnil;
4983 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4985 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4987 val = acons (Qface_cache, make_int (stats.face), val);
4988 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4989 #ifdef HAVE_SCROLLBARS
4990 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4992 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4993 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4994 val = acons (Qother, make_int (stats.other), val);
4995 val = Fcons (Qnil, val);
4996 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4997 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4998 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
5000 return Fnreverse (val);
5003 #endif /* MEMORY_USAGE_STATS */
5006 /************************************************************************/
5007 /* Window configurations */
5008 /************************************************************************/
5010 /* #### This window configuration stuff has had serious bugs lurking in it
5011 for years; it would be a -huge- win if this was reimplemented in lisp.
5014 /* If you add anything to this structure make sure saved_window_equal
5018 Lisp_Object window; /* window */
5019 Lisp_Object buffer; /* buffer */
5020 Lisp_Object start; /* copied marker */
5021 Lisp_Object pointm; /* copied marker */
5022 Lisp_Object sb_point; /* copied marker */
5023 Lisp_Object mark; /* copied marker */
5029 Charcount modeline_hscroll;
5030 int parent_index; /* index into saved_windows */
5031 int prev_index; /* index into saved_windows */
5032 char start_at_line_beg; /* boolean */
5034 #define WINDOW_SLOT_DECLARATION
5035 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
5036 #include "winslots.h"
5039 /* If you add anything to this structure make sure window_config_equal
5041 struct window_config
5043 struct lcrecord_header header;
5044 /* int frame_width; No longer needed, JV
5045 int frame_height; */
5047 Lisp_Object selected_frame;
5049 Lisp_Object current_window;
5050 Lisp_Object current_buffer;
5051 Lisp_Object minibuffer_scroll_window;
5052 Lisp_Object root_window;
5053 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
5054 /* Record the values of window-min-width and window-min-height
5055 so that window sizes remain consistent with them. */
5056 int min_width, min_height;
5057 unsigned int saved_windows_count;
5058 /* Zero-sized arrays aren't ANSI C */
5059 struct saved_window saved_windows[1];
5062 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
5063 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
5064 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
5065 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
5066 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
5069 mark_window_config (Lisp_Object obj)
5071 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5073 mark_object (config->current_window);
5074 mark_object (config->current_buffer);
5075 mark_object (config->minibuffer_scroll_window);
5076 mark_object (config->root_window);
5078 for (i = 0; i < config->saved_windows_count; i++)
5080 struct saved_window *s = SAVED_WINDOW_N (config, i);
5081 mark_object (s->window);
5082 mark_object (s->buffer);
5083 mark_object (s->start);
5084 mark_object (s->pointm);
5085 mark_object (s->sb_point);
5086 mark_object (s->mark);
5088 /* #### This looked like this. I do not see why specifier cached
5089 values should not be marked, as such specifiers as toolbars
5090 might have GC-able instances. Freed configs are not marked,
5091 aren't they? -- kkm */
5092 mark_object (s->dedicated);
5094 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
5095 #include "winslots.h"
5101 inline static size_t
5102 sizeof_window_config_for_n_windows (unsigned int n)
5104 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (struct window_config,
5105 struct saved_window, saved_windows, n);
5109 sizeof_window_config (const void *h)
5111 const struct window_config *c = (const struct window_config *) h;
5112 return sizeof_window_config_for_n_windows (c->saved_windows_count);
5116 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
5118 struct window_config *config = XWINDOW_CONFIGURATION (obj);
5121 error ("printing unreadable object #<window-configuration 0x%x>",
5122 config->header.uid);
5123 write_c_string ("#<window-configuration ", printcharfun);
5124 sprintf (buf, "0x%x>", config->header.uid);
5125 write_c_string (buf, printcharfun);
5128 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
5129 window_configuration,
5131 print_window_config,
5132 0, 0, 0, 0, sizeof_window_config,
5133 struct window_config);
5136 /* Returns a boolean indicating whether the two saved windows are
5139 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
5141 #define WINDOW_SLOT(slot, compare) \
5142 if (!compare (win1->slot, win2->slot)) \
5144 #include "winslots.h"
5147 EQ (win1->window, win2->window) &&
5148 EQ (win1->buffer, win2->buffer) &&
5149 internal_equal (win1->start, win2->start, 0) &&
5150 internal_equal (win1->pointm, win2->pointm, 0) &&
5151 internal_equal (win1->sb_point, win2->sb_point, 0) &&
5152 internal_equal (win1->mark, win2->mark, 0) &&
5153 win1->pixel_left == win2->pixel_left &&
5154 win1->pixel_top == win2->pixel_top &&
5155 win1->pixel_width == win2->pixel_width &&
5156 win1->pixel_height == win2->pixel_height &&
5157 win1->hscroll == win2->hscroll &&
5158 win1->modeline_hscroll == win2->modeline_hscroll &&
5159 win1->parent_index == win2->parent_index &&
5160 win1->prev_index == win2->prev_index &&
5161 win1->start_at_line_beg == win2->start_at_line_beg;
5164 /* Returns a boolean indicating whether the two given configurations
5167 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
5169 struct window_config *fig1, *fig2;
5172 /* First check if they are truly the same. */
5173 if (EQ (conf1, conf2))
5176 fig1 = XWINDOW_CONFIGURATION (conf1);
5177 fig2 = XWINDOW_CONFIGURATION (conf2);
5179 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
5180 EQ (fig1->current_window, fig2->current_window) &&
5181 EQ (fig1->current_buffer, fig2->current_buffer) &&
5182 EQ (fig1->root_window, fig2->root_window) &&
5183 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
5185 fig1->frame_width == fig2->frame_width &&
5186 fig1->frame_height == fig2->frame_height)) */
5189 for (i = 0; i < fig1->saved_windows_count; i++)
5191 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
5192 SAVED_WINDOW_N (fig2, i)))
5199 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
5200 Return t if OBJECT is a window-configuration object.
5204 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5208 mark_windows_in_use_closure (struct window *w, void *closure)
5210 int mark = *(int *)closure;
5211 w->config_mark = mark;
5216 mark_windows_in_use (struct frame *f, int mark)
5218 map_windows (f, mark_windows_in_use_closure, &mark);
5221 /* Lisp_Object return value so it can be used in record_unwind_protect() */
5223 free_window_configuration (Lisp_Object window_config)
5226 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
5228 /* Free all the markers. It's not completely necessary that
5229 we do this (window configs sitting in a free list aren't
5230 marked normally so the markers wouldn't be marked anyway)
5231 but it's more efficient. */
5232 for (i = 0; i < config->saved_windows_count; i++)
5234 struct saved_window *p = SAVED_WINDOW_N (config, i);
5236 if (!NILP (p->pointm))
5238 free_marker (XMARKER (p->pointm));
5241 if (!NILP (p->start))
5243 free_marker (XMARKER (p->start));
5246 if (!NILP (p->sb_point))
5248 free_marker (XMARKER (p->sb_point));
5251 if (!NILP (p->mark))
5253 free_marker (XMARKER (p->mark));
5258 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5259 free_managed_lcrecord (Vwindow_configuration_free_list
5260 [config->saved_windows_count - 1],
5266 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5267 Set the configuration of windows and buffers as specified by CONFIGURATION.
5268 CONFIGURATION must be a value previously returned
5269 by `current-window-configuration' (which see).
5274 struct window_config *config;
5275 struct saved_window *p;
5276 Lisp_Object new_current_buffer;
5280 struct gcpro gcpro1;
5281 Lisp_Object old_window_config;
5282 /* int previous_frame_height;
5283 int previous_frame_width;*/
5284 int previous_pixel_top;
5285 int previous_pixel_height;
5286 int previous_pixel_left;
5287 int previous_pixel_width;
5288 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5289 int real_font_height;
5290 int converted_minibuf_height,target_minibuf_height;
5291 int specpdl_count = specpdl_depth ();
5293 GCPRO1 (configuration);
5295 CHECK_WINDOW_CONFIGURATION (configuration);
5296 config = XWINDOW_CONFIGURATION (configuration);
5298 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5301 /* Do not signal an error here if the frame was deleted. There are
5302 reasonable cases where we could get here with a deleted frame and
5303 just want to do close to nothing instead. */
5305 if (FRAME_LIVE_P (f))
5307 /* restore the frame characteristics */
5309 new_current_buffer = config->current_buffer;
5310 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5311 new_current_buffer = Qnil;
5314 * Assumed precondition: w->config_mark = 0 for all w
5315 * This procedure should ensure this is true by the time it exits
5316 * to ensure the precondition for future calls.
5318 * We use w->config_mark to know whether we're modifying a
5319 * window that is currently visible on the frame (#### we
5320 * should just be able to check whether the window is dead
5321 * or not, but this way is safer?). As we process each
5322 * window, we set its config_mark to 0. At the end, we
5323 * go through all the windows that used to be on the frame,
5324 * set each one's config_mark to 0 (to maintain the
5325 * assumed precondition) and delete each one that's no
5328 * #### Using a window-configuration to keep track of
5329 * the current windows is wasteful. All we need is the
5330 * list of windows, so we could just use a dynarr.
5332 old_window_config = Fcurrent_window_configuration (frame);
5334 /* If the new configuration is already equal to the old, then stop
5335 right here. This saves the work below and it also saves
5336 triggering a full redisplay of this window. This is a huge win
5337 when using the mouse since the mode motion code uses
5338 save-window-excursion extensively but will rarely cause the
5339 configuration to actually change. */
5340 if (window_config_equal (configuration, old_window_config))
5342 free_window_configuration (old_window_config);
5347 /* We can't quit or even check for quit because that may cause
5348 investigation of the frame state, which may crash if the frame is
5349 in an inconsistent state. */
5350 begin_dont_check_for_quit ();
5351 record_unwind_protect (free_window_configuration, old_window_config);
5353 mark_windows_in_use (f, 1);
5354 #ifdef BROKEN_SUBWINDOW_REDISPLAY
5355 /* Force subwindows to be remapped. This is overkill but saves
5356 us having to rely on the redisplay code to unmap any extant
5359 #### It does cause some extra flashing though which we could
5360 possibly avoid. So consider trying to get redisplay to work
5363 Removing the instances from the frame cache is wrong because
5364 an instance is only put in the frame cache when it is
5365 instantiated. So if we do this there is a chance that stuff
5366 will never get put back in the frame cache. */
5367 reset_frame_subwindow_instance_cache (f);
5370 /* JV: This is bogus,
5371 First of all, the units are inconsistent. The frame sizes are measured
5372 in characters but the window sizes are stored in pixels. So if a
5373 font size change happened between saving and restoring, the
5374 frame "sizes" maybe equal but the windows still should be
5375 resized. This is tickled a lot by the new "character size
5376 stays constant" policy in 21.0. It leads to very weird
5377 glitches (and possibly crashes when asserts are tickled).
5379 Just changing the units doesn't help because changing the
5380 toolbar configuration can also change the pixel positions.
5381 Luckily there is a much simpler way of doing this, see below.
5383 previous_frame_width = FRAME_WIDTH (f);
5384 previous_frame_height = FRAME_HEIGHT (f);
5385 /* If the frame has been resized since this window configuration was
5386 made, we change the frame to the size specified in the
5387 configuration, restore the configuration, and then resize it
5388 back. We keep track of the prevailing height in these variables. */
5389 if (config->frame_height != FRAME_HEIGHT (f)
5390 || config->frame_width != FRAME_WIDTH (f))
5391 change_frame_size (f, config->frame_height, config->frame_width, 0);
5394 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5395 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5396 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5397 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5399 /* remember some properties of the minibuffer */
5401 default_face_height_and_width (frame, &real_font_height, 0);
5402 assert(real_font_height > 0);
5404 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5406 previous_minibuf_height
5407 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5408 previous_minibuf_top
5409 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5410 previous_minibuf_width
5411 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5415 previous_minibuf_height = 0;
5416 previous_minibuf_top = 0;
5417 previous_minibuf_width = 0;
5419 converted_minibuf_height =
5420 (previous_minibuf_height % real_font_height) == 0 ?
5421 - (previous_minibuf_height / real_font_height ) : /* lines */
5422 previous_minibuf_height; /* pixels */
5424 /* Temporarily avoid any problems with windows that are smaller
5425 than they are supposed to be. */
5426 window_min_height = 1;
5427 window_min_width = 1;
5429 /* OK, now restore all the windows in the window config.
5430 This may involve "undeleting" windows, since the
5431 windows in the window config may be deleted.
5433 for (k = 0; k < config->saved_windows_count; k++)
5435 p = SAVED_WINDOW_N (config, k);
5436 w = XWINDOW (p->window);
5439 /* The window might be dead. In this case, its redisplay
5440 structures were freed, so we need to reallocate them. */
5441 if (!w->face_cachels)
5443 w->face_cachels = Dynarr_new (face_cachel);
5444 reset_face_cachels (w);
5446 if (!w->glyph_cachels)
5447 w->glyph_cachels = Dynarr_new (glyph_cachel);
5448 if (!w->line_start_cache)
5449 w->line_start_cache = Dynarr_new (line_start_cache);
5450 w->gutter_extent_modiff[0] = 0;
5451 w->gutter_extent_modiff[1] = 0;
5452 w->gutter_extent_modiff[2] = 0;
5453 w->gutter_extent_modiff[3] = 0;
5456 if (p->parent_index >= 0)
5457 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5461 if (p->prev_index >= 0)
5463 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5465 /* This is true for a minibuffer-only frame. */
5466 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5469 XWINDOW (w->prev)->next = p->window;
5474 if (!NILP (w->parent))
5476 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5478 XWINDOW (w->parent)->vchild = p->window;
5479 XWINDOW (w->parent)->hchild = Qnil;
5483 XWINDOW (w->parent)->hchild = p->window;
5484 XWINDOW (w->parent)->vchild = Qnil;
5488 if (!w->config_mark)
5490 /* #### This should be equivalent to the window previously
5491 having been dead. If we're brave, we'll put in an
5492 assertion to this effect. */
5493 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5495 else /* if (!EQ (w->buffer, p->buffer)) */
5497 /* With the new redisplay we let it know that a change has
5498 been made and it will take care of the rest. If we don't
5499 tell it something has possibly changed it could lead to
5500 incorrect display. */
5501 MARK_WINDOWS_CHANGED (w);
5504 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5505 WINDOW_TOP (w) = WINDOW_TOP (p);
5506 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5507 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5508 w->hscroll = p->hscroll;
5509 w->modeline_hscroll = p->modeline_hscroll;
5510 w->line_cache_last_updated = Qzero;
5511 /* When we restore a window's configuration, the identity of
5512 the window hasn't actually changed - so there is no
5513 reason why we shouldn't preserve the instance cache for
5514 it - unless it was originally deleted. This will often
5515 buy us something as we will not have to re-instantiate
5516 all the instances. This is because this is an instance
5517 cache - not a display cache. Preserving the display cache
5518 would definitely be wrong.
5520 We specifically want to do this for tabs, since for some
5521 reason finding a file will cause the configuration to be
5523 if (NILP (w->subwindow_instance_cache))
5524 w->subwindow_instance_cache =
5525 make_image_instance_cache_hash_table ();
5527 SET_LAST_MODIFIED (w, 1);
5528 SET_LAST_FACECHANGE (w);
5531 /* #### Consider making the instance cache a winslot. */
5532 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5533 #include "winslots.h"
5535 /* Reinstall the saved buffer and pointers into it. */
5536 if (NILP (p->buffer))
5537 w->buffer = p->buffer;
5540 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5541 /* If saved buffer is alive, install it. */
5543 w->buffer = p->buffer;
5544 w->start_at_line_beg = p->start_at_line_beg;
5545 set_marker_restricted (w->start[CURRENT_DISP],
5546 Fmarker_position (p->start),
5548 set_marker_restricted (w->pointm[CURRENT_DISP],
5549 Fmarker_position (p->pointm),
5551 set_marker_restricted (w->sb_point,
5552 Fmarker_position (p->sb_point),
5554 Fset_marker (XBUFFER (w->buffer)->mark,
5555 Fmarker_position (p->mark), w->buffer);
5557 /* As documented in Fcurrent_window_configuration, don't
5558 save the location of point in the buffer which was current
5559 when the window configuration was recorded. */
5560 if (!EQ (p->buffer, new_current_buffer) &&
5561 XBUFFER (p->buffer) == current_buffer)
5562 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5564 else if (NILP (w->buffer) ||
5565 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5566 /* Else if window's old buffer is dead too, get a live one. */
5568 /* #### The following line makes me nervous... */
5569 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5570 w->buffer = Fget_buffer_create (QSscratch);
5571 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5572 /* This will set the markers to beginning of visible
5574 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5575 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5577 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5578 w->start_at_line_beg = 1;
5581 /* Keeping window's old buffer; make sure the markers
5584 /* Set window markers at start of visible range. */
5585 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5586 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5588 if (XMARKER (w->sb_point)->buffer == 0)
5589 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5590 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5591 set_marker_restricted (w->pointm[CURRENT_DISP],
5593 (BUF_PT (XBUFFER (w->buffer))),
5595 w->start_at_line_beg = 1;
5600 FRAME_ROOT_WINDOW (f) = config->root_window;
5601 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5602 then calls do_switch_frame() below to select the frame that was
5603 recorded in the window config as being selected.
5605 Instead, we don't ever change the selected frame, and either
5606 call Fselect_window() below if the window config's frame is
5607 currently selected, or just set the selected window of the
5608 window config's frame. */
5611 /* Set the frame height to the value it had before this function. */
5612 if (previous_frame_height != FRAME_HEIGHT (f)
5613 || previous_frame_width != FRAME_WIDTH (f))
5614 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5616 /* We just reset the size and position of the minibuffer, to its old
5617 value, which needn't be valid. So we do some magic to see which value
5618 to actually take. Then we set it.
5621 We take the old value if is in the same units but differs from the
5624 #### Now we get more cases correct then ever before, but
5625 are we treating all? For instance what if the frames minibuf window
5626 is no longer the same one?
5628 target_minibuf_height = previous_minibuf_height;
5629 if (converted_minibuf_height &&
5630 (converted_minibuf_height * config->minibuf_height) > 0 &&
5631 (converted_minibuf_height != config->minibuf_height))
5633 target_minibuf_height = config->minibuf_height < 0 ?
5634 - (config->minibuf_height * real_font_height) :
5635 config->minibuf_height;
5636 target_minibuf_height =
5637 max(target_minibuf_height,real_font_height);
5639 if (previous_minibuf_height)
5641 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5642 = previous_minibuf_top -
5643 (target_minibuf_height - previous_minibuf_height);
5644 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5645 target_minibuf_height, 0);
5646 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5647 previous_minibuf_width, 0);
5650 /* This is a better way to deal with frame resizing, etc.
5651 What we _actually_ want is for the old (just restored)
5653 into the place of the new one. So we just do that. Simple! */
5654 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5655 /* Note that this function also updates the subwindow
5657 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5658 previous_pixel_height -
5659 (target_minibuf_height - previous_minibuf_height), 0);
5660 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5661 /* Note that this function also updates the subwindow
5663 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5665 /* If restoring in the current frame make the window current,
5666 otherwise just update the frame selected_window slot to be
5667 the restored current_window. */
5668 if (f == selected_frame ())
5671 /* When using `pop-window-configuration', often the minibuffer
5672 ends up as the selected window even though it's not active ...
5673 I really don't know the cause of this, but it should never
5674 happen. This kludge should fix it.
5676 #### Find out why this is really going wrong. */
5677 if (!minibuf_level &&
5678 MINI_WINDOW_P (XWINDOW (config->current_window)))
5679 window_to_select = Fnext_window (config->current_window,
5682 window_to_select = config->current_window;
5684 /* Do this last so that buffer stacking is calculated
5686 Fselect_window (config->current_window, Qnil);
5688 if (!NILP (new_current_buffer))
5690 Fset_buffer (new_current_buffer);
5691 Frecord_buffer (new_current_buffer);
5695 Fset_buffer (XWINDOW (config->current_window)->buffer);
5696 Frecord_buffer (XWINDOW (config->current_window)->buffer);
5700 set_frame_selected_window (f, config->current_window);
5703 old_window_config = Qnil; /* Warning suppression */
5705 /* Restore the minimum heights recorded in the configuration. */
5706 window_min_height = config->min_height;
5707 window_min_width = config->min_width;
5710 /* see above comment */
5711 /* Fselect_window will have made f the selected frame, so we
5712 reselect the proper frame here. Fhandle_switch_frame will change the
5713 selected window too, but that doesn't make the call to
5714 Fselect_window above totally superfluous; it still sets f's
5716 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5717 do_switch_frame (config->selected_frame, Qnil, 0);
5720 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5722 if (FRAME_LIVE_P (f))
5724 /* Do this before calling recompute_all_cached_specifiers_in_window()
5725 so that things like redisplay_redraw_cursor() won't abort due
5726 to no window mirror present. */
5727 f->mirror_dirty = 1;
5729 config = XWINDOW_CONFIGURATION (old_window_config);
5730 for (k = 0; k < config->saved_windows_count; k++)
5732 p = SAVED_WINDOW_N (config, k);
5733 w = XWINDOW (p->window);
5734 /* Remember, we set w->config_mark on all currently visible
5735 windows, and reset it on all newly visible windows.
5736 Any windows still marked need to be deleted. */
5739 mark_window_as_deleted (w);
5744 /* We just potentially changed the window's buffer and
5745 potentially turned a dead window into a live one,
5746 so we need to recompute the cached specifier values. */
5747 recompute_all_cached_specifiers_in_window (w);
5752 /* Now restore things, when everything else if OK. */
5754 unbind_to (specpdl_count, Qnil);
5761 /* Mark all subwindows of a window as deleted. The argument
5762 W is actually the subwindow tree of the window in question. */
5765 delete_all_subwindows (struct window *w)
5767 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5768 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5769 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5771 mark_window_as_deleted (w);
5776 count_windows (struct window *window)
5779 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5780 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5781 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5785 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5788 for (j = 0; j < lim; j++)
5790 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5794 return 0; /* suppress compiler warning */
5798 save_window_save (Lisp_Object window, struct window_config *config, int i)
5802 for (; !NILP (window); window = w->next)
5804 struct saved_window *p = SAVED_WINDOW_N (config, i);
5806 w = XWINDOW (window);
5809 p->buffer = w->buffer;
5810 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5811 WINDOW_TOP (p) = WINDOW_TOP (w);
5812 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5813 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5814 p->hscroll = w->hscroll;
5815 p->modeline_hscroll = w->modeline_hscroll;
5817 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5818 #include "winslots.h"
5820 if (!NILP (w->buffer))
5822 /* Save w's value of point in the window configuration.
5823 If w is the selected window, then get the value of point
5824 from the buffer; pointm is garbage in the selected window. */
5825 if (EQ (window, Fselected_window (Qnil)))
5827 p->pointm = noseeum_make_marker ();
5828 Fset_marker (p->pointm,
5829 make_int (BUF_PT (XBUFFER (w->buffer))),
5833 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5835 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5836 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5837 p->start_at_line_beg = w->start_at_line_beg;
5839 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5847 p->start_at_line_beg = 0;
5850 if (NILP (w->parent))
5851 p->parent_index = -1;
5853 p->parent_index = saved_window_index (w->parent, config, i);
5857 p->prev_index = saved_window_index (w->prev, config, i);
5858 if (!NILP (w->vchild))
5859 i = save_window_save (w->vchild, config, i);
5860 if (!NILP (w->hchild))
5861 i = save_window_save (w->hchild, config, i);
5868 /* Added to doc string:
5870 This also records the currently selected frame, and FRAME's focus
5871 redirection (see `redirect-frame-focus').
5876 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5877 Return an object representing the current window configuration of FRAME.
5878 If FRAME is nil or omitted, use the selected frame.
5879 This describes the number of windows, their sizes and current buffers,
5880 and for each window on FRAME the displayed buffer, where display
5881 starts, and the positions of point and mark.
5882 An exception is made for point in the current buffer:
5883 its value is -not- saved.
5888 struct frame *f = decode_frame (frame);
5889 struct window_config *config;
5890 unsigned int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5892 int real_font_height;
5894 if (n_windows <= countof (Vwindow_configuration_free_list))
5895 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5896 (Vwindow_configuration_free_list
5899 /* More than ten windows; just allocate directly */
5900 config = (struct window_config *)
5901 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5902 &lrecord_window_configuration);
5903 XSETWINDOW_CONFIGURATION (result, config);
5905 config->frame_width = FRAME_WIDTH (f);
5906 config->frame_height = FRAME_HEIGHT (f); */
5907 /* #### When using `push-window-configuration', often the minibuffer ends
5908 up as the selected window because functions run as the result of
5909 user interaction e.g. hyper-apropos. It seems to me the sensible
5910 thing to do is not record the minibuffer here.
5912 #### Unfortunately this is a change to previous behaviour, however logical
5913 it may be, so revert for the moment. */
5915 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
5916 config->current_window = FRAME_SELECTED_WINDOW (f);
5918 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
5920 config->current_window = FRAME_SELECTED_WINDOW (f);
5921 XSETBUFFER (config->current_buffer, current_buffer);
5922 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5923 config->root_window = FRAME_ROOT_WINDOW (f);
5924 config->min_height = window_min_height;
5925 config->min_width = window_min_width;
5926 config->saved_windows_count = n_windows;
5927 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5929 /* save the minibuffer height using the heuristics from
5930 change_frame_size_1 */
5932 XSETFRAME (frame, f); /* frame could have been nil ! */
5933 default_face_height_and_width (frame, &real_font_height, 0);
5934 assert(real_font_height > 0);
5936 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5937 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5940 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5941 - (minibuf_height / real_font_height ) : /* lines */
5942 minibuf_height; /* pixels */
5948 save_window_excursion_unwind (Lisp_Object window_config)
5950 Lisp_Object val = Fset_window_configuration (window_config);
5951 free_window_configuration (window_config);
5955 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5956 Execute body, preserving window sizes and contents.
5957 Restores which buffer appears in which window, where display starts,
5958 as well as the current buffer.
5959 Does not restore the value of point in current buffer.
5963 /* This function can GC */
5965 int speccount = specpdl_depth ();
5967 record_unwind_protect (save_window_excursion_unwind,
5968 Fcurrent_window_configuration (Qnil));
5969 val = Fprogn (args);
5970 return unbind_to (speccount, val);
5973 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5974 Return the horizontal pixel position of POS in window.
5975 Beginning of line is column 0. This is calculated using the redisplay
5976 display tables. If WINDOW is nil, the current window is assumed.
5977 If POS is nil, point is assumed. Note that POS must be visible for
5978 a non-nil result to be returned.
5982 struct window* w = decode_window (window);
5983 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5985 struct display_line *dl = 0;
5986 struct display_block *db = 0;
5987 struct rune* rb = 0;
5988 int y = w->last_point_y[CURRENT_DISP];
5989 int x = w->last_point_x[CURRENT_DISP];
5991 if (MINI_WINDOW_P (w))
5994 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
6000 pos = Fwindow_point (window);
6005 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
6010 for (i = first_line; i < Dynarr_length (dla); i++)
6012 dl = Dynarr_atp (dla, i);
6013 /* find the vertical location first */
6014 if (point >= dl->bufpos && point <= dl->end_bufpos)
6016 db = get_display_block_from_line (dl, TEXT);
6017 for (i = 0; i < Dynarr_length (db->runes); i++)
6019 rb = Dynarr_atp (db->runes, i);
6020 if (point <= rb->bufpos)
6032 /* optimized case */
6033 dl = Dynarr_atp (dla, y);
6034 db = get_display_block_from_line (dl, TEXT);
6036 if (x >= Dynarr_length (db->runes))
6039 rb = Dynarr_atp (db->runes, x);
6042 return make_int (rb->xpos - WINDOW_LEFT (w));
6047 /* This is short and simple in elisp, but... it was written to debug
6048 problems purely on the C side. That is where we need to call it so
6051 debug_print_window (Lisp_Object window, int level)
6054 Lisp_Object child = Fwindow_first_vchild (window);
6057 child = Fwindow_first_hchild (window);
6059 for (i = level; i > 0; i--)
6062 stderr_out ("#<window");
6064 Lisp_Object buffer = XWINDOW (window)->buffer;
6065 if (!NILP (buffer) && BUFFERP (buffer))
6066 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
6068 stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
6070 while (!NILP (child))
6072 debug_print_window (child, level + 1);
6073 child = Fwindow_next_child (child);
6077 void debug_print_windows (struct frame *f);
6079 debug_print_windows (struct frame *f)
6081 debug_print_window (f->root_window, 0);
6082 putc ('\n', stderr);
6084 #endif /* DEBUG_XEMACS */
6087 /************************************************************************/
6088 /* initialization */
6089 /************************************************************************/
6092 syms_of_window (void)
6094 INIT_LRECORD_IMPLEMENTATION (window);
6095 INIT_LRECORD_IMPLEMENTATION (window_configuration);
6097 defsymbol (&Qwindowp, "windowp");
6098 defsymbol (&Qwindow_live_p, "window-live-p");
6099 defsymbol (&Qwindow_configurationp, "window-configuration-p");
6100 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6101 defsymbol (&Qdisplay_buffer, "display-buffer");
6103 #ifdef MEMORY_USAGE_STATS
6104 defsymbol (&Qface_cache, "face-cache");
6105 defsymbol (&Qglyph_cache, "glyph-cache");
6106 defsymbol (&Qline_start_cache, "line-start-cache");
6107 #ifdef HAVE_SCROLLBARS
6108 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
6110 defsymbol (&Qother_redisplay, "other-redisplay");
6111 /* Qother in general.c */
6114 DEFSYMBOL (Qtruncate_partial_width_windows);
6116 DEFSUBR (Fselected_window);
6117 DEFSUBR (Flast_nonminibuf_window);
6118 DEFSUBR (Fminibuffer_window);
6119 DEFSUBR (Fwindow_minibuffer_p);
6121 DEFSUBR (Fwindow_live_p);
6122 DEFSUBR (Fwindow_first_hchild);
6123 DEFSUBR (Fwindow_first_vchild);
6124 DEFSUBR (Fwindow_next_child);
6125 DEFSUBR (Fwindow_previous_child);
6126 DEFSUBR (Fwindow_parent);
6127 DEFSUBR (Fwindow_lowest_p);
6128 DEFSUBR (Fwindow_truncated_p);
6129 DEFSUBR (Fwindow_highest_p);
6130 DEFSUBR (Fwindow_leftmost_p);
6131 DEFSUBR (Fwindow_rightmost_p);
6132 DEFSUBR (Fpos_visible_in_window_p);
6133 DEFSUBR (Fwindow_buffer);
6134 DEFSUBR (Fwindow_frame);
6135 DEFSUBR (Fwindow_height);
6136 DEFSUBR (Fwindow_displayed_height);
6137 DEFSUBR (Fwindow_width);
6138 DEFSUBR (Fwindow_full_width);
6139 DEFSUBR (Fwindow_pixel_height);
6140 DEFSUBR (Fwindow_pixel_width);
6141 DEFSUBR (Fwindow_text_area_height);
6142 DEFSUBR (Fwindow_text_area_pixel_height);
6143 DEFSUBR (Fwindow_displayed_text_pixel_height);
6144 DEFSUBR (Fwindow_text_area_pixel_width);
6145 DEFSUBR (Fwindow_hscroll);
6146 DEFSUBR (Fset_window_hscroll);
6147 DEFSUBR (Fmodeline_hscroll);
6148 DEFSUBR (Fset_modeline_hscroll);
6149 #if 0 /* bogus FSF crock */
6150 DEFSUBR (Fwindow_redisplay_end_trigger);
6151 DEFSUBR (Fset_window_redisplay_end_trigger);
6153 DEFSUBR (Fwindow_pixel_edges);
6154 DEFSUBR (Fwindow_text_area_pixel_edges);
6155 DEFSUBR (Fwindow_point);
6156 DEFSUBR (Fwindow_start);
6157 DEFSUBR (Fwindow_end);
6158 DEFSUBR (Fwindow_last_line_visible_height);
6159 DEFSUBR (Fset_window_point);
6160 DEFSUBR (Fset_window_start);
6161 DEFSUBR (Fwindow_dedicated_p);
6162 DEFSUBR (Fset_window_dedicated_p);
6163 DEFSUBR (Fnext_window);
6164 DEFSUBR (Fprevious_window);
6165 DEFSUBR (Fnext_vertical_window);
6166 DEFSUBR (Fother_window);
6167 DEFSUBR (Fget_lru_window);
6168 DEFSUBR (Fget_largest_window);
6169 DEFSUBR (Fget_buffer_window);
6170 DEFSUBR (Fwindow_left_margin_pixel_width);
6171 DEFSUBR (Fwindow_right_margin_pixel_width);
6172 DEFSUBR (Fdelete_other_windows);
6173 DEFSUBR (Fdelete_windows_on);
6174 DEFSUBR (Freplace_buffer_in_windows);
6175 DEFSUBR (Fdelete_window);
6176 DEFSUBR (Fset_window_buffer);
6177 DEFSUBR (Fselect_window);
6178 DEFSUBR (Fsplit_window);
6179 DEFSUBR (Fenlarge_window);
6180 DEFSUBR (Fenlarge_window_pixels);
6181 DEFSUBR (Fshrink_window);
6182 DEFSUBR (Fshrink_window_pixels);
6183 DEFSUBR (Fscroll_up);
6184 DEFSUBR (Fscroll_down);
6185 DEFSUBR (Fscroll_left);
6186 DEFSUBR (Fscroll_right);
6187 DEFSUBR (Fother_window_for_scrolling);
6188 DEFSUBR (Fscroll_other_window);
6189 DEFSUBR (Fcenter_to_window_line);
6190 DEFSUBR (Fmove_to_window_line);
6191 #ifdef MEMORY_USAGE_STATS
6192 DEFSUBR (Fwindow_memory_usage);
6194 DEFSUBR (Fwindow_configuration_p);
6195 DEFSUBR (Fset_window_configuration);
6196 DEFSUBR (Fcurrent_window_configuration);
6197 DEFSUBR (Fsave_window_excursion);
6198 DEFSUBR (Fcurrent_pixel_column);
6202 reinit_vars_of_window (void)
6205 /* Make sure all windows get marked */
6206 minibuf_window = Qnil;
6207 staticpro_nodump (&minibuf_window);
6209 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
6211 Vwindow_configuration_free_list[i] =
6212 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
6213 &lrecord_window_configuration);
6214 staticpro_nodump (&Vwindow_configuration_free_list[i]);
6219 vars_of_window (void)
6221 reinit_vars_of_window ();
6223 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
6224 *Non-nil means to scroll if point lands on a line which is clipped.
6226 scroll_on_clipped_lines = 1;
6228 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
6229 See `temp-buffer-show-function'.
6231 Vtemp_buffer_show_hook = Qnil;
6233 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
6234 Non-nil means call as function to display a help buffer.
6235 The function is called with one argument, the buffer to be displayed.
6236 Used by `with-output-to-temp-buffer'.
6237 If this function is used, then it must do the entire job of showing
6238 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
6239 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
6241 Vtemp_buffer_show_function = Qnil;
6243 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
6244 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
6246 Vminibuffer_scroll_window = Qnil;
6248 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
6249 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
6251 Vother_window_scroll_buffer = Qnil;
6253 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
6254 *Number of pixels to scroll by per requested line.
6255 If nil then normal line scrolling occurs regardless of line height.
6256 If t then scrolling is done in increments equal to the height of the default face.
6258 Vwindow_pixel_scroll_increment = Qt;
6260 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
6261 *Number of lines of continuity when scrolling by screenfuls.
6263 next_screen_context_lines = 2;
6265 DEFVAR_INT ("window-min-height", &window_min_height /*
6266 *Delete any window less than this tall (including its modeline).
6268 window_min_height = 4;
6270 DEFVAR_INT ("window-min-width", &window_min_width /*
6271 *Delete any window less than this wide.
6273 window_min_width = 10;
6277 specifier_vars_of_window (void)
6279 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
6280 *How thick to draw 3D shadows around modelines.
6281 If this is set to 0, modelines will be the traditional 2D. Sizes above
6282 10 will be accepted but the maximum thickness that will be drawn is 10.
6283 This is a specifier; use `set-specifier' to change it.
6285 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
6286 /* The initial value for modeline-shadow-thickness is 2, but if the
6287 user removes all specifications we provide a fallback value of 0,
6288 which is probably what was expected. */
6289 set_specifier_fallback (Vmodeline_shadow_thickness,
6290 list1 (Fcons (Qnil, Qzero)));
6291 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
6293 set_specifier_caching (Vmodeline_shadow_thickness,
6294 offsetof (struct window, modeline_shadow_thickness),
6295 modeline_shadow_thickness_changed,
6298 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
6299 *Whether the modeline should be displayed.
6300 This is a specifier; use `set-specifier' to change it.
6302 Vhas_modeline_p = Fmake_specifier (Qboolean);
6303 set_specifier_fallback (Vhas_modeline_p,
6304 list1 (Fcons (Qnil, Qt)));
6305 set_specifier_caching (Vhas_modeline_p,
6306 offsetof (struct window, has_modeline_p),
6307 /* #### It's strange that we need a special
6308 flag to indicate that the shadow-thickness
6309 has changed, but not one to indicate that
6310 the modeline has been turned off or on. */
6311 some_window_value_changed,
6314 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
6315 &Vvertical_divider_always_visible_p /*
6316 *Should XEmacs always display vertical dividers between windows.
6318 When this is non-nil, vertical dividers are always shown, and are
6319 draggable. When it is nil, vertical dividers are shown only when
6320 there are no scrollbars in between windows, and are not draggable.
6322 This is a specifier; use `set-specifier' to change it.
6324 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6325 set_specifier_fallback (Vvertical_divider_always_visible_p,
6326 list1 (Fcons (Qnil, Qt)));
6327 set_specifier_caching (Vvertical_divider_always_visible_p,
6328 offsetof (struct window,
6329 vertical_divider_always_visible_p),
6330 vertical_divider_changed_in_window,
6333 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6334 *How thick to draw 3D shadows around vertical dividers.
6335 This is a specifier; use `set-specifier' to change it.
6337 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6338 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6339 list1 (Fcons (Qnil, Qzero)));
6340 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6342 set_specifier_caching (Vvertical_divider_shadow_thickness,
6343 offsetof (struct window,
6344 vertical_divider_shadow_thickness),
6345 vertical_divider_changed_in_window,
6347 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6348 *The width of the vertical dividers, not including shadows.
6350 For TTY windows, divider line is always one character wide. When
6351 instance of this specifier is zero in a TTY window, no divider is
6352 drawn at all between windows. When non-zero, a one character wide
6353 divider is displayed.
6355 This is a specifier; use `set-specifier' to change it.
6358 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6360 Lisp_Object fb = Qnil;
6362 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6365 fb = Fcons (Fcons (list1 (Qgtk), make_int (3)), fb);
6367 #ifdef HAVE_X_WINDOWS
6368 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6370 #ifdef HAVE_MS_WINDOWS
6371 /* #### This should be made magic and made to obey system settings */
6372 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6374 set_specifier_fallback (Vvertical_divider_line_width, fb);
6376 set_specifier_caching (Vvertical_divider_line_width,
6377 offsetof (struct window,
6378 vertical_divider_line_width),
6379 vertical_divider_changed_in_window,
6382 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6383 *How much space to leave around the vertical dividers.
6385 In TTY windows, spacing is always zero, and the value of this
6386 specifier is ignored.
6388 This is a specifier; use `set-specifier' to change it.
6390 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6392 Lisp_Object fb = Qnil;
6394 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6396 #ifdef HAVE_X_WINDOWS
6397 /* #### 3D dividers look great on MS Windows with spacing = 0.
6398 Should not the same value be the fallback under X? - kkm */
6399 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6402 fb = Fcons (Fcons (list1 (Qgtk), Qzero), fb);
6404 #ifdef HAVE_MS_WINDOWS
6405 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6407 set_specifier_fallback (Vvertical_divider_spacing, fb);
6409 set_specifier_caching (Vvertical_divider_spacing,
6410 offsetof (struct window, vertical_divider_spacing),
6411 vertical_divider_changed_in_window,