1 /* Window creation, deletion and examination for XEmacs.
2 Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1996 Chuck Thompson.
7 This file is part of XEmacs.
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
24 /* Synched up with: FSF 19.30. */
25 /* Beginning to diverge significantly. */
27 /* This file has been Mule-ized. */
37 #include "redisplay.h"
43 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp;
44 Lisp_Object Qdisplay_buffer;
46 #ifdef MEMORY_USAGE_STATS
47 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
48 #ifdef HAVE_SCROLLBARS
49 Lisp_Object Qscrollbar_instances;
53 EXFUN (Fnext_window, 4);
55 static int window_pixel_width_to_char_width (struct window *w,
57 int include_margins_p);
58 static int window_char_width_to_pixel_width (struct window *w,
60 int include_margins_p);
61 static int window_pixel_height_to_char_height (struct window *w,
63 int include_gutters_p);
64 static int window_char_height_to_pixel_height (struct window *w,
66 int include_gutters_p);
67 static void change_window_height (struct window *w, int delta, int widthflag,
70 /* Thickness of shadow border around 3d modelines. */
71 Lisp_Object Vmodeline_shadow_thickness;
73 /* Whether vertical dividers are draggable and displayed */
74 Lisp_Object Vvertical_divider_always_visible_p;
76 /* Whether a modeline should be displayed. */
77 Lisp_Object Vhas_modeline_p;
79 /* Thickness of shadow border around vertical dividers. */
80 Lisp_Object Vvertical_divider_shadow_thickness;
82 /* Divider surface width (not counting 3-d borders) */
83 Lisp_Object Vvertical_divider_line_width;
85 /* Spacing between outer egde of divider border and window edge */
86 Lisp_Object Vvertical_divider_spacing;
88 /* How much to scroll by per-line. */
89 Lisp_Object Vwindow_pixel_scroll_increment;
91 /* Scroll if point lands on the bottom line and that line is partially
93 int scroll_on_clipped_lines;
95 /* The minibuffer window of the selected frame.
96 Note that you cannot test for minibufferness of an arbitrary window
97 by comparing against this; but you can test for minibufferness of
98 the selected window. */
99 Lisp_Object minibuf_window;
101 /* Non-nil means it is the window for C-M-v to scroll
102 when the minibuffer is selected. */
103 Lisp_Object Vminibuffer_scroll_window;
105 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
106 Lisp_Object Vother_window_scroll_buffer;
108 /* Non-nil means it's the function to call to display temp buffers. */
109 Lisp_Object Vtemp_buffer_show_function;
111 Lisp_Object Vtemp_buffer_show_hook;
113 /* If a window gets smaller than either of these, it is removed. */
114 int window_min_height;
115 int window_min_width;
117 /* Hook run at end of temp_output_buffer_show. */
118 Lisp_Object Qtemp_buffer_show_hook;
120 /* Number of lines of continuity in scrolling by screenfuls. */
121 int next_screen_context_lines;
123 /* List of freed window configurations with 1 - 10 windows. */
124 static Lisp_Object Vwindow_configuration_free_list[10];
126 #define SET_LAST_MODIFIED(w, cache_too) \
128 (w)->last_modified[CURRENT_DISP] = Qzero; \
129 (w)->last_modified[DESIRED_DISP] = Qzero; \
130 (w)->last_modified[CMOTION_DISP] = Qzero; \
132 (w)->line_cache_last_updated = Qzero; \
135 #define SET_LAST_FACECHANGE(w) \
137 (w)->last_facechange[CURRENT_DISP] = Qzero; \
138 (w)->last_facechange[DESIRED_DISP] = Qzero; \
139 (w)->last_facechange[CMOTION_DISP] = Qzero; \
143 #define MARK_DISP_VARIABLE(field) \
144 mark_object (window->field[CURRENT_DISP]); \
145 mark_object (window->field[DESIRED_DISP]); \
146 mark_object (window->field[CMOTION_DISP]);
149 mark_window (Lisp_Object obj)
151 struct window *window = XWINDOW (obj);
152 mark_object (window->frame);
153 mark_object (window->mini_p);
154 mark_object (window->next);
155 mark_object (window->prev);
156 mark_object (window->hchild);
157 mark_object (window->vchild);
158 mark_object (window->parent);
159 mark_object (window->buffer);
160 MARK_DISP_VARIABLE (start);
161 MARK_DISP_VARIABLE (pointm);
162 mark_object (window->sb_point); /* #### move to scrollbar.c? */
163 mark_object (window->use_time);
164 MARK_DISP_VARIABLE (last_modified);
165 MARK_DISP_VARIABLE (last_point);
166 MARK_DISP_VARIABLE (last_start);
167 MARK_DISP_VARIABLE (last_facechange);
168 mark_object (window->line_cache_last_updated);
169 mark_object (window->redisplay_end_trigger);
170 mark_object (window->subwindow_instance_cache);
172 mark_face_cachels (window->face_cachels);
173 mark_glyph_cachels (window->glyph_cachels);
175 #define WINDOW_SLOT(slot, compare) mark_object (window->slot)
176 #include "winslots.h"
182 print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
187 error ("printing unreadable object #<window 0x%x>",
188 XWINDOW (obj)->header.uid);
190 write_c_string ("#<window", printcharfun);
191 if (!NILP (XWINDOW (obj)->buffer))
193 Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
194 write_c_string (" on ", printcharfun);
195 print_internal (name, printcharfun, 1);
197 sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
198 write_c_string (buf, printcharfun);
202 finalize_window (void *header, int for_disksave)
204 struct window *w = (struct window *) header;
206 if (w->line_start_cache)
208 Dynarr_free (w->line_start_cache);
209 w->line_start_cache = 0;
216 for (i = 0; i < Dynarr_length (w->face_cachels); i++)
218 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i);
219 if (cachel->merged_faces)
221 Dynarr_free (cachel->merged_faces);
222 cachel->merged_faces = 0;
225 Dynarr_free (w->face_cachels);
229 if (w->glyph_cachels)
231 Dynarr_free (w->glyph_cachels);
232 w->glyph_cachels = 0;
236 DEFINE_LRECORD_IMPLEMENTATION ("window", window,
237 mark_window, print_window, finalize_window,
238 0, 0, 0, struct window);
241 #define INIT_DISP_VARIABLE(field, initialization) \
242 p->field[CURRENT_DISP] = initialization; \
243 p->field[DESIRED_DISP] = initialization; \
244 p->field[CMOTION_DISP] = initialization;
246 /* We have an implicit assertion that the first two elements (default
247 and modeline faces) are always present in the face_element_cache.
248 Normally redisplay ensures this. However, it is possible for a
249 window to get created and functions which reference these values
250 called before redisplay works with the window for the first time.
251 All callers of allocate_window should therefore call
252 reset_face_cachels on the created window. We can't do it
253 here because the window must have its frame pointer set or
254 reset_face_cachels will fail. */
256 allocate_window (void)
259 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
273 INIT_DISP_VARIABLE (start, Fmake_marker ());
274 INIT_DISP_VARIABLE (pointm, Fmake_marker ());
275 p->sb_point = Fmake_marker ();
277 INIT_DISP_VARIABLE (last_modified, Qzero);
278 INIT_DISP_VARIABLE (last_point, Fmake_marker ());
279 INIT_DISP_VARIABLE (last_start, Fmake_marker ());
280 INIT_DISP_VARIABLE (last_facechange, Qzero);
281 p->face_cachels = Dynarr_new (face_cachel);
282 p->glyph_cachels = Dynarr_new (glyph_cachel);
283 p->line_start_cache = Dynarr_new (line_start_cache);
284 p->subwindow_instance_cache = make_lisp_hash_table (10,
287 p->line_cache_last_updated = Qzero;
288 INIT_DISP_VARIABLE (last_point_x, 0);
289 INIT_DISP_VARIABLE (last_point_y, 0);
290 INIT_DISP_VARIABLE (window_end_pos, 0);
291 p->redisplay_end_trigger = Qnil;
293 #define WINDOW_SLOT(slot, compare) p->slot = Qnil
294 #include "winslots.h"
296 p->windows_changed = 1;
297 p->shadow_thickness_changed = 1;
301 #undef INIT_DISP_VARIABLE
304 * The redisplay structures used to be stored with each window. While
305 * they are logically something associated with frames they can't be
306 * stored there with a redisplay which handles variable height lines.
307 * Lines in horizontally split windows might not line up. So they get
308 * stored with the windows.
310 * The problem with this is window configurations. When restoring a
311 * window configuration it now becomes problematic to do an
312 * incremental redisplay. The solution is to store the redisplay
313 * structures with the frame as they should be but laid out in the
314 * same manner as the window structure. Thus is born the window
317 * It also becomes a convenient place to stick scrollbar instances
318 * since they extrapolate out to having the same problem described for
319 * the display structures.
322 /* Create a new window mirror structure and associated redisplay
324 static struct window_mirror *
325 new_window_mirror (struct frame *f)
327 struct window_mirror *t = xnew_and_zero (struct window_mirror);
331 t->current_display_lines = Dynarr_new (display_line);
332 t->desired_display_lines = Dynarr_new (display_line);
335 #ifdef HAVE_SCROLLBARS
336 t->scrollbar_vertical_instance = NULL;
337 t->scrollbar_horizontal_instance = NULL;
343 /* Synchronize the mirror structure with a given window structure.
344 This is normally called from update_frame_window_mirror with a
345 starting window of f->root_window. */
346 static struct window_mirror *
347 update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
353 free_window_mirror (mir);
360 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
362 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
363 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
364 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
367 * If the redisplay structs are not empty and the mirror has
368 * children, then this mirror structure was formerly being used for
369 * display but is no longer. Reset its current display structs so
370 * that redisplay doesn't accidentally think they are accurate if it
371 * is later used for display purposes once again. Also, mark the
372 * scrollbar instance as not active.
374 if (mir->vchild || mir->hchild)
376 /* The redisplay structures are big. Leaving them around in
377 non-leaf windows can add up to a lot of wasted space. So
379 free_display_structs (mir);
380 mir->current_display_lines = Dynarr_new (display_line);
381 mir->desired_display_lines = Dynarr_new (display_line);
383 #ifdef HAVE_SCROLLBARS
384 update_window_scrollbars (XWINDOW (win), mir, 0, 0);
392 /* Given a window mirror, determine which real window it contains the
393 redisplay structures for. */
395 real_window_internal (Lisp_Object win, struct window_mirror *rmir,
396 struct window_mirror *mir)
398 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
402 if (!NILP (XWINDOW (win)->vchild))
405 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir);
409 if (!NILP (XWINDOW (win)->hchild))
412 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir);
421 /* Given a real window, find the mirror structure which contains its
422 redisplay structures. */
423 static struct window_mirror *
424 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
427 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
429 if (w == XWINDOW (win))
432 if (!NILP (XWINDOW (win)->vchild))
434 struct window_mirror *retval =
435 find_window_mirror_internal (XWINDOW (win)->vchild,
437 if (retval) return retval;
440 if (!NILP (XWINDOW (win)->hchild))
442 struct window_mirror *retval =
443 find_window_mirror_internal (XWINDOW (win)->hchild,
445 if (retval) return retval;
452 /* Update the mirror structure for the given frame. */
454 update_frame_window_mirror (struct frame *f)
456 f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
460 /* Free a given mirror structure along with all of its children as
461 well as their associated display structures. */
463 free_window_mirror (struct window_mirror *mir)
467 struct window_mirror *prev = mir;
468 if (mir->hchild) free_window_mirror (mir->hchild);
469 if (mir->vchild) free_window_mirror (mir->vchild);
470 #ifdef HAVE_SCROLLBARS
471 release_window_mirror_scrollbars (mir);
473 free_display_structs (mir);
479 /* Given a mirror structure, return the window it mirrors. Calls
480 real_window_internal to do most of the work. */
482 real_window (struct window_mirror *mir, int no_abort)
484 Lisp_Object retval = real_window_internal (mir->frame->root_window,
485 mir->frame->root_mirror, mir);
486 if (NILP (retval) && !no_abort)
492 /* Given a real window, return its mirror structure. Calls
493 find_window_mirror_internal to do all of the work. */
494 struct window_mirror *
495 find_window_mirror (struct window *w)
497 struct frame *f = XFRAME (w->frame);
499 update_frame_window_mirror (f);
500 return find_window_mirror_internal (f->root_window, f->root_mirror, w);
503 /*****************************************************************************
504 find_window_by_pixel_pos
506 Given a pixel position relative to a frame, find the window at that
508 ****************************************************************************/
510 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win)
515 for (; !NILP (win); win = XWINDOW (win)->next)
519 if (!NILP (XWINDOW (win)->vchild))
521 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild);
524 if (!NILP (XWINDOW (win)->hchild))
526 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild);
530 if (pix_x >= WINDOW_LEFT (w)
531 && pix_x <= WINDOW_RIGHT (w)
532 && pix_y >= WINDOW_TOP (w)
533 && pix_y <= WINDOW_BOTTOM (w))
539 /* Return a pointer to the display structures for the given window. */
540 display_line_dynarr *
541 window_display_lines (struct window *w, int which)
543 struct window_mirror *t;
545 if (XFRAME (w->frame)->mirror_dirty)
546 update_frame_window_mirror (XFRAME (w->frame));
547 t = find_window_mirror (w);
551 if (which == CURRENT_DISP)
552 return t->current_display_lines;
553 else if (which == DESIRED_DISP)
554 return t->desired_display_lines;
555 else if (which == CMOTION_DISP)
556 /* The CMOTION_DISP display lines are global. */
557 return cmotion_display_lines;
561 return 0; /* shut up compiler */
565 window_display_buffer (struct window *w)
567 struct window_mirror *t;
569 if (XFRAME (w->frame)->mirror_dirty)
570 update_frame_window_mirror (XFRAME (w->frame));
571 t = find_window_mirror (w);
579 set_window_display_buffer (struct window *w, struct buffer *b)
581 struct window_mirror *t;
583 if (XFRAME (w->frame)->mirror_dirty)
584 update_frame_window_mirror (XFRAME (w->frame));
585 t = find_window_mirror (w);
593 /* Determining a window's position based solely on its pixel
594 positioning doesn't work. Instead, we do it the intelligent way,
595 by checking its positioning in the window hierarchy. */
597 window_is_leftmost (struct window *w)
599 Lisp_Object parent, current_ancestor, window;
601 XSETWINDOW (window, w);
603 parent = XWINDOW (window)->parent;
604 current_ancestor = window;
606 while (!NILP (parent))
608 if (!NILP (XWINDOW (parent)->hchild) &&
609 !EQ (XWINDOW (parent)->hchild, current_ancestor))
612 current_ancestor = parent;
613 parent = XWINDOW (parent)->parent;
620 window_is_rightmost (struct window *w)
622 Lisp_Object parent, current_ancestor, window;
624 XSETWINDOW (window, w);
626 parent = XWINDOW (window)->parent;
627 current_ancestor = window;
629 while (!NILP (parent))
631 if (!NILP (XWINDOW (parent)->hchild)
632 && !NILP (XWINDOW (current_ancestor)->next))
635 current_ancestor = parent;
636 parent = XWINDOW (parent)->parent;
643 window_full_width_p (struct window *w)
645 return window_is_leftmost (w) && window_is_rightmost (w);
649 window_is_highest (struct window *w)
651 Lisp_Object parent, current_ancestor, window;
653 XSETWINDOW (window, w);
655 parent = XWINDOW (window)->parent;
656 current_ancestor = window;
658 while (!NILP (parent))
660 if (!NILP (XWINDOW (parent)->vchild) &&
661 !EQ (XWINDOW (parent)->vchild, current_ancestor))
664 current_ancestor = parent;
665 parent = XWINDOW (parent)->parent;
668 /* This is really to catch the minibuffer but we make it generic in
669 case we ever change things around to let the minibuffer be on top. */
670 if (NILP (XWINDOW (current_ancestor)->prev))
677 window_is_lowest (struct window *w)
679 Lisp_Object parent, current_ancestor, window;
681 XSETWINDOW (window, w);
683 parent = XWINDOW (window)->parent;
684 current_ancestor = window;
686 while (!NILP (parent))
688 if (!NILP (XWINDOW (parent)->vchild)
689 && !NILP (XWINDOW (current_ancestor)->next))
692 current_ancestor = parent;
693 parent = XWINDOW (parent)->parent;
699 #if 0 /* not currently used */
702 window_full_height_p (struct window *w)
704 return window_is_highest (w) && window_is_lowest (w);
710 window_truncation_on (struct window *w)
712 /* Minibuffer windows are never truncated.
713 ### is this the right way ? */
714 if (MINI_WINDOW_P (w))
717 /* Horizontally scrolled windows are truncated. */
721 /* If truncate_partial_width_windows is true and the window is not
722 the full width of the frame it is truncated. */
723 if (truncate_partial_width_windows
724 && !(window_is_leftmost (w) && window_is_rightmost (w)))
727 /* If the window's buffer's value of truncate_lines is non-nil, then
728 the window is truncated. */
729 if (!NILP (XBUFFER (w->buffer)->truncate_lines))
735 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
736 Returns Non-Nil iff the window is truncated.
740 struct window *w = decode_window (window);
742 return window_truncation_on (w) ? Qt : Qnil;
747 have_undivided_common_edge (struct window *w_right, void *closure)
749 struct window *w_left = (struct window *) closure;
750 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
751 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
752 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
753 #ifdef HAVE_SCROLLBARS
754 && (NILP (w_right->scrollbar_on_left_p)
755 || NILP (w_right->vertical_scrollbar_visible_p)
756 || ZEROP (w_right->scrollbar_width))
762 window_needs_vertical_divider_1 (struct window *w)
764 /* Never if we're on the right */
765 if (window_is_rightmost (w))
768 /* Always if draggable */
769 if (!NILP (w->vertical_divider_always_visible_p))
772 #ifdef HAVE_SCROLLBARS
773 /* Our right scrollbar is enough to separate us at the right */
774 if (NILP (w->scrollbar_on_left_p)
775 && !NILP (w->vertical_scrollbar_visible_p)
776 && !ZEROP (w->scrollbar_width))
780 /* Ok. to determine whether we need a divider on the left, we must
781 check that our right neighbor windows have scrollbars on their
782 left sides. We must check all such windows which have common
783 left edge with our window's right edge. */
784 return map_windows (XFRAME (WINDOW_FRAME (w)),
785 have_undivided_common_edge, (void*)w);
789 window_needs_vertical_divider (struct window *w)
791 if (!w->need_vertical_divider_valid_p)
793 w->need_vertical_divider_p =
794 window_needs_vertical_divider_1 (w);
795 w->need_vertical_divider_valid_p = 1;
797 return w->need_vertical_divider_p;
800 /* Called from invalidate_vertical_divider_cache_in_frame */
802 invalidate_vertical_divider_cache_in_window (struct window *w,
805 w->need_vertical_divider_valid_p = 0;
809 /* Calculate width of vertical divider, including its shadows
810 and spacing. The returned value is effectively the distance
811 between adjacent window edges. This function does not check
812 whether a window needs a vertical divider, so the returned
813 value is a "theoretical" one */
815 window_divider_width (struct window *w)
817 /* the shadow thickness can be negative. This means that the divider
818 will have a depressed look */
820 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
822 XINT (w->vertical_divider_line_width)
823 + 2 * XINT (w->vertical_divider_spacing)
824 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
826 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
830 window_scrollbar_width (struct window *w)
832 #ifdef HAVE_SCROLLBARS
833 if (!WINDOW_WIN_P (w)
836 || NILP (w->vertical_scrollbar_visible_p))
837 /* #### when does NILP (w->buffer) happen? */
840 return XINT (w->scrollbar_width);
843 #endif /* HAVE_SCROLLBARS */
846 /* Horizontal scrollbars are only active on windows with truncation
849 window_scrollbar_height (struct window *w)
851 #ifdef HAVE_SCROLLBARS
852 if (!WINDOW_WIN_P (w)
855 || NILP (w->horizontal_scrollbar_visible_p)
856 || !window_truncation_on (w))
859 return XINT (w->scrollbar_height);
862 #endif /* HAVE_SCROLLBARS */
866 window_modeline_height (struct window *w)
868 struct frame *f = XFRAME (w->frame);
871 if (MINI_WINDOW_P (w) || NILP (w->buffer))
875 else if (!WINDOW_HAS_MODELINE_P (w))
877 if (window_scrollbar_height (w))
881 modeline_height = FRAMEMETH (f, divider_height, ());
883 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
884 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
893 display_line_dynarr *dla;
895 /* We don't force a regeneration of the modeline here.
896 Instead it is now a precondition that any function calling
897 this should make sure that one of these structures is
898 up-to-date. In practice this only affects two internal
899 redisplay functions, regenerate_window and
900 regenerate_window_point_center. */
901 /* We check DESIRED_DISP because if it is valid it is more
902 up-to-date than CURRENT_DISP. For calls to this outside
903 of redisplay it doesn't matter which structure we check
904 since there is a redisplay condition that these
905 structures be identical outside of redisplay. */
906 dla = window_display_lines (w, DESIRED_DISP);
907 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
908 modeline_height = (Dynarr_atp (dla, 0)->ascent +
909 Dynarr_atp (dla, 0)->descent);
912 dla = window_display_lines (w, CURRENT_DISP);
913 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
914 modeline_height = (Dynarr_atp (dla, 0)->ascent +
915 Dynarr_atp (dla, 0)->descent);
917 /* This should be an abort except I'm not yet 100%
918 confident that it won't ever get hit (though I
919 haven't been able to trigger it). It is extremely
920 unlikely to cause any noticeable problem and even if
921 it does it will be a minor display glitch. */
922 /* #### Bullshit alert. It does get hit and it causes
923 noticeable glitches. real_current_modeline_height
924 is a kludge to fix this for 19.14. */
925 modeline_height = real_current_modeline_height (w);
928 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
929 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
933 return modeline_height;
936 /*****************************************************************************
937 margin_width_internal
939 For a given window, return the width in pixels of the specified margin.
940 ****************************************************************************/
942 margin_width_internal (struct window *w, int left_margin)
945 int window_cwidth = window_char_width (w, 1);
950 /* We might be getting called on a non-leaf. */
951 if (NILP (w->buffer))
954 /* The minibuffer never has margins. */
955 if (MINI_WINDOW_P (w))
958 XSETWINDOW (window, w);
959 b = XBUFFER (w->buffer);
960 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
961 XINT (w->right_margin_width));
963 default_face_height_and_width (window, 0, &font_width);
965 /* The left margin takes precedence over the right margin so we
966 subtract its width from the space available for the right
969 window_cwidth -= XINT (w->left_margin_width);
971 /* The margin cannot be wider than the window is. We allow the
972 value to be bigger since it is possible for the user to enlarge
973 the window such that the left margin value would no longer be too
974 big, but we won't return a value that is larger. */
975 if (margin_cwidth > window_cwidth)
976 margin_cwidth = window_cwidth;
978 /* At the user level the margin is always specified in characters.
979 Internally however it is manipulated in terms of pixels. */
980 return margin_cwidth * font_width;
984 window_left_margin_width (struct window *w)
986 return margin_width_internal (w, 1);
990 window_right_margin_width (struct window *w)
992 return margin_width_internal (w, 0);
995 /*****************************************************************************
998 The gutters of a window are those areas in the boundary defined by
999 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1000 do not contain text. Items which may be in the gutters include
1001 scrollbars, toolbars and modelines. The margin areas are not
1002 included. This is an exception made because redisplay special cases
1003 the handling of those areas in many places in such a way that
1004 including them in the gutter area would make life difficult.
1006 The size functions refer to height for the bottom and top gutters and
1007 width for the left and right gutters. The starting position
1008 functions refer to the Y coord for bottom and top gutters and the X
1009 coord for left and right gutters. All starting positions are
1010 relative to the frame, not the window.
1011 ****************************************************************************/
1014 window_top_gutter_height (struct window *w)
1016 int gutter = WINDOW_REAL_TOP_GUTTER_BOUNDS (w);
1018 if (!NILP (w->hchild) || !NILP (w->vchild))
1021 #ifdef HAVE_SCROLLBARS
1022 if (!NILP (w->scrollbar_on_top_p))
1023 return window_scrollbar_height (w) + gutter;
1030 window_bottom_gutter_height (struct window *w)
1032 int gutter = WINDOW_REAL_BOTTOM_GUTTER_BOUNDS (w);
1034 if (!NILP (w->hchild) || !NILP (w->vchild))
1037 gutter += window_modeline_height (w);
1039 #ifdef HAVE_SCROLLBARS
1040 if (NILP (w->scrollbar_on_top_p))
1041 return window_scrollbar_height (w) + gutter;
1048 window_left_gutter_width (struct window *w, int modeline)
1050 int gutter = WINDOW_REAL_LEFT_GUTTER_BOUNDS (w);
1052 if (!NILP (w->hchild) || !NILP (w->vchild))
1055 #ifdef HAVE_SCROLLBARS
1056 if (!modeline && !NILP (w->scrollbar_on_left_p))
1057 gutter += window_scrollbar_width (w);
1064 window_right_gutter_width (struct window *w, int modeline)
1066 int gutter = WINDOW_REAL_RIGHT_GUTTER_BOUNDS (w);
1068 if (!NILP (w->hchild) || !NILP (w->vchild))
1071 #ifdef HAVE_SCROLLBARS
1072 if (!modeline && NILP (w->scrollbar_on_left_p))
1073 gutter += window_scrollbar_width (w);
1076 if (window_needs_vertical_divider (w))
1077 gutter += window_divider_width (w);
1083 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1084 Return t if OBJ is a window.
1088 return WINDOWP (obj) ? Qt : Qnil;
1091 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1092 Return t if OBJ is a window which is currently visible.
1096 return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
1099 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1100 Return the window that the cursor now appears in and commands apply to.
1101 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1102 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1103 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1104 is a console, the selected frame on that console's selected device will
1105 be used. Otherwise, the selected frame is used.
1109 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1110 return Qnil; /* happens at startup */
1113 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1114 return FRAME_SELECTED_WINDOW (f);
1118 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1119 Return the last selected window that is not a minibuffer window.
1120 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1121 return the last non-minibuffer window used by that frame. If
1122 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1123 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1124 that console's selected device will be used. Otherwise, the selected
1129 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1130 return Qnil; /* happens at startup */
1133 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1134 return FRAME_LAST_NONMINIBUF_WINDOW (f);
1138 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1139 Return the window used now for minibuffers.
1140 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1141 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1142 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1143 is a console, the selected frame on that console's selected device will
1144 be used. Otherwise, the selected frame is used.
1148 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1151 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1152 Return non-nil if WINDOW is a minibuffer window.
1156 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1159 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1160 Return the first horizontal child of WINDOW, or nil.
1164 return decode_window (window)->hchild;
1167 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1168 Return the first vertical child of WINDOW, or nil.
1172 return decode_window (window)->vchild;
1175 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1176 Return the next window on the same level as WINDOW, or nil.
1180 return decode_window (window)->next;
1183 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1184 Return the previous window on the same level as WINDOW, or nil.
1188 return decode_window (window)->prev;
1191 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1192 Return the parent of WINDOW, or nil.
1196 return decode_window (window)->parent;
1199 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1200 Return non-nil if WINDOW is along the bottom of its frame.
1204 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1207 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1208 Return non-nil if WINDOW is along the top of its frame.
1212 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1215 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1216 Return non-nil if WINDOW is along the left edge of its frame.
1220 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1223 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1224 Return non-nil if WINDOW is along the right edge of its frame.
1228 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1231 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1232 Return t if position POS is currently on the frame in WINDOW.
1233 Returns nil if that position is scrolled vertically out of view.
1234 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1238 struct window *w = decode_window (window);
1239 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1241 struct buffer *buf = XBUFFER (w->buffer);
1244 posint = BUF_PT (buf);
1247 CHECK_INT_COERCE_MARKER (pos);
1248 posint = XINT (pos);
1251 if (posint < top || posint > BUF_ZV (buf))
1254 /* w->start can be out of range. If it is, do something reasonable. */
1255 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1258 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1263 decode_window (Lisp_Object window)
1266 return XWINDOW (Fselected_window (Qnil));
1268 CHECK_LIVE_WINDOW (window);
1269 return XWINDOW (window);
1272 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1273 Return the buffer that WINDOW is displaying.
1277 return decode_window (window)->buffer;
1280 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1281 Return the frame that window WINDOW is on.
1285 return decode_window (window)->frame;
1288 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1289 Return the number of default lines in WINDOW.
1290 This actually works by dividing the window's pixel height (including
1291 the modeline and horizontal scrollbar, if any) by the height of the
1292 default font; therefore, the number of displayed lines will probably
1294 Use `window-height' to get consistent results in geometry calculations.
1295 Use `window-displayed-height' to get the actual number of lines
1296 currently displayed in a window.
1300 return make_int (window_char_height (decode_window (window), 1));
1303 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1304 Return the number of lines currently displayed in WINDOW.
1305 This counts the actual number of lines displayed in WINDOW
1306 \(as opposed to `window-height'). The modeline and horizontal
1307 scrollbar do not count as lines. If there is some blank space
1308 between the end of the buffer and the end of the window, this
1309 function pretends that there are lines of text in the default
1314 return make_int (window_displayed_height (decode_window (window)));
1317 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1318 Return the height of WINDOW in pixels. Defaults to current window.
1319 This includes the window's modeline and horizontal scrollbar (if any).
1323 return make_int (decode_window (window)->pixel_height);
1326 DEFUN ("window-text-area-pixel-height",
1327 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1328 Return the height in pixels of the text-displaying portion of WINDOW.
1329 Unlike `window-pixel-height', the space occupied by the modeline and
1330 horizontal scrollbar, if any, is not counted.
1334 struct window *w = decode_window (window);
1336 return make_int (WINDOW_TEXT_HEIGHT (w));
1339 DEFUN ("window-displayed-text-pixel-height",
1340 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1341 Return the height in pixels of the text displayed in WINDOW.
1342 Unlike `window-text-area-pixel-height', any blank space below the
1343 end of the buffer is not included. If optional argument NOCLIPPED
1344 is non-nil, do not include space occupied by clipped lines.
1346 (window, noclipped))
1349 Bufpos start, eobuf;
1351 int hlimit, height, prev_height = -1;
1355 line_start_cache_dynarr *cache;
1358 window = Fselected_window (Qnil);
1360 CHECK_LIVE_WINDOW (window);
1361 w = XWINDOW (window);
1363 start = marker_position (w->start[CURRENT_DISP]);
1364 hlimit = WINDOW_TEXT_HEIGHT (w);
1365 eobuf = BUF_ZV (XBUFFER (w->buffer));
1367 default_face_height_and_width (window, &defheight, NULL);
1369 /* guess lines needed in line start cache + a few extra */
1370 needed = (hlimit + defheight-1) / defheight + 3;
1373 elt = point_in_line_start_cache (w, start, needed);
1374 assert (elt >= 0); /* in the cache */
1376 cache = w->line_start_cache;
1377 nelt = Dynarr_length (cache);
1380 for (i = elt; i < nelt; i++) {
1381 line = Dynarr_atp (cache, i)->height;
1383 if (height + line > hlimit)
1384 return make_int (!NILP (noclipped) ? height : hlimit);
1388 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1389 return make_int (height);
1392 /* get here => need more cache lines. try again. */
1393 assert(height > prev_height); /* progress? */
1394 prev_height = height;
1396 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1399 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1402 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1403 Return the number of display columns in WINDOW.
1404 This is the width that is usable columns available for text in WINDOW.
1408 return make_int (window_char_width (decode_window (window), 0));
1411 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1412 Return the width of WINDOW in pixels. Defaults to current window.
1416 return make_int (decode_window (window)->pixel_width);
1419 DEFUN ("window-text-area-pixel-width",
1420 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1421 Return the width in pixels of the text-displaying portion of WINDOW.
1422 Unlike `window-pixel-width', the space occupied by the vertical
1423 scrollbar or divider, if any, is not counted.
1427 struct window *w = decode_window (window);
1429 return make_int (WINDOW_TEXT_WIDTH (w));
1432 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1433 Return the number of columns by which WINDOW is scrolled from left margin.
1437 return make_int (decode_window (window)->hscroll);
1440 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1441 Return the horizontal scrolling ammount of WINDOW's modeline.
1442 If the window has no modeline, return nil.
1446 struct window *w = decode_window (window);
1448 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
1452 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1453 Set the horizontal scrolling ammount of WINDOW's modeline to NCOL.
1454 If NCOL is negative, it will silently be forced to 0.
1455 If the window has no modeline, return nil. Otherwise, return the actual
1460 struct window *w = decode_window (window);
1462 if (WINDOW_HAS_MODELINE_P (w))
1467 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
1468 if (ncols != w->modeline_hscroll)
1470 MARK_MODELINE_CHANGED;
1471 w->modeline_hscroll = ncols;
1473 return make_int ((int) ncols);
1479 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1480 Set number of columns WINDOW is scrolled from left margin to NCOL.
1481 NCOL should be zero or positive.
1489 ncols = XINT (ncol);
1490 if (ncols < 0) ncols = 0;
1491 w = decode_window (window);
1492 if (w->hscroll != ncols)
1493 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1498 #if 0 /* bogus FSF crock */
1500 xxDEFUN ("window-redisplay-end-trigger",
1501 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1502 Return WINDOW's redisplay end trigger value.
1503 See `set-window-redisplay-end-trigger' for more information.
1507 return decode_window (window)->redisplay_end_trigger;
1510 xxDEFUN ("set-window-redisplay-end-trigger",
1511 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1512 Set WINDOW's redisplay end trigger value to VALUE.
1513 VALUE should be a buffer position (typically a marker) or nil.
1514 If it is a buffer position, then if redisplay in WINDOW reaches a position
1515 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1516 with two arguments: WINDOW, and the end trigger value.
1517 Afterwards the end-trigger value is reset to nil.
1521 return (decode_window (window)->redisplay_end_trigger = value);
1526 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1527 Return a list of the pixel edge coordinates of WINDOW.
1528 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1529 The frame toolbars and menubars are considered to be outside of this area.
1533 struct window *w = decode_window (window);
1534 struct frame *f = XFRAME (w->frame);
1536 int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
1537 int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
1539 return list4 (make_int (left),
1541 make_int (left + w->pixel_width),
1542 make_int (top + w->pixel_height));
1545 DEFUN ("window-text-area-pixel-edges",
1546 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1547 Return a list of the pixel edge coordinates of the text area of WINDOW.
1548 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1549 top left corner of the window.
1553 struct window *w = decode_window (window);
1555 int left = window_left_gutter_width (w, /* modeline = */ 0);
1556 int top = window_top_gutter_height (w);
1557 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1558 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1560 return list4 (make_int (left),
1566 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1567 Return current value of point in WINDOW.
1568 For a nonselected window, this is the value point would have
1569 if that window were selected.
1571 Note that, when WINDOW is the selected window and its buffer
1572 is also currently selected, the value returned is the same as (point).
1573 It would be more strictly correct to return the `top-level' value
1574 of point, outside of any save-excursion forms.
1575 But that is hard to define.
1579 struct window *w = decode_window (window);
1581 /* The special check for current buffer is necessary for this
1582 function to work as defined when called within an excursion. */
1583 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1584 && current_buffer == XBUFFER (w->buffer))
1585 return Fpoint (Qnil);
1586 return Fmarker_position (w->pointm[CURRENT_DISP]);
1589 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1590 Return position at which display currently starts in WINDOW.
1591 This is updated by redisplay or by calling `set-window-start'.
1595 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1598 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1599 Return position at which display currently ends in WINDOW.
1600 This is updated by redisplay, when it runs to completion.
1601 Simply changing the buffer text or setting `window-start'
1602 does not update this value.
1603 If GUARANTEE is non-nil, then the return value is guaranteed to be
1604 the value of window-end at the end of the next full redisplay assuming
1605 nothing else changes in the meantime. This function is potentially much
1606 slower with this flag set.
1608 (window, guarantee))
1610 struct window *w = decode_window (window);
1612 if (NILP (guarantee))
1617 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1621 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1622 return make_int (end_of_last_line (w, startp));
1626 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1627 Make point value in WINDOW be at position POS in WINDOW's buffer.
1631 struct window *w = decode_window (window);
1633 CHECK_INT_COERCE_MARKER (pos);
1634 if (w == XWINDOW (Fselected_window (Qnil)))
1635 Fgoto_char (pos, Qnil);
1637 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1643 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1644 Make display in WINDOW start at position POS in WINDOW's buffer.
1645 Optional third arg NOFORCE non-nil inhibits next redisplay
1646 from overriding motion of point in order to display at this exact start.
1648 (window, pos, noforce))
1650 struct window *w = decode_window (window);
1652 CHECK_INT_COERCE_MARKER (pos);
1653 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1654 /* this is not right, but much easier than doing what is right. */
1655 /* w->start_at_line_beg = 0; */
1656 /* WTF is the above supposed to mean? GE */
1657 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1658 marker_position (w->start[CURRENT_DISP]));
1661 w->redo_modeline = 1;
1662 SET_LAST_MODIFIED (w, 0);
1663 SET_LAST_FACECHANGE (w);
1665 MARK_WINDOWS_CHANGED (w);
1670 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1671 Return WINDOW's dedicated object, usually t or nil.
1672 See also `set-window-dedicated-p'.
1676 return decode_window (window)->dedicated;
1679 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1680 Control whether WINDOW is dedicated to the buffer it displays.
1681 If it is dedicated, Emacs will not automatically change
1682 which buffer appears in it.
1683 The second argument is the new value for the dedication flag;
1688 struct window *w = decode_window (window);
1690 w->dedicated = NILP (arg) ? Qnil : Qt;
1692 return w->dedicated;
1695 /* FSFmacs has window-display-table here. We have display table as a
1699 /* Record info on buffer window w is displaying
1700 when it is about to cease to display that buffer. */
1702 unshow_buffer (struct window *w)
1704 Lisp_Object buf = w->buffer;
1706 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1709 /* FSF disables this check, so I'll do it too. I hope it won't
1710 break things. --ben */
1712 if (w == XWINDOW (Fselected_window (Qnil))
1713 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1714 /* Do this except when the selected window's buffer
1715 is being removed from some other window. */
1717 /* last_window_start records the start position that this buffer
1718 had in the last window to be disconnected from it.
1719 Now that this statement is unconditional,
1720 it is possible for the buffer to be displayed in the
1721 selected window, while last_window_start reflects another
1722 window which was recently showing the same buffer.
1723 Some people might say that might be a good thing. Let's see. */
1724 XBUFFER (buf)->last_window_start =
1725 marker_position (w->start[CURRENT_DISP]);
1727 /* Point in the selected window's buffer
1728 is actually stored in that buffer, and the window's pointm isn't used.
1729 So don't clobber point in that buffer. */
1730 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1732 struct buffer *b= XBUFFER (buf);
1733 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1734 marker_position (w->pointm[CURRENT_DISP]),
1739 /* Put REPLACEMENT into the window structure in place of OLD. */
1741 replace_window (Lisp_Object old, Lisp_Object replacement)
1744 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1746 /* If OLD is its frame's root_window, then replacement is the new
1747 root_window for that frame. */
1749 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1750 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1752 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1753 WINDOW_TOP (p) = WINDOW_TOP (o);
1754 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1755 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1757 p->next = tem = o->next;
1759 XWINDOW (tem)->prev = replacement;
1761 p->prev = tem = o->prev;
1763 XWINDOW (tem)->next = replacement;
1765 p->parent = tem = o->parent;
1768 if (EQ (XWINDOW (tem)->vchild, old))
1769 XWINDOW (tem)->vchild = replacement;
1770 if (EQ (XWINDOW (tem)->hchild, old))
1771 XWINDOW (tem)->hchild = replacement;
1774 /* #### Here, if replacement is a vertical combination
1775 and so is its new parent, we should make replacement's
1776 children be children of that parent instead. */
1779 /* we're deleting W; set the structure of W to indicate this. */
1782 mark_window_as_deleted (struct window *w)
1785 (while t (split-window) (delete-window))
1786 we end up with a tree of deleted windows which are all connected
1787 through the `next' slot. This might not seem so bad, as they're
1788 deleted, and will presumably be GCed - but if even *one* of those
1789 windows is still being pointed to, by the user, or by a window
1790 configuration, then *all* of those windows stick around.
1792 Since the window-configuration code doesn't need any of the
1793 pointers to other windows (they are all recreated from the
1794 window-config data), we set them all to nil so that we
1795 are able to collect more actual garbage.
1805 /* Free the extra data structures attached to windows immediately so
1806 they don't sit around consuming excess space. They will be
1807 reinitialized by the window-configuration code as necessary. */
1808 finalize_window ((void *) w, 0);
1811 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1812 Remove WINDOW from the display. Default is selected window.
1813 If window is the only one on the frame, the frame is destroyed.
1814 Normally, you cannot delete the last non-minibuffer-only frame (you must
1815 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1816 second argument FORCE is non-nil, you can delete the last frame. (This
1817 will automatically call `save-buffers-kill-emacs'.)
1821 /* This function can GC if this is the only window in the frame */
1829 /* Note: this function is called by other C code on non-leaf
1832 /* Do the equivalent of decode_window() but don't error out on
1833 deleted window; it's OK to delete an already-deleted window. */
1835 window = Fselected_window (Qnil);
1837 CHECK_WINDOW (window);
1838 w = XWINDOW (window);
1840 /* It's okay to delete an already-deleted window. */
1841 if (! WINDOW_LIVE_P (w))
1844 frame = WINDOW_FRAME (w);
1846 d = XDEVICE (FRAME_DEVICE (f));
1848 if (TOP_LEVEL_WINDOW_P (w))
1850 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1851 /* this frame isn't fully initialized yet; don't blow up. */
1854 if (MINI_WINDOW_P (XWINDOW (window)))
1855 error ("Attempt to delete the minibuffer window");
1857 /* It has been suggested that it's a good thing for C-x 0 to have this
1858 behavior, but not such a good idea for #'delete-window to have it.
1859 Maybe C-x 0 should be bound to something else, or maybe frame
1860 deletion should only happen when this is called interactively.
1862 delete_frame_internal (f, !NILP (force), 0, 0);
1866 /* At this point, we know the window has a parent. */
1868 par = XWINDOW (parent);
1870 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1871 /* It's quite likely that deleting a window will result in
1872 subwindows needing to be deleted also (since they are cached
1873 per-window). So we mark them as changed, so that the cachels will
1874 get reset by redisplay and thus deleted subwindows can get
1876 MARK_FRAME_SUBWINDOWS_CHANGED (f);
1878 /* Are we trying to delete any frame's selected window?
1879 Note that we could be dealing with a non-leaf window
1880 where the selected window is one of our children.
1881 So, we check by scanning all the ancestors of the
1882 frame's selected window and comparing each one with
1885 Lisp_Object pwindow;
1887 pwindow = FRAME_SELECTED_WINDOW (f);
1889 while (!NILP (pwindow))
1891 if (EQ (window, pwindow))
1893 pwindow = XWINDOW (pwindow)->parent;
1896 if (EQ (window, pwindow))
1898 /* OK, we found it. */
1899 Lisp_Object alternative;
1900 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1902 /* If we're about to delete the selected window on the
1903 selected frame, then we should use Fselect_window to select
1904 the new window. On the other hand, if we're about to
1905 delete the selected window on any other frame, we shouldn't do
1906 anything but set the frame's selected_window slot. */
1907 if (EQ (frame, Fselected_frame (Qnil)))
1908 Fselect_window (alternative, Qnil);
1910 set_frame_selected_window (f, alternative);
1914 /* w->buffer is nil in a non-leaf window; in this case,
1915 get rid of the markers we maintain that point into that buffer. */
1916 if (!NILP (w->buffer))
1919 unchain_marker (w->pointm[CURRENT_DISP]);
1920 unchain_marker (w->pointm[DESIRED_DISP]);
1921 unchain_marker (w->pointm[CMOTION_DISP]);
1922 unchain_marker (w->start[CURRENT_DISP]);
1923 unchain_marker (w->start[DESIRED_DISP]);
1924 unchain_marker (w->start[CMOTION_DISP]);
1925 unchain_marker (w->sb_point);
1926 /* This breaks set-window-configuration if windows in the saved
1927 configuration get deleted and multiple frames are in use. */
1928 /* w->buffer = Qnil; */
1931 /* close up the hole in the sibling list */
1932 if (!NILP (w->next))
1933 XWINDOW (w->next)->prev = w->prev;
1934 if (!NILP (w->prev))
1935 XWINDOW (w->prev)->next = w->next;
1936 if (EQ (window, par->hchild))
1937 par->hchild = w->next;
1938 if (EQ (window, par->vchild))
1939 par->vchild = w->next;
1941 /* Find one of our siblings to give our space to. */
1943 Lisp_Object sib = w->prev;
1946 /* If w gives its space to its next sibling, that sibling needs
1947 to have its top/left side pulled back to where w's is.
1948 set_window_{height,width} will re-position the sibling's
1951 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1952 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1955 /* Stretch that sibling. */
1956 if (!NILP (par->vchild))
1957 set_window_pixheight
1958 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1959 if (!NILP (par->hchild))
1961 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1964 /* If parent now has only one child,
1965 put the child into the parent's place. */
1967 Lisp_Object parchild = par->hchild;
1968 if (NILP (parchild))
1969 parchild = par->vchild;
1970 if (NILP (XWINDOW (parchild)->next))
1972 replace_window (parent, parchild);
1973 mark_window_as_deleted (XWINDOW (parent));
1977 /* Since we may be deleting combination windows, we must make sure that
1978 not only W but all its children have been marked as deleted. */
1979 if (!NILP (w->hchild))
1980 delete_all_subwindows (XWINDOW (w->hchild));
1981 else if (!NILP (w->vchild))
1982 delete_all_subwindows (XWINDOW (w->vchild));
1984 mark_window_as_deleted (w);
1986 f->mirror_dirty = 1;
1991 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1992 Return next window after WINDOW in canonical ordering of windows.
1993 If omitted, WINDOW defaults to the selected window.
1995 Optional second arg MINIBUF t means count the minibuffer window even
1996 if not active. MINIBUF nil or omitted means count the minibuffer iff
1997 it is active. MINIBUF neither t nor nil means not to count the
1998 minibuffer even if it is active.
2000 Several frames may share a single minibuffer; if the minibuffer
2001 counts, all windows on all frames that share that minibuffer count
2002 too. Therefore, `next-window' can be used to iterate through the
2003 set of windows even when the minibuffer is on another frame. If the
2004 minibuffer does not count, only windows from WINDOW's frame count.
2006 Optional third arg ALL-FRAMES t means include windows on all frames.
2007 ALL-FRAMES nil or omitted means cycle within the frames as specified
2008 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2009 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2010 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2011 Anything else means restrict to WINDOW's frame.
2013 Optional fourth argument CONSOLE controls which consoles or devices the
2014 returned window may be on. If CONSOLE is a console, return windows only
2015 on that console. If CONSOLE is a device, return windows only on that
2016 device. If CONSOLE is a console type, return windows only on consoles
2017 of that type. If CONSOLE is 'window-system, return any windows on any
2018 window-system consoles. If CONSOLE is nil or omitted, return windows only
2019 on WINDOW's console. Otherwise, all windows are considered.
2021 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2022 can use `next-window' to iterate through the entire cycle of acceptable
2023 windows, eventually ending up back at the window you started with.
2024 `previous-window' traverses the same cycle, in the reverse order.
2026 (window, minibuf, all_frames, console))
2029 Lisp_Object start_window;
2032 window = Fselected_window (Qnil);
2034 CHECK_LIVE_WINDOW (window);
2036 start_window = window;
2038 /* minibuf == nil may or may not include minibuffers.
2039 Decide if it does. */
2041 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2042 else if (! EQ (minibuf, Qt))
2044 /* Now minibuf can be t => count all minibuffer windows,
2045 lambda => count none of them,
2046 or a specific minibuffer window (the active one) to count. */
2048 /* all_frames == nil doesn't specify which frames to include. */
2049 if (NILP (all_frames))
2050 all_frames = (! EQ (minibuf, Qlambda)
2051 ? (FRAME_MINIBUF_WINDOW
2054 (XWINDOW (window)))))
2056 else if (EQ (all_frames, Qvisible))
2058 else if (ZEROP (all_frames))
2060 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2061 /* If all_frames is a frame and window arg isn't on that frame, just
2062 return the first window on the frame. */
2063 return frame_first_window (XFRAME (all_frames));
2064 else if (! EQ (all_frames, Qt))
2066 /* Now all_frames is t meaning search all frames,
2067 nil meaning search just current frame,
2068 visible meaning search just visible frames,
2069 0 meaning search visible and iconified frames,
2070 or a window, meaning search the frame that window belongs to. */
2072 /* Do this loop at least once, to get the next window, and perhaps
2073 again, if we hit the minibuffer and that is not acceptable. */
2076 /* Find a window that actually has a next one. This loop
2077 climbs up the tree. */
2078 while (tem = XWINDOW (window)->next, NILP (tem))
2079 if (tem = XWINDOW (window)->parent, !NILP (tem))
2081 else /* window must be minibuffer window now */
2083 /* We've reached the end of this frame.
2084 Which other frames are acceptable? */
2085 tem = WINDOW_FRAME (XWINDOW (window));
2087 if (! NILP (all_frames))
2092 tem = next_frame (tem, all_frames, console);
2093 /* In the case where the minibuffer is active,
2094 and we include its frame as well as the selected one,
2095 next_frame may get stuck in that frame.
2096 If that happens, go back to the selected frame
2097 so we can complete the cycle. */
2099 XSETFRAME (tem, selected_frame ());
2102 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2108 /* If we're in a combination window, find its first child and
2109 recurse on that. Otherwise, we've found the window we want. */
2112 if (!NILP (XWINDOW (window)->hchild))
2113 window = XWINDOW (window)->hchild;
2114 else if (!NILP (XWINDOW (window)->vchild))
2115 window = XWINDOW (window)->vchild;
2119 /* "acceptable" is the correct spelling. */
2120 /* Which windows are acceptable?
2121 Exit the loop and accept this window if
2122 this isn't a minibuffer window,
2123 or we're accepting all minibuffer windows,
2124 or this is the active minibuffer and we are accepting that one, or
2125 we've come all the way around and we're back at the original window. */
2126 while (MINI_WINDOW_P (XWINDOW (window))
2127 && ! EQ (minibuf, Qt)
2128 && ! EQ (minibuf, window)
2129 && ! EQ (window, start_window));
2134 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2135 Return the window preceding WINDOW in canonical ordering of windows.
2136 If omitted, WINDOW defaults to the selected window.
2138 Optional second arg MINIBUF t means count the minibuffer window even
2139 if not active. MINIBUF nil or omitted means count the minibuffer iff
2140 it is active. MINIBUF neither t nor nil means not to count the
2141 minibuffer even if it is active.
2143 Several frames may share a single minibuffer; if the minibuffer
2144 counts, all windows on all frames that share that minibuffer count
2145 too. Therefore, `previous-window' can be used to iterate through
2146 the set of windows even when the minibuffer is on another frame. If
2147 the minibuffer does not count, only windows from WINDOW's frame count
2149 If optional third arg ALL-FRAMES t means include windows on all frames.
2150 ALL-FRAMES nil or omitted means cycle within the frames as specified
2151 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2152 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2153 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2154 Anything else means restrict to WINDOW's frame.
2156 Optional fourth argument CONSOLE controls which consoles or devices the
2157 returned window may be on. If CONSOLE is a console, return windows only
2158 on that console. If CONSOLE is a device, return windows only on that
2159 device. If CONSOLE is a console type, return windows only on consoles
2160 of that type. If CONSOLE is 'window-system, return any windows on any
2161 window-system consoles. If CONSOLE is nil or omitted, return windows only
2162 on WINDOW's console. Otherwise, all windows are considered.
2164 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2165 can use `previous-window' to iterate through the entire cycle of acceptable
2166 windows, eventually ending up back at the window you started with.
2167 `next-window' traverses the same cycle, in the reverse order.
2169 (window, minibuf, all_frames, console))
2172 Lisp_Object start_window;
2175 window = Fselected_window (Qnil);
2177 CHECK_LIVE_WINDOW (window);
2179 start_window = window;
2181 /* minibuf == nil may or may not include minibuffers.
2182 Decide if it does. */
2184 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2185 else if (! EQ (minibuf, Qt))
2187 /* Now minibuf can be t => count all minibuffer windows,
2188 lambda => count none of them,
2189 or a specific minibuffer window (the active one) to count. */
2191 /* all_frames == nil doesn't specify which frames to include.
2192 Decide which frames it includes. */
2193 if (NILP (all_frames))
2194 all_frames = (! EQ (minibuf, Qlambda)
2195 ? (FRAME_MINIBUF_WINDOW
2198 (XWINDOW (window)))))
2200 else if (EQ (all_frames, Qvisible))
2202 else if (ZEROP (all_frames))
2204 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2205 /* If all_frames is a frame and window arg isn't on that frame, just
2206 return the first window on the frame. */
2207 return frame_first_window (XFRAME (all_frames));
2208 else if (! EQ (all_frames, Qt))
2210 /* Now all_frames is t meaning search all frames,
2211 nil meaning search just current frame,
2212 visible meaning search just visible frames,
2213 0 meaning search visible and iconified frames,
2214 or a window, meaning search the frame that window belongs to. */
2216 /* Do this loop at least once, to get the next window, and perhaps
2217 again, if we hit the minibuffer and that is not acceptable. */
2220 /* Find a window that actually has a next one. This loop
2221 climbs up the tree. */
2222 while (tem = XWINDOW (window)->prev, NILP (tem))
2223 if (tem = XWINDOW (window)->parent, !NILP (tem))
2225 else /* window must be minibuffer window now */
2227 /* We have found the top window on the frame.
2228 Which frames are acceptable? */
2229 tem = WINDOW_FRAME (XWINDOW (window));
2231 if (! NILP (all_frames))
2232 /* It's actually important that we use prev_frame here,
2233 rather than next_frame. All the windows acceptable
2234 according to the given parameters should form a ring;
2235 Fnext_window and Fprevious_window should go back and
2236 forth around the ring. If we use next_frame here,
2237 then Fnext_window and Fprevious_window take different
2238 paths through the set of acceptable windows.
2239 window_loop assumes that these `ring' requirement are
2245 tem = prev_frame (tem, all_frames, console);
2246 /* In the case where the minibuffer is active,
2247 and we include its frame as well as the selected one,
2248 next_frame may get stuck in that frame.
2249 If that happens, go back to the selected frame
2250 so we can complete the cycle. */
2252 XSETFRAME (tem, selected_frame ());
2255 /* If this frame has a minibuffer, find that window first,
2256 because it is conceptually the last window in that frame. */
2257 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2258 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2260 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2267 /* If we're in a combination window, find its first child and
2268 recurse on that. Otherwise, we've found the window we want. */
2271 if (!NILP (XWINDOW (window)->hchild))
2272 window = XWINDOW (window)->hchild;
2273 else if (!NILP (XWINDOW (window)->vchild))
2274 window = XWINDOW (window)->vchild;
2276 while (tem = XWINDOW (window)->next, !NILP (tem))
2280 /* Which windows are acceptable?
2281 Exit the loop and accept this window if
2282 this isn't a minibuffer window,
2283 or we're accepting all minibuffer windows,
2284 or this is the active minibuffer and we are accepting that one, or
2285 we've come all the way around and we're back at the original window. */
2286 while (MINI_WINDOW_P (XWINDOW (window))
2287 && ! EQ (minibuf, Qt)
2288 && ! EQ (minibuf, window)
2289 && ! EQ (window, start_window));
2294 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2295 Return the next window which is vertically after WINDOW.
2300 struct window *w = decode_window (window);
2301 XSETWINDOW (window, w);
2303 if (MINI_WINDOW_P (XWINDOW (window)))
2306 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2308 if (EQ (window, root))
2311 if (!NILP (XWINDOW (window)->hchild))
2312 window = XWINDOW (window)->hchild;
2313 else if (!NILP (XWINDOW (window)->vchild))
2314 window = XWINDOW (window)->vchild;
2321 if (!NILP (XWINDOW (window)->parent) &&
2322 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2324 if (!NILP (XWINDOW (window)->next))
2325 return XWINDOW (window)->next;
2327 window = XWINDOW (window)->parent;
2330 window = XWINDOW (window)->parent;
2332 while (!EQ (window, root));
2335 if (!NILP (XWINDOW (window)->hchild))
2336 window = XWINDOW (window)->hchild;
2337 else if (!NILP (XWINDOW (window)->vchild))
2338 window = XWINDOW (window)->vchild;
2343 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2344 Select the N'th different window on this frame.
2345 All windows on current frame are arranged in a cyclic order.
2346 This command selects the window N steps away in that order.
2347 A negative N moves in the opposite order.
2349 If optional argument FRAME is `visible', search all visible frames.
2350 If FRAME is 0, search all visible and iconified frames.
2351 If FRAME is t, search all frames.
2352 If FRAME is nil, search only the selected frame.
2353 If FRAME is a frame, search only that frame.
2355 Optional third argument CONSOLE controls which consoles or devices the
2356 returned window may be on. If CONSOLE is a console, return windows only
2357 on that console. If CONSOLE is a device, return windows only on that
2358 device. If CONSOLE is a console type, return windows only on consoles
2359 of that type. If CONSOLE is 'window-system, return any windows on any
2360 window-system consoles. If CONSOLE is nil or omitted, return windows only
2361 on FRAME'S console, or on the selected console if FRAME is not a frame.
2362 Otherwise, all windows are considered.
2364 (n, frame, console))
2370 w = Fselected_window (Qnil);
2375 w = Fnext_window (w, Qnil, frame, console);
2380 w = Fprevious_window (w, Qnil, frame, console);
2383 Fselect_window (w, Qnil);
2388 /* Look at all windows, performing an operation specified by TYPE
2391 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2392 frame. If FRAMES is a frame, just look at windows on that frame.
2393 If MINI is non-zero, perform the operation on minibuffer windows too.
2399 GET_BUFFER_WINDOW, /* Arg is buffer */
2400 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2401 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2402 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2404 UNSHOW_BUFFER, /* Arg is buffer */
2405 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2406 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2410 window_loop (enum window_loop type,
2415 Lisp_Object console)
2417 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2419 Lisp_Object best_window = Qnil;
2420 Lisp_Object next_window;
2421 Lisp_Object last_window;
2422 struct frame *frame;
2423 Lisp_Object frame_arg = Qt;
2424 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2425 /* #### I think the change of "precomputing" last_window and next_window
2426 * #### catch the lossage this is meant(?) to punt on...
2429 Lisp_Object devcons, concons;
2431 /* FRAME_ARG is Qlambda to stick to one frame,
2432 Qvisible to consider all visible frames,
2435 /* If we're only looping through windows on a particular frame,
2436 FRAME points to that frame. If we're looping through windows
2437 on all frames, FRAME is 0. */
2439 if (FRAMEP (frames))
2440 frame = XFRAME (frames);
2441 else if (NILP (frames))
2442 frame = selected_frame ();
2446 frame_arg = Qlambda;
2447 else if (ZEROP (frames))
2449 else if (EQ (frames, Qvisible))
2452 DEVICE_LOOP_NO_BREAK (devcons, concons)
2454 Lisp_Object device = XCAR (devcons);
2455 Lisp_Object the_frame;
2458 XSETFRAME (the_frame, frame);
2460 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2462 if (NILP (the_frame))
2465 if (!device_matches_console_spec (the_frame, device, console))
2468 /* Pick a window to start with. */
2472 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2474 /* Figure out the last window we're going to mess with. Since
2475 Fnext_window, given the same options, is guaranteed to go in a
2476 ring, we can just use Fprevious_window to find the last one.
2478 We can't just wait until we hit the first window again,
2479 because it might be deleted. */
2481 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2486 struct window *p = XWINDOW (w);
2487 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2489 /* Pick the next window now, since some operations will delete
2490 the current window. */
2491 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2493 /* #### Still needed ?? */
2494 /* Given the outstanding quality of the rest of this code,
2495 I feel no shame about putting this piece of shit in. */
2496 if (++lose_lose >= 500)
2499 /* Note that we do not pay attention here to whether
2500 the frame is visible, since Fnext_window skips non-visible frames
2501 if that is desired, under the control of frame_arg. */
2502 if (! MINI_WINDOW_P (p)
2503 || (mini && minibuf_level > 0))
2506 case GET_BUFFER_WINDOW:
2508 if (XBUFFER (p->buffer) == XBUFFER (obj))
2513 case GET_BUFFER_WINDOW_COUNT:
2515 if (XBUFFER (p->buffer) == XBUFFER (obj))
2520 case GET_LRU_WINDOW:
2522 /* t as arg means consider only full-width windows */
2524 && !window_full_width_p (p))
2526 /* Ignore dedicated windows and minibuffers. */
2527 if (MINI_WINDOW_P (p)
2528 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2530 if (NILP (best_window)
2531 || (XINT (XWINDOW (best_window)->use_time)
2532 > XINT (p->use_time)))
2537 case GET_BUFFER_MRU_WINDOW:
2539 /* #### what about the first check in GET_LRU_WINDOW? */
2540 /* Ignore dedicated windows and minibuffers. */
2541 if (MINI_WINDOW_P (p)
2542 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2545 if (XBUFFER (p->buffer) == XBUFFER (obj))
2547 if (NILP (best_window)
2548 || (XINT (XWINDOW (best_window)->use_time)
2549 < XINT (p->use_time)))
2555 case DELETE_OTHER_WINDOWS:
2557 /* Don't delete the last window on a frame; this can
2558 happen when the minibuffer is selected, and would
2559 cause the frame to be deleted. */
2560 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2561 Fdelete_window (w, Qnil);
2565 case DELETE_BUFFER_WINDOWS:
2567 if (EQ (p->buffer, obj))
2569 struct frame *f = XFRAME (WINDOW_FRAME (p));
2571 /* If this window is dedicated, and in a frame
2572 of its own, kill the frame. */
2573 if (EQ (w, FRAME_ROOT_WINDOW (f))
2574 && !NILP (p->dedicated)
2575 && other_visible_frames (f))
2577 /* Skip the other windows on this frame.
2578 There might be one, the minibuffer! */
2579 if (! EQ (w, last_window))
2580 while (f == XFRAME (WINDOW_FRAME
2581 (XWINDOW (next_window))))
2583 /* As we go, check for the end of the
2584 loop. We mustn't start going
2585 around a second time. */
2586 if (EQ (next_window, last_window))
2591 next_window = Fnext_window (next_window,
2595 /* Now we can safely delete the frame. */
2596 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2599 /* If we're deleting the buffer displayed in
2600 the only window on the frame, find a new
2601 buffer to display there. */
2602 if (NILP (p->parent))
2604 Lisp_Object new_buffer;
2605 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2606 if (NILP (new_buffer))
2607 new_buffer = Fget_buffer_create (QSscratch);
2608 Fset_window_buffer (w, new_buffer);
2609 if (EQ (w, Fselected_window (Qnil)))
2610 Fset_buffer (p->buffer);
2613 Fdelete_window (w, Qnil);
2618 case GET_LARGEST_WINDOW:
2620 /* Ignore dedicated windows and minibuffers. */
2621 if (MINI_WINDOW_P (p)
2622 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2625 /* write the check as follows to avoid tripping
2626 error_check_window() --ben */
2627 struct window *b = NILP (best_window) ? 0 :
2628 XWINDOW (best_window);
2629 if (NILP (best_window)
2630 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2631 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2639 if (EQ (p->buffer, obj))
2641 /* Find another buffer to show in this window. */
2642 Lisp_Object another_buffer =
2643 Fother_buffer (obj, Qnil, Qnil);
2644 if (NILP (another_buffer))
2646 = Fget_buffer_create (QSscratch);
2647 /* If this window is dedicated, and in a frame
2648 of its own, kill the frame. */
2649 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2650 && !NILP (p->dedicated)
2651 && other_visible_frames (w_frame))
2653 /* Skip the other windows on this frame.
2654 There might be one, the minibuffer! */
2655 if (! EQ (w, last_window))
2656 while (w_frame == XFRAME (WINDOW_FRAME
2657 (XWINDOW (next_window))))
2659 /* As we go, check for the end of the
2660 loop. We mustn't start going
2661 around a second time. */
2662 if (EQ (next_window, last_window))
2667 next_window = Fnext_window (next_window,
2671 /* Now we can safely delete the frame. */
2672 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2677 /* Otherwise show a different buffer in the
2679 p->dedicated = Qnil;
2680 Fset_window_buffer (w, another_buffer);
2681 if (EQ (w, Fselected_window (Qnil)))
2682 Fset_buffer (p->buffer);
2692 if (EQ (w, last_window))
2699 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2702 #if 0 /* not currently used */
2705 buffer_window_count (struct buffer *b, struct frame *f)
2707 Lisp_Object buffer, frame;
2709 XSETFRAME (frame, f);
2710 XSETBUFFER (buffer, b);
2712 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2717 buffer_window_mru (struct window *w)
2719 Lisp_Object window =
2720 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2724 else if (XWINDOW (window) == w)
2733 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2734 Return the window least recently selected or used for display.
2735 If optional argument FRAME is `visible', search all visible frames.
2736 If FRAME is 0, search all visible and iconified frames.
2737 If FRAME is t, search all frames.
2738 If FRAME is nil, search only the selected frame.
2739 If FRAME is a frame, search only that frame.
2741 Optional second argument CONSOLE controls which consoles or devices the
2742 returned window may be on. If CONSOLE is a console, return windows only
2743 on that console. If CONSOLE is a device, return windows only on that
2744 device. If CONSOLE is a console type, return windows only on consoles
2745 of that type. If CONSOLE is 'window-system, return any windows on any
2746 window-system consoles. If CONSOLE is nil or omitted, return windows only
2747 on FRAME'S console, or on the selected console if FRAME is not a frame.
2748 Otherwise, all windows are considered.
2753 /* First try for a non-dedicated window that is full-width */
2754 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2755 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2758 /* Then try for any non-dedicated window */
2759 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2760 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2764 /* FSFmacs never returns a dedicated window here. If we do,
2765 it makes `display-buffer' not work right. #### All of this
2766 shit is so disgusting and awful that it needs to be rethought
2768 /* then try for a dedicated window that is full-width */
2769 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2770 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2773 /* If none of them, then all windows, dedicated or not. */
2774 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2776 /* At this point we damn well better have found something. */
2777 if (NILP (w)) abort ();
2783 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2784 Return the window largest in area.
2785 If optional argument FRAME is `visible', search all visible frames.
2786 If FRAME is 0, search all visible and iconified frames.
2787 If FRAME is t, search all frames.
2788 If FRAME is nil, search only the selected frame.
2789 If FRAME is a frame, search only that frame.
2791 Optional second argument CONSOLE controls which consoles or devices the
2792 returned window may be on. If CONSOLE is a console, return windows only
2793 on that console. If CONSOLE is a device, return windows only on that
2794 device. If CONSOLE is a console type, return windows only on consoles
2795 of that type. If CONSOLE is 'window-system, return any windows on any
2796 window-system consoles. If CONSOLE is nil or omitted, return windows only
2797 on FRAME'S console, or on the selected console if FRAME is not a frame.
2798 Otherwise, all windows are considered.
2802 /* Don't search dedicated windows because FSFmacs doesn't.
2803 This stuff is all black magic so don't try to apply common
2805 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2808 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2809 Return a window currently displaying BUFFER, or nil if none.
2810 If optional argument FRAME is `visible', search all visible frames.
2811 If optional argument FRAME is 0, search all visible and iconified frames.
2812 If FRAME is t, search all frames.
2813 If FRAME is nil, search only the selected frame.
2814 If FRAME is a frame, search only that frame.
2816 Optional third argument CONSOLE controls which consoles or devices the
2817 returned window may be on. If CONSOLE is a console, return windows only
2818 on that console. If CONSOLE is a device, return windows only on that
2819 device. If CONSOLE is a console type, return windows only on consoles
2820 of that type. If CONSOLE is 'window-system, return any windows on any
2821 window-system consoles. If CONSOLE is nil or omitted, return windows only
2822 on FRAME'S console, or on the selected console if FRAME is not a frame.
2823 Otherwise, all windows are considered.
2825 (buffer, frame, console))
2827 buffer = Fget_buffer (buffer);
2828 if (BUFFERP (buffer))
2829 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2830 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2835 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2836 but there is no sensible way to implement those functions, since
2837 you can't in general derive a window from a buffer. */
2839 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2841 Return the width in pixels of the left outside margin of window WINDOW.
2842 If WINDOW is nil, the selected window is assumed.
2846 return make_int (window_left_margin_width (decode_window (window)));
2849 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2851 Return the width in pixels of the right outside margin of window WINDOW.
2852 If WINDOW is nil, the selected window is assumed.
2856 return make_int (window_right_margin_width (decode_window (window)));
2859 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2860 Make WINDOW (or the selected window) fill its frame.
2861 Only the frame WINDOW is on is affected.
2862 This function tries to reduce display jumps
2863 by keeping the text previously visible in WINDOW
2864 in the same place on the frame. Doing this depends on
2865 the value of (window-start WINDOW), so if calling this function
2866 in a program gives strange scrolling, make sure the window-start
2867 value is reasonable when this function is called.
2871 struct window *w = decode_window (window);
2872 struct buffer *b = XBUFFER (w->buffer);
2874 int old_top = WINDOW_TOP (w);
2876 XSETWINDOW (window, w);
2878 if (MINI_WINDOW_P (w) && old_top > 0)
2879 error ("Can't expand minibuffer to full frame");
2881 /* Ignore dedicated windows. */
2882 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2884 start_pos = marker_position (w->start[CURRENT_DISP]);
2886 /* Try to minimize scrolling, by setting the window start to the
2887 point which will cause the text at the old window start to be at
2888 the same place on the frame. But don't try to do this if the
2889 window start is outside the visible portion (as might happen when
2890 the display is not current, due to typeahead). */
2891 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2892 && !MINI_WINDOW_P (w))
2894 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2896 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2898 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2900 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2902 /* We need to do this, so that the window-scroll-functions
2910 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2911 "bDelete windows on (buffer): ", /*
2912 Delete all windows showing BUFFER.
2913 Optional second argument FRAME controls which frames are affected.
2914 If nil or omitted, delete all windows showing BUFFER in any frame.
2915 If t, delete only windows showing BUFFER in the selected frame.
2916 If `visible', delete all windows showing BUFFER in any visible frame.
2917 If a frame, delete only windows showing BUFFER in that frame.
2919 Optional third argument CONSOLE controls which consoles or devices the
2920 returned window may be on. If CONSOLE is a console, return windows only
2921 on that console. If CONSOLE is a device, return windows only on that
2922 device. If CONSOLE is a console type, return windows only on consoles
2923 of that type. If CONSOLE is 'window-system, return any windows on any
2924 window-system consoles. If CONSOLE is nil or omitted, return windows only
2925 on FRAME'S console, or on the selected console if FRAME is not a frame.
2926 Otherwise, all windows are considered.
2928 (buffer, frame, console))
2930 /* This function can GC */
2931 /* FRAME uses t and nil to mean the opposite of what window_loop
2933 if (!FRAMEP (frame))
2934 frame = NILP (frame) ? Qt : Qnil;
2938 buffer = Fget_buffer (buffer);
2939 CHECK_BUFFER (buffer);
2940 /* Ignore dedicated windows. */
2941 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2946 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2947 "bReplace buffer in windows: ", /*
2948 Replace BUFFER with some other buffer in all windows showing it.
2952 /* This function can GC */
2955 buffer = Fget_buffer (buffer);
2956 CHECK_BUFFER (buffer);
2957 /* Ignore dedicated windows. */
2958 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2963 /* The smallest acceptable dimensions for a window. Anything smaller
2964 might crash Emacs. */
2965 #define MIN_SAFE_WINDOW_WIDTH (2)
2966 #define MIN_SAFE_WINDOW_HEIGHT (2)
2968 /* Make sure that window_min_height and window_min_width are
2969 not too small; if they are, set them to safe minima. */
2972 check_min_window_sizes (void)
2974 /* Smaller values might permit a crash. */
2975 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2976 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2977 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2978 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2981 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2982 minimum allowable size. */
2984 check_frame_size (struct frame *frame, int *rows, int *cols)
2986 /* For height, we have to see whether the frame has a minibuffer, and
2987 whether it wants a modeline. */
2989 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2990 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2991 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2993 if (*rows < min_height)
2995 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2996 *cols = MIN_SAFE_WINDOW_WIDTH;
2999 /* Normally the window is deleted if it gets too small.
3000 nodelete nonzero means do not do this.
3001 (The caller should check later and do so if appropriate) */
3003 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3006 struct window *w = XWINDOW (window);
3007 struct frame *f = XFRAME (w->frame);
3009 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3010 Lisp_Object child, minor_kid, major_kid;
3013 int defheight, defwidth;
3015 /* #### This is very likely incorrect and instead the char_to_pixel_
3016 functions should be called. */
3017 default_face_height_and_width (window, &defheight, &defwidth);
3018 line_size = (set_height ? defheight : defwidth);
3020 check_min_window_sizes ();
3022 minsize = (set_height ? window_min_height : window_min_width);
3023 minsize *= line_size;
3026 && !TOP_LEVEL_WINDOW_P (w)
3027 && new_pixsize < minsize)
3029 Fdelete_window (window, Qnil);
3033 SET_LAST_MODIFIED (w, 0);
3034 SET_LAST_FACECHANGE (w);
3035 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3038 WINDOW_HEIGHT (w) = new_pixsize;
3039 major_kid = w->vchild;
3040 minor_kid = w->hchild;
3044 WINDOW_WIDTH (w) = new_pixsize;
3045 major_kid = w->hchild;
3046 minor_kid = w->vchild;
3049 if (!NILP (minor_kid))
3051 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3054 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3056 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3058 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3061 else if (!NILP (major_kid))
3063 int last_pos, last_old_pos, pos, old_pos, first;
3064 int pixel_adj_left = new_pixsize - old_pixsize;
3065 int div_val = old_pixsize << 1;
3068 * Previously we bailed out here if there was no size change.
3069 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3070 * toolbar appears or disappears, windows may not change size,
3071 * but their top and left coordinates need to be updated.
3073 * So we don't bail until after the loop below.
3076 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3079 for (child = major_kid; !NILP (child); child = c->next)
3081 c = XWINDOW (child);
3085 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3086 WINDOW_TOP (c) = last_pos;
3090 old_pos = last_old_pos + WINDOW_WIDTH (c);
3091 WINDOW_LEFT (c) = last_pos;
3094 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3095 /* All but the last window should have a height which is
3096 a multiple of the default line height. */
3097 if (!NILP (c->next))
3098 pos = (pos / line_size) * line_size;
3100 /* Avoid confusion: don't delete child if it becomes too small */
3101 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3103 last_pos = pos + first;
3104 last_old_pos = old_pos;
3107 /* Sometimes we may get called with our old size. In that case
3108 we don't need to do anything else. */
3109 if (!pixel_adj_left)
3112 /* Now delete any children that became too small. */
3114 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3117 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3119 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3124 /* Set the height of WINDOW and all its inferiors. */
3126 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3128 set_window_pixsize (window, new_pixheight, nodelete, 1);
3131 /* Recursively set width of WINDOW and its inferiors. */
3133 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3135 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3139 static int window_select_count;
3141 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3142 Make WINDOW display BUFFER as its contents.
3143 BUFFER can be a buffer or buffer name.
3148 struct window *w = decode_window (window);
3150 buffer = Fget_buffer (buffer);
3151 CHECK_BUFFER (buffer);
3153 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3154 error ("Attempt to display deleted buffer");
3158 error ("Window is deleted");
3160 /* While this seems like a logical thing to do, it causes problems
3161 because of saved window configurations. It is possible for a
3162 buffer to get restored into a window in which it is already being
3163 displayed, but start and point are actually at completely
3164 different locations. So we let this function complete fully and
3165 it will then make sure redisplay correctly updates things.
3167 #### This is a kludge. The correct approach is not to do this
3168 but to fix set-window-configuration. */
3170 else if (EQ (tem, buffer))
3173 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3174 is first being set up. */
3176 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3177 error ("Window is dedicated to buffer %s",
3178 XSTRING_DATA (XBUFFER (tem)->name));
3184 w->window_end_pos[CURRENT_DISP] = 0;
3186 w->modeline_hscroll = 0;
3187 Fset_marker (w->pointm[CURRENT_DISP],
3188 make_int (BUF_PT (XBUFFER (buffer))),
3190 set_marker_restricted (w->start[CURRENT_DISP],
3191 make_int (XBUFFER (buffer)->last_window_start),
3193 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3194 /* set start_at_line_beg correctly. GE */
3195 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3196 marker_position (w->start[CURRENT_DISP]));
3197 w->force_start = 0; /* Lucid fix */
3198 SET_LAST_MODIFIED (w, 1);
3199 SET_LAST_FACECHANGE (w);
3200 MARK_WINDOWS_CHANGED (w);
3201 recompute_all_cached_specifiers_in_window (w);
3202 if (EQ (window, Fselected_window (Qnil)))
3204 Fset_buffer (buffer);
3209 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3210 Select WINDOW. Most editing will apply to WINDOW's buffer.
3211 The main editor command loop selects the buffer of the selected window
3212 before each command.
3214 With non-nil optional argument `norecord', do not modify the
3215 global or per-frame buffer ordering.
3220 Lisp_Object old_selected_window = Fselected_window (Qnil);
3222 CHECK_LIVE_WINDOW (window);
3223 w = XWINDOW (window);
3225 /* we have already caught dead-window errors */
3226 if (!NILP (w->hchild) || !NILP (w->vchild))
3227 error ("Trying to select non-leaf window");
3229 w->use_time = make_int (++window_select_count);
3230 if (EQ (window, old_selected_window))
3233 /* deselect the old window, if it exists (it might not exist if
3234 the selected device has no frames, which occurs at startup) */
3235 if (!NILP (old_selected_window))
3237 struct window *ow = XWINDOW (old_selected_window);
3239 Fset_marker (ow->pointm[CURRENT_DISP],
3240 make_int (BUF_PT (XBUFFER (ow->buffer))),
3243 MARK_WINDOWS_CHANGED (ow);
3246 /* now select the window's frame */
3247 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3249 select_frame_1 (WINDOW_FRAME (w));
3251 /* also select the window's buffer */
3252 if (NILP (norecord))
3253 Frecord_buffer (w->buffer);
3254 Fset_buffer (w->buffer);
3256 /* Go to the point recorded in the window.
3257 This is important when the buffer is in more
3258 than one window. It also matters when
3259 redisplay_window has altered point after scrolling,
3260 because it makes the change only in the window. */
3262 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3263 if (new_point < BUF_BEGV (current_buffer))
3264 new_point = BUF_BEGV (current_buffer);
3265 else if (new_point > BUF_ZV (current_buffer))
3266 new_point = BUF_ZV (current_buffer);
3268 BUF_SET_PT (current_buffer, new_point);
3271 MARK_WINDOWS_CHANGED (w);
3277 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3278 Lisp_Object override_frame)
3280 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3284 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3286 /* This function can GC */
3289 struct buffer *b = XBUFFER (buf);
3291 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3292 widen_buffer (b, 0);
3293 BUF_SET_PT (b, BUF_BEG (b));
3295 if (!NILP (Vtemp_buffer_show_function))
3296 call1 (Vtemp_buffer_show_function, buf);
3299 window = display_buffer (buf, Qnil, same_frame);
3301 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3302 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3304 Vminibuffer_scroll_window = window;
3305 w = XWINDOW (window);
3307 w->modeline_hscroll = 0;
3308 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3309 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3310 set_marker_restricted (w->sb_point, make_int (1), buf);
3312 /* Run temp-buffer-show-hook, with the chosen window selected. */
3313 if (!preparing_for_armageddon)
3316 tem = Fboundp (Qtemp_buffer_show_hook);
3319 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3322 int count = specpdl_depth ();
3324 /* Select the window that was chosen, for running
3326 record_unwind_protect (save_window_excursion_unwind,
3327 Fcurrent_window_configuration (Qnil));
3329 Fselect_window (window, Qnil);
3330 run_hook (Qtemp_buffer_show_hook);
3331 unbind_to (count, Qnil);
3339 make_dummy_parent (Lisp_Object window)
3342 struct window *o = XWINDOW (window);
3343 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3345 XSETWINDOW (new, p);
3346 copy_lcrecord (p, o);
3348 /* Don't copy the pointers to the line start cache or the face
3350 p->line_start_cache = Dynarr_new (line_start_cache);
3351 p->face_cachels = Dynarr_new (face_cachel);
3352 p->glyph_cachels = Dynarr_new (glyph_cachel);
3354 /* Put new into window structure in place of window */
3355 replace_window (window, new);
3363 p->start[CURRENT_DISP] = Qnil;
3364 p->start[DESIRED_DISP] = Qnil;
3365 p->start[CMOTION_DISP] = Qnil;
3366 p->pointm[CURRENT_DISP] = Qnil;
3367 p->pointm[DESIRED_DISP] = Qnil;
3368 p->pointm[CMOTION_DISP] = Qnil;
3373 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3374 Split WINDOW, putting SIZE lines in the first of the pair.
3375 WINDOW defaults to selected one and SIZE to half its size.
3376 If optional third arg HOR-FLAG is non-nil, split side by side
3377 and put SIZE columns in the first of the pair.
3379 (window, chsize, horflag))
3382 struct window *o, *p;
3388 window = Fselected_window (Qnil);
3390 CHECK_LIVE_WINDOW (window);
3392 o = XWINDOW (window);
3393 f = XFRAME (WINDOW_FRAME (o));
3397 if (!NILP (horflag))
3398 /* In the new scheme, we are symmetric with respect to separators
3399 so there is no need to do weird things here. */
3401 psize = WINDOW_WIDTH (o) >> 1;
3402 size = window_pixel_width_to_char_width (o, psize, 0);
3406 psize = WINDOW_HEIGHT (o) >> 1;
3407 size = window_pixel_height_to_char_height (o, psize, 1);
3413 size = XINT (chsize);
3414 if (!NILP (horflag))
3415 psize = window_char_width_to_pixel_width (o, size, 0);
3417 psize = window_char_height_to_pixel_height (o, size, 1);
3420 if (MINI_WINDOW_P (o))
3421 error ("Attempt to split minibuffer window");
3422 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3423 error ("Attempt to split unsplittable frame");
3425 check_min_window_sizes ();
3429 if (size < window_min_height)
3430 error ("Window height %d too small (after splitting)", size);
3431 if (size + window_min_height > window_char_height (o, 1))
3432 error ("Window height %d too small (after splitting)",
3433 window_char_height (o, 1) - size);
3434 if (NILP (o->parent)
3435 || NILP (XWINDOW (o->parent)->vchild))
3437 make_dummy_parent (window);
3438 reset_face_cachels (XWINDOW (window));
3440 XWINDOW (new)->vchild = window;
3441 XFRAME (o->frame)->mirror_dirty = 1;
3446 if (size < window_min_width)
3447 error ("Window width %d too small (after splitting)", size);
3448 if (size + window_min_width > window_char_width (o, 0))
3449 error ("Window width %d too small (after splitting)",
3450 window_char_width (o, 0) - size);
3451 if (NILP (o->parent)
3452 || NILP (XWINDOW (o->parent)->hchild))
3454 make_dummy_parent (window);
3455 reset_face_cachels (XWINDOW (window));
3457 XWINDOW (new)->hchild = window;
3458 XFRAME (o->frame)->mirror_dirty = 1;
3462 /* Now we know that window's parent is a vertical combination
3463 if we are dividing vertically, or a horizontal combination
3464 if we are making side-by-side windows */
3466 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3467 new = allocate_window ();
3470 p->frame = o->frame;
3472 if (!NILP (p->next))
3473 XWINDOW (p->next)->prev = new;
3476 p->parent = o->parent;
3479 reset_face_cachels (p);
3480 reset_glyph_cachels (p);
3483 /* Apportion the available frame space among the two new windows */
3485 if (!NILP (horflag))
3487 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3488 WINDOW_TOP (p) = WINDOW_TOP (o);
3489 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3490 WINDOW_WIDTH (o) = psize;
3491 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3495 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3496 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3497 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3498 WINDOW_HEIGHT (o) = psize;
3499 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3502 XFRAME (p->frame)->mirror_dirty = 1;
3503 /* do this last (after the window is completely initialized and
3504 the mirror-dirty flag is set) so that specifier recomputation
3505 caused as a result of this will work properly and not abort. */
3506 Fset_window_buffer (new, o->buffer);
3511 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3512 Make the selected window N lines bigger.
3513 From program, optional second arg SIDE non-nil means grow sideways N columns,
3514 and optional third arg WINDOW specifies the window to change instead of the
3519 struct window *w = decode_window (window);
3521 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3525 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3526 Make the selected window N pixels bigger.
3527 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3528 and optional third arg WINDOW specifies the window to change instead of the
3533 struct window *w = decode_window (window);
3535 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3539 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3540 Make the selected window N lines smaller.
3541 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3542 and optional third arg WINDOW specifies the window to change instead of the
3548 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3553 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3554 Make the selected window N pixels smaller.
3555 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3556 and optional third arg WINDOW specifies the window to change instead of the
3562 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3568 window_pixel_height (Lisp_Object window)
3570 return WINDOW_HEIGHT (XWINDOW (window));
3574 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3575 int include_gutters_p)
3578 int defheight, defwidth;
3582 XSETWINDOW (window, w);
3584 avail_height = (pixel_height -
3585 (include_gutters_p ? 0 :
3586 window_top_gutter_height (w) +
3587 window_bottom_gutter_height (w)));
3589 default_face_height_and_width (window, &defheight, &defwidth);
3591 char_height = avail_height / defheight;
3593 /* It's the calling function's responsibility to check these values
3594 and make sure they're not out of range.
3596 #### We need to go through the calling functions and actually
3598 return max (0, char_height);
3602 window_char_height_to_pixel_height (struct window *w, int char_height,
3603 int include_gutters_p)
3606 int defheight, defwidth;
3611 XSETWINDOW (window, w);
3613 default_face_height_and_width (window, &defheight, &defwidth);
3615 avail_height = char_height * defheight;
3616 pixel_height = (avail_height +
3617 (include_gutters_p ? 0 :
3618 window_top_gutter_height (w) +
3619 window_bottom_gutter_height (w)));
3621 /* It's the calling function's responsibility to check these values
3622 and make sure they're not out of range.
3624 #### We need to go through the calling functions and actually
3626 return max (0, pixel_height);
3629 /* Return number of default lines of text can fit in the window W.
3630 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3631 horizontal scrollbar) in the space that is used for the calculation.
3634 window_char_height (struct window *w, int include_gutters_p)
3636 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3641 * Return number of lines currently displayed in window w. If
3642 * end-of-buffer is displayed then the area below end-of-buffer is assume
3643 * to be blank lines of default height.
3644 * Does not include the modeline.
3647 window_displayed_height (struct window *w)
3649 struct buffer *b = XBUFFER (w->buffer);
3650 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3652 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3654 : w->window_end_pos[CURRENT_DISP]);
3656 if (!Dynarr_length (dla))
3657 return window_char_height (w, 0);
3659 num_lines = Dynarr_length (dla);
3661 /* #### Document and assert somewhere that w->window_end_pos == -1
3662 indicates that end-of-buffer is being displayed. */
3665 struct display_line *dl = Dynarr_atp (dla, 0);
3666 int ypos1 = dl->ypos + dl->descent;
3667 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3669 int defheight, defwidth;
3671 XSETWINDOW (window, w);
3677 if (Dynarr_length (dla) == 1)
3678 ypos1 = WINDOW_TEXT_TOP (w);
3681 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3682 /* If this line is clipped then we know that there is no
3683 blank room between eob and the modeline. If we are
3684 scrolling on clipped lines just know off the clipped
3686 if (scroll_on_clipped_lines && dl->clip)
3687 return num_lines - 1;
3688 ypos1 = dl->ypos + dl->descent - dl->clip;
3692 default_face_height_and_width (window, &defheight, &defwidth);
3693 /* #### This probably needs to know about the clipping area once a
3694 final definition is decided on. */
3695 num_lines += ((ypos2 - ypos1) / defheight);
3699 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3702 if (scroll_on_clipped_lines
3703 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3711 window_pixel_width (Lisp_Object window)
3713 return WINDOW_WIDTH (XWINDOW (window));
3717 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3718 int include_margins_p)
3722 int defheight, defwidth;
3725 XSETWINDOW (window, w);
3727 avail_width = (pixel_width -
3728 window_left_gutter_width (w, 0) -
3729 window_right_gutter_width (w, 0) -
3730 (include_margins_p ? 0 : window_left_margin_width (w)) -
3731 (include_margins_p ? 0 : window_right_margin_width (w)));
3733 default_face_height_and_width (window, &defheight, &defwidth);
3735 char_width = (avail_width / defwidth);
3737 /* It's the calling function's responsibility to check these values
3738 and make sure they're not out of range.
3740 #### We need to go through the calling functions and actually
3742 return max (0, char_width);
3746 window_char_width_to_pixel_width (struct window *w, int char_width,
3747 int include_margins_p)
3751 int defheight, defwidth;
3754 XSETWINDOW (window, w);
3756 default_face_height_and_width (window, &defheight, &defwidth);
3758 avail_width = char_width * defwidth;
3759 pixel_width = (avail_width +
3760 window_left_gutter_width (w, 0) +
3761 window_right_gutter_width (w, 0) +
3762 (include_margins_p ? 0 : window_left_margin_width (w)) +
3763 (include_margins_p ? 0 : window_right_margin_width (w)));
3765 /* It's the calling function's responsibility to check these values
3766 and make sure they're not out of range.
3768 #### We need to go through the calling functions and actually
3770 return max (0, pixel_width);
3773 /* This returns the usable space which doesn't include space needed by
3774 scrollbars or divider lines. */
3776 window_char_width (struct window *w, int include_margins_p)
3778 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3782 #define MINSIZE(w) \
3784 ? window_min_width * defwidth \
3785 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3788 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3790 #define CURSIZE(w) \
3791 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3793 #define CURCHARSIZE(w) \
3794 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3796 #define MINCHARSIZE(window) \
3797 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3798 ? 1 : window_min_height)
3800 /* Unlike set_window_pixheight, this function
3801 also changes the heights of the siblings so as to
3802 keep everything consistent. */
3805 change_window_height (struct window *win, int delta, int widthflag,
3813 int (*sizefun) (Lisp_Object) = (widthflag
3814 ? window_pixel_width
3815 : window_pixel_height);
3816 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3817 ? set_window_pixwidth
3818 : set_window_pixheight);
3820 int defheight, defwidth;
3825 check_min_window_sizes ();
3827 XSETWINDOW (window, win);
3828 f = XFRAME (win->frame);
3829 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3830 error ("Won't change only window");
3832 /* #### This is very likely incorrect and instead the char_to_pixel_
3833 functions should be called. */
3834 default_face_height_and_width (window, &defheight, &defwidth);
3838 w = XWINDOW (window);
3843 error ("No other window to side of this one");
3847 ? !NILP (XWINDOW (parent)->hchild)
3848 : !NILP (XWINDOW (parent)->vchild))
3853 sizep = &CURSIZE (w);
3854 dim = CURCHARSIZE (w);
3856 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3857 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3859 if (MINI_WINDOW_P (XWINDOW (window)))
3861 else if (!NILP (parent))
3863 Fdelete_window (window, Qnil);
3869 delta *= (widthflag ? defwidth : defheight);
3874 maxdelta = ((!NILP (parent))
3875 ? (*sizefun) (parent) - *sizep
3876 : ((!NILP (w->next))
3877 ? (*sizefun) (w->next) - MINSIZE (w->next)
3878 : ((!NILP (w->prev))
3879 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3880 /* This is a frame with only one window,
3881 a minibuffer-only or a minibufferless frame. */
3884 if (delta > maxdelta)
3885 /* This case traps trying to make the minibuffer
3886 the full frame, or make the only window aside from the
3887 minibuffer the full frame. */
3894 /* #### Chuck: is this correct? */
3895 if (*sizep + delta < MINSIZE (window))
3897 Fdelete_window (window);
3903 if (!NILP (w->next) &&
3904 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3906 CURBEG (XWINDOW (w->next)) += delta;
3907 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3908 (*setsizefun) (window, *sizep + delta, 0);
3910 else if (!NILP (w->prev) &&
3911 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3913 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3914 CURBEG (w) -= delta;
3915 (*setsizefun) (window, *sizep + delta, 0);
3920 int opht = (*sizefun) (parent);
3922 /* If trying to grow this window to or beyond size of the parent,
3923 make delta1 so big that, on shrinking back down,
3924 all the siblings end up with less than one line and are deleted. */
3925 if (opht <= *sizep + delta)
3926 delta1 = opht * opht * 2;
3927 /* Otherwise, make delta1 just right so that if we add delta1
3928 lines to this window and to the parent, and then shrink
3929 the parent back to its original size, the new proportional
3930 size of this window will increase by delta. */
3932 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3934 /* Add delta1 lines or columns to this window, and to the parent,
3935 keeping things consistent while not affecting siblings. */
3936 CURSIZE (XWINDOW (parent)) = opht + delta1;
3937 (*setsizefun) (window, *sizep + delta1, 0);
3939 /* Squeeze out delta1 lines or columns from our parent,
3940 shrinking this window and siblings proportionately.
3941 This brings parent back to correct size.
3942 Delta1 was calculated so this makes this window the desired size,
3943 taking it all out of the siblings. */
3944 (*setsizefun) (parent, opht, 0);
3947 SET_LAST_MODIFIED (w, 0);
3948 SET_LAST_FACECHANGE (w);
3949 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3950 /* overkill maybe, but better to be correct */
3951 MARK_FRAME_GUTTERS_CHANGED (f);
3961 /* Scroll contents of window WINDOW up N lines. If N < (top line height /
3962 average line height) then we just adjust the top clip. */
3964 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3965 Error_behavior errb)
3967 struct window *w = XWINDOW (window);
3968 struct buffer *b = XBUFFER (w->buffer);
3969 int selected = EQ (window, Fselected_window (Qnil));
3971 Lisp_Object point, tem;
3972 display_line_dynarr *dla;
3973 int fheight, fwidth, modeline = 0;
3974 struct display_line* dl;
3977 point = make_int (BUF_PT (b));
3980 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3982 if (pos < BUF_BEGV (b))
3984 else if (pos > BUF_ZV (b))
3987 point = make_int (pos);
3990 /* Always set force_start so that redisplay_window will run
3991 the window-scroll-functions. */
3994 /* #### When the fuck does this happen? I'm so glad that history has
3995 completely documented the behavior of the scrolling functions under
3996 all circumstances. */
3997 tem = Fpos_visible_in_window_p (point, window);
4000 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4002 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4003 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4004 WINDOW_TEXT_TOP_CLIP (w) = 0;
4005 MARK_WINDOWS_CHANGED (w);
4014 n = Fprefix_numeric_value (n);
4015 value = XINT (n) * direction;
4018 return; /* someone just made a pointless call */
4022 /* If the user didn't specify how far to scroll then we have to figure it
4023 out by ourselves. */
4024 if (NILP (n) || EQ (n, Qminus))
4026 /* Going forwards is easy. If that is what we are doing then just
4027 set value and the section which handles the user specifying a
4028 positive value will work. */
4031 value = window_displayed_height (w) - next_screen_context_lines;
4032 value = (value < 1 ? 1 : value);
4035 /* Going backwards is hard. We can't use the same loop used if the
4036 user specified a negative value because we care about
4037 next_screen_context_lines. In a variable height world you don't
4038 know how many lines above you can actually be displayed and still
4039 have the context lines appear. So we leave value set to 0 and add
4040 a separate section to deal with this. */
4044 if (direction == 1 && !value)
4049 /* Determine parameters to test for partial line scrolling with. */
4050 dla = window_display_lines (w, CURRENT_DISP);
4052 if (INTP (Vwindow_pixel_scroll_increment))
4053 fheight = XINT (Vwindow_pixel_scroll_increment);
4054 else if (!NILP (Vwindow_pixel_scroll_increment));
4055 default_face_height_and_width (window, &fheight, &fwidth);
4057 if (Dynarr_length (dla) >= 1)
4058 modeline = Dynarr_atp (dla, 0)->modeline;
4060 dl = Dynarr_atp (dla, modeline);
4064 /* Go for partial display line scrolling. This just means bumping
4065 the clip by a reasonable amount and redisplaying, everything else
4066 remains unchanged. */
4067 if (!NILP (Vwindow_pixel_scroll_increment)
4069 Dynarr_length (dla) >= (1 + modeline)
4071 (dl->ascent - dl->top_clip) - fheight * value > 0)
4073 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4074 MARK_WINDOWS_CHANGED (w);
4079 Bufpos startp, old_start;
4081 if (WINDOW_TEXT_TOP_CLIP (w))
4083 WINDOW_TEXT_TOP_CLIP (w) = 0;
4084 MARK_WINDOWS_CHANGED (w);
4087 old_start = marker_position (w->start[CURRENT_DISP]);
4088 startp = vmotion (w, old_start, value, &vtarget);
4090 if (vtarget < value &&
4091 (w->window_end_pos[CURRENT_DISP] == -1
4092 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4094 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4099 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4102 w->start_at_line_beg = beginning_of_line_p (b, startp);
4103 MARK_WINDOWS_CHANGED (w);
4105 if (!point_would_be_visible (w, startp, XINT (point)))
4108 BUF_SET_PT (b, startp);
4110 set_marker_restricted (w->pointm[CURRENT_DISP],
4119 /* Go for partial display line scrolling. This just means bumping
4120 the clip by a reasonable amount and redisplaying, everything else
4121 remains unchanged. */
4122 if (!NILP (Vwindow_pixel_scroll_increment)
4124 Dynarr_length (dla) >= (1 + modeline)
4126 (dl->ascent - dl->top_clip) - fheight * value <
4127 (dl->ascent + dl->descent - dl->clip)
4129 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4131 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4132 MARK_WINDOWS_CHANGED (w);
4137 Bufpos startp, old_start;
4139 if (WINDOW_TEXT_TOP_CLIP (w))
4141 WINDOW_TEXT_TOP_CLIP (w) = 0;
4142 MARK_WINDOWS_CHANGED (w);
4145 old_start = marker_position (w->start[CURRENT_DISP]);
4146 startp = vmotion (w, old_start, value, &vtarget);
4149 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4151 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4156 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4159 w->start_at_line_beg = beginning_of_line_p (b, startp);
4160 MARK_WINDOWS_CHANGED (w);
4162 if (!point_would_be_visible (w, startp, XINT (point)))
4166 if (MINI_WINDOW_P (w))
4169 new_point = start_of_last_line (w, startp);
4172 BUF_SET_PT (b, new_point);
4174 set_marker_restricted (w->pointm[CURRENT_DISP],
4175 make_int (new_point),
4181 else /* value == 0 && direction == -1 */
4183 if (WINDOW_TEXT_TOP_CLIP (w))
4185 WINDOW_TEXT_TOP_CLIP (w) = 0;
4186 MARK_WINDOWS_CHANGED (w);
4188 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4190 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4196 int movement = next_screen_context_lines - 1;
4197 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4198 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4200 start_with_point_on_display_line (w, bottom,
4201 -1 - (movement - vtarget));
4203 if (startp >= old_startp)
4204 startp = vmotion (w, old_startp, -1, NULL);
4206 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4209 w->start_at_line_beg = beginning_of_line_p (b, startp);
4210 MARK_WINDOWS_CHANGED (w);
4212 if (!point_would_be_visible (w, startp, XINT (point)))
4214 Bufpos new_point = start_of_last_line (w, startp);
4217 BUF_SET_PT (b, new_point);
4219 set_marker_restricted (w->pointm[CURRENT_DISP],
4220 make_int (new_point),
4227 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4228 Scroll text of current window upward N lines; or near full screen if no arg.
4229 A near full screen is `next-screen-context-lines' less than a full screen.
4230 Negative N means scroll downward.
4231 When calling from a program, supply an integer as argument or nil.
4232 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4233 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4238 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4242 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4243 Scroll text of current window downward N lines; or near full screen if no arg.
4244 A near full screen is `next-screen-context-lines' less than a full screen.
4245 Negative N means scroll upward.
4246 When calling from a program, supply a number as argument or nil.
4247 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4248 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4253 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4257 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4258 Return the other window for "other window scroll" commands.
4259 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4260 specifies the window.
4261 If `other-window-scroll-buffer' is non-nil, a window
4262 showing that buffer is used.
4267 Lisp_Object selected_window = Fselected_window (Qnil);
4269 if (MINI_WINDOW_P (XWINDOW (selected_window))
4270 && !NILP (Vminibuffer_scroll_window))
4271 window = Vminibuffer_scroll_window;
4272 /* If buffer is specified, scroll that buffer. */
4273 else if (!NILP (Vother_window_scroll_buffer))
4275 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4277 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4281 /* Nothing specified; look for a neighboring window on the same
4283 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4285 if (EQ (window, selected_window))
4286 /* That didn't get us anywhere; look for a window on another
4289 window = Fnext_window (window, Qnil, Qt, Qnil);
4290 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4291 && ! EQ (window, selected_window));
4294 CHECK_LIVE_WINDOW (window);
4296 if (EQ (window, selected_window))
4297 error ("There is no other window");
4302 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4303 Scroll next window upward N lines; or near full frame if no arg.
4304 The next window is the one below the current one; or the one at the top
4305 if the current one is at the bottom. Negative N means scroll downward.
4306 When calling from a program, supply a number as argument or nil.
4308 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4309 specifies the window to scroll.
4310 If `other-window-scroll-buffer' is non-nil, scroll the window
4311 showing that buffer, popping the buffer up if necessary.
4315 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4319 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4320 Scroll selected window display N columns left.
4321 Default for N is window width minus 2.
4325 Lisp_Object window = Fselected_window (Qnil);
4326 struct window *w = XWINDOW (window);
4327 int count = (NILP (n) ?
4328 window_char_width (w, 0) - 2 :
4329 XINT (Fprefix_numeric_value (n)));
4331 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4334 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4335 Scroll selected window display N columns right.
4336 Default for N is window width minus 2.
4340 Lisp_Object window = Fselected_window (Qnil);
4341 struct window *w = XWINDOW (window);
4342 int count = (NILP (n) ?
4343 window_char_width (w, 0) - 2 :
4344 XINT (Fprefix_numeric_value (n)));
4346 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4349 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4350 Center point in WINDOW. With N, put point on line N.
4351 The desired position of point is always relative to the window.
4352 If WINDOW is nil, the selected window is used.
4356 struct window *w = decode_window (window);
4357 struct buffer *b = XBUFFER (w->buffer);
4358 Bufpos opoint = BUF_PT (b);
4362 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4365 n = Fprefix_numeric_value (n);
4367 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4370 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4372 w->start_at_line_beg = beginning_of_line_p (b, startp);
4374 MARK_WINDOWS_CHANGED (w);
4378 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4379 Position point relative to WINDOW.
4380 With no argument, position text at center of window.
4381 An argument specifies window line; zero means top of window,
4382 negative means relative to bottom of window.
4383 If WINDOW is nil, the selected window is used.
4390 Bufpos start, new_point;
4393 /* Don't use decode_window() because we need the new value of
4396 window = Fselected_window (Qnil);
4398 CHECK_LIVE_WINDOW (window);
4399 w = XWINDOW (window);
4400 b = XBUFFER (w->buffer);
4402 height = window_displayed_height (w);
4403 selected = EQ (window, Fselected_window (w->frame));
4409 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4410 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4412 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4415 BUF_SET_PT (b, new_point);
4417 Fset_window_point (window, make_int (new_point));
4419 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4423 start = marker_position (w->start[CURRENT_DISP]);
4424 if (start < BUF_BEGV (b))
4425 start = BUF_BEGV (b);
4426 else if (start > BUF_ZV (b))
4430 new_point = BUF_PT (b);
4432 new_point = marker_position (w->pointm[CURRENT_DISP]);
4434 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4437 BUF_SET_PT (b, new_point);
4439 Fset_window_point (window, make_int (new_point));
4441 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4444 return make_int (retval);
4448 /* #### Is this going to work right when at eob? */
4449 arg = Fprefix_numeric_value (arg);
4451 XSETINT (arg, XINT (arg) + height);
4454 start = marker_position (w->start[CURRENT_DISP]);
4455 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4458 new_point = BUF_PT (b);
4460 new_point = marker_position (w->pointm[CURRENT_DISP]);
4462 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4465 BUF_SET_PT (b, new_point);
4467 Fset_window_point (window, make_int (new_point));
4469 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4471 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4477 BUF_SET_PT (b, start);
4479 Fset_window_point (window, make_int (start));
4483 return Fvertical_motion (arg, window, Qnil);
4487 new_point = vmotion (XWINDOW (window),
4488 marker_position (w->pointm[CURRENT_DISP]),
4490 Fset_window_point (window, make_int (new_point));
4491 return make_int (vpos);
4497 map_windows_1 (Lisp_Object window,
4498 int (*mapfun) (struct window *w, void *closure),
4501 for (; !NILP (window); window = XWINDOW (window)->next)
4504 struct window *w = XWINDOW (window);
4506 if (!NILP (w->vchild))
4507 retval = map_windows_1 (w->vchild, mapfun, closure);
4508 else if (!NILP (w->hchild))
4509 retval = map_windows_1 (w->hchild, mapfun, closure);
4511 retval = (mapfun) (w, closure);
4520 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4521 invocation of MAPFUN. If any invocation of MAPFUN returns
4522 non-zero, the mapping is halted. Otherwise, map_windows() maps
4523 over all windows in F.
4525 If MAPFUN creates or deletes windows, the behavior is undefined. */
4528 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4532 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4535 Lisp_Object frmcons, devcons, concons;
4537 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4539 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4551 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4554 w->shadow_thickness_changed = 1;
4555 MARK_WINDOWS_CHANGED (w);
4559 vertical_divider_changed_in_window (Lisp_Object specifier,
4563 MARK_WINDOWS_CHANGED (w);
4564 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4567 /* also used in scrollbar.c */
4569 some_window_value_changed (Lisp_Object specifier, struct window *w,
4572 MARK_WINDOWS_CHANGED (w);
4575 #ifdef MEMORY_USAGE_STATS
4581 #ifdef HAVE_SCROLLBARS
4585 int other_redisplay;
4590 compute_window_mirror_usage (struct window_mirror *mir,
4591 struct window_stats *stats,
4592 struct overhead_stats *ovstats)
4596 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4598 #ifdef HAVE_SCROLLBARS
4600 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4603 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4606 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4609 #endif /* HAVE_SCROLLBARS */
4610 stats->other_redisplay +=
4611 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4612 stats->other_redisplay +=
4613 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4617 compute_window_usage (struct window *w, struct window_stats *stats,
4618 struct overhead_stats *ovstats)
4621 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4622 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4623 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4624 stats->line_start +=
4625 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4626 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4629 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4630 Return stats about the memory usage of window WINDOW.
4631 The values returned are in the form of an alist of usage types and byte
4632 counts. The byte counts attempt to encompass all the memory used
4633 by the window (separate from the memory logically associated with a
4634 buffer or frame), including internal structures and any malloc()
4635 overhead associated with them. In practice, the byte counts are
4636 underestimated because certain memory usage is very hard to determine
4637 \(e.g. the amount of memory used inside the Xt library or inside the
4638 X server) and because there is other stuff that might logically
4639 be associated with a window, buffer, or frame (e.g. window configurations,
4640 glyphs) but should not obviously be included in the usage counts.
4642 Multiple slices of the total memory usage may be returned, separated
4643 by a nil. Each slice represents a particular view of the memory, a
4644 particular way of partitioning it into groups. Within a slice, there
4645 is no overlap between the groups of memory, and each slice collectively
4646 represents all the memory concerned.
4650 struct window_stats stats;
4651 struct overhead_stats ovstats;
4652 Lisp_Object val = Qnil;
4654 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4656 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4658 val = acons (Qface_cache, make_int (stats.face), val);
4659 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4660 #ifdef HAVE_SCROLLBARS
4661 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4663 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4664 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4665 val = acons (Qother, make_int (stats.other), val);
4666 val = Fcons (Qnil, val);
4667 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4668 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4669 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4671 return Fnreverse (val);
4674 #endif /* MEMORY_USAGE_STATS */
4677 /************************************************************************/
4678 /* Window configurations */
4679 /************************************************************************/
4681 /* #### This window configuration stuff has had serious bugs lurking in it
4682 for years; it would be a -huge- win if this was reimplemented in lisp.
4685 /* If you add anything to this structure make sure saved_window_equal
4689 Lisp_Object window; /* window */
4690 Lisp_Object buffer; /* buffer */
4691 Lisp_Object start; /* copied marker */
4692 Lisp_Object pointm; /* copied marker */
4693 Lisp_Object sb_point; /* copied marker */
4694 Lisp_Object mark; /* copied marker */
4700 Charcount modeline_hscroll;
4701 int parent_index; /* index into saved_windows */
4702 int prev_index; /* index into saved_windows */
4703 char start_at_line_beg; /* boolean */
4705 #define WINDOW_SLOT_DECLARATION
4706 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4707 #include "winslots.h"
4710 /* If you add anything to this structure make sure window_config_equal
4712 struct window_config
4714 struct lcrecord_header header;
4715 /* int frame_width; No longer needed, JV
4716 int frame_height; */
4718 Lisp_Object selected_frame;
4720 Lisp_Object current_window;
4721 Lisp_Object current_buffer;
4722 Lisp_Object minibuffer_scroll_window;
4723 Lisp_Object root_window;
4724 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4725 /* Record the values of window-min-width and window-min-height
4726 so that window sizes remain consistent with them. */
4727 int min_width, min_height;
4728 int saved_windows_count;
4729 /* Zero-sized arrays aren't ANSI C */
4730 struct saved_window saved_windows[1];
4733 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4734 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4735 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4736 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4737 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4740 mark_window_config (Lisp_Object obj)
4742 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4744 mark_object (config->current_window);
4745 mark_object (config->current_buffer);
4746 mark_object (config->minibuffer_scroll_window);
4747 mark_object (config->root_window);
4749 for (i = 0; i < config->saved_windows_count; i++)
4751 struct saved_window *s = SAVED_WINDOW_N (config, i);
4752 mark_object (s->window);
4753 mark_object (s->buffer);
4754 mark_object (s->start);
4755 mark_object (s->pointm);
4756 mark_object (s->sb_point);
4757 mark_object (s->mark);
4759 /* #### This looked like this. I do not see why specifier cached
4760 values should not be marked, as such specifiers as toolbars
4761 might have GC-able instances. Freed configs are not marked,
4762 aren't they? -- kkm */
4763 mark_object (s->dedicated);
4765 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
4766 #include "winslots.h"
4773 sizeof_window_config_for_n_windows (int n)
4775 return (sizeof (struct window_config) +
4776 /* n - 1 because zero-sized arrays aren't ANSI C */
4777 (n - 1) *sizeof (struct saved_window));
4781 sizeof_window_config (CONST void *h)
4783 CONST struct window_config *c = (CONST struct window_config *) h;
4784 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4788 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4790 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4793 error ("printing unreadable object #<window-configuration 0x%x>",
4794 config->header.uid);
4795 write_c_string ("#<window-configuration ", printcharfun);
4796 sprintf (buf, "0x%x>", config->header.uid);
4797 write_c_string (buf, printcharfun);
4800 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4801 window_configuration,
4803 print_window_config,
4804 0, 0, 0, 0, sizeof_window_config,
4805 struct window_config);
4808 /* Returns a boolean indicating whether the two saved windows are
4811 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4813 #define WINDOW_SLOT(slot, compare) \
4814 if (!compare (win1->slot, win2->slot)) \
4816 #include "winslots.h"
4819 EQ (win1->window, win2->window) &&
4820 EQ (win1->buffer, win2->buffer) &&
4821 internal_equal (win1->start, win2->start, 0) &&
4822 internal_equal (win1->pointm, win2->pointm, 0) &&
4823 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4824 internal_equal (win1->mark, win2->mark, 0) &&
4825 win1->pixel_left == win2->pixel_left &&
4826 win1->pixel_top == win2->pixel_top &&
4827 win1->pixel_width == win2->pixel_width &&
4828 win1->pixel_height == win2->pixel_height &&
4829 win1->hscroll == win2->hscroll &&
4830 win1->modeline_hscroll == win2->modeline_hscroll &&
4831 win1->parent_index == win2->parent_index &&
4832 win1->prev_index == win2->prev_index &&
4833 win1->start_at_line_beg == win2->start_at_line_beg;
4836 /* Returns a boolean indicating whether the two given configurations
4839 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4841 struct window_config *fig1, *fig2;
4844 /* First check if they are truly the same. */
4845 if (EQ (conf1, conf2))
4848 fig1 = XWINDOW_CONFIGURATION (conf1);
4849 fig2 = XWINDOW_CONFIGURATION (conf2);
4851 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4852 EQ (fig1->current_window, fig2->current_window) &&
4853 EQ (fig1->current_buffer, fig2->current_buffer) &&
4854 EQ (fig1->root_window, fig2->root_window) &&
4855 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
4857 fig1->frame_width == fig2->frame_width &&
4858 fig1->frame_height == fig2->frame_height)) */
4861 for (i = 0; i < fig1->saved_windows_count; i++)
4863 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4864 SAVED_WINDOW_N (fig2, i)))
4871 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4872 Return t if OBJECT is a window-configuration object.
4876 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4880 mark_windows_in_use_closure (struct window *w, void *closure)
4882 int mark = *(int *)closure;
4883 w->config_mark = mark;
4888 mark_windows_in_use (struct frame *f, int mark)
4890 map_windows (f, mark_windows_in_use_closure, &mark);
4893 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4895 free_window_configuration (Lisp_Object window_config)
4898 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4900 /* Free all the markers. It's not completely necessary that
4901 we do this (window configs sitting in a free list aren't
4902 marked normally so the markers wouldn't be marked anyway)
4903 but it's more efficient. */
4904 for (i = 0; i < config->saved_windows_count; i++)
4906 struct saved_window *p = SAVED_WINDOW_N (config, i);
4908 if (!NILP (p->pointm))
4910 free_marker (XMARKER (p->pointm));
4913 if (!NILP (p->start))
4915 free_marker (XMARKER (p->start));
4918 if (!NILP (p->sb_point))
4920 free_marker (XMARKER (p->sb_point));
4923 if (!NILP (p->mark))
4925 free_marker (XMARKER (p->mark));
4930 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4931 free_managed_lcrecord (Vwindow_configuration_free_list
4932 [config->saved_windows_count - 1],
4938 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4939 Set the configuration of windows and buffers as specified by CONFIGURATION.
4940 CONFIGURATION must be a value previously returned
4941 by `current-window-configuration' (which see).
4946 struct window_config *config;
4947 struct saved_window *p;
4948 Lisp_Object new_current_buffer;
4952 struct gcpro gcpro1;
4953 Lisp_Object old_window_config;
4954 /* int previous_frame_height;
4955 int previous_frame_width;*/
4956 int previous_pixel_top;
4957 int previous_pixel_height;
4958 int previous_pixel_left;
4959 int previous_pixel_width;
4960 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
4961 int real_font_height;
4962 int converted_minibuf_height,target_minibuf_height;
4963 int specpdl_count = specpdl_depth ();
4965 GCPRO1 (configuration);
4967 CHECK_WINDOW_CONFIGURATION (configuration);
4968 config = XWINDOW_CONFIGURATION (configuration);
4970 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4973 /* Do not signal an error here if the frame was deleted. There are
4974 reasonable cases where we could get here with a deleted frame and
4975 just want to do close to nothing instead. */
4977 if (FRAME_LIVE_P (f))
4979 /* restore the frame characteristics */
4981 new_current_buffer = config->current_buffer;
4982 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4983 new_current_buffer = Qnil;
4986 * Assumed precondition: w->config_mark = 0 for all w
4987 * This procedure should ensure this is true by the time it exits
4988 * to ensure the precondition for future calls.
4990 * We use w->config_mark to know whether we're modifying a
4991 * window that is currently visible on the frame (#### we
4992 * should just be able to check whether the window is dead
4993 * or not, but this way is safer?). As we process each
4994 * window, we set its config_mark to 0. At the end, we
4995 * go through all the windows that used to be on the frame,
4996 * set each one's config_mark to 0 (to maintain the
4997 * assumed precondition) and delete each one that's no
5000 * #### Using a window-configuration to keep track of
5001 * the current windows is wasteful. All we need is the
5002 * list of windows, so we could just use a dynarr.
5004 old_window_config = Fcurrent_window_configuration (frame);
5006 /* If the new configuration is already equal to the old, then stop
5007 right here. This saves the work below and it also saves
5008 triggering a full redisplay of this window. This is a huge win
5009 when using the mouse since the mode motion code uses
5010 save-window-excursion extensively but will rarely cause the
5011 configuration to actually change. */
5012 if (window_config_equal (configuration, old_window_config))
5014 free_window_configuration (old_window_config);
5019 /* We can't quit or even check for quit because that may cause
5020 investigation of the frame state, which may crash if the frame is
5021 in an inconsistent state. */
5022 begin_dont_check_for_quit ();
5023 record_unwind_protect (free_window_configuration, old_window_config);
5025 mark_windows_in_use (f, 1);
5028 /* JV: This is bogus,
5029 First of all, the units are inconsistent. The frame sizes are measured
5030 in characters but the window sizes are stored in pixels. So if a
5031 font size change happened between saving and restoring, the
5032 frame "sizes" maybe equal but the windows still should be
5033 resized. This is tickled alot by the new "character size
5034 stays constant" policy in 21.0. It leads to very wierd
5035 glitches (and possibly craches when asserts are tickled).
5037 Just changing the units doens't help because changing the
5038 toolbar configuration can also change the pixel positions.
5039 Luckily there is a much simpler way of doing this, see below.
5041 previous_frame_width = FRAME_WIDTH (f);
5042 previous_frame_height = FRAME_HEIGHT (f);
5043 /* If the frame has been resized since this window configuration was
5044 made, we change the frame to the size specified in the
5045 configuration, restore the configuration, and then resize it
5046 back. We keep track of the prevailing height in these variables. */
5047 if (config->frame_height != FRAME_HEIGHT (f)
5048 || config->frame_width != FRAME_WIDTH (f))
5049 change_frame_size (f, config->frame_height, config->frame_width, 0);
5052 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5053 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5054 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5055 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5057 /* remember some properties of the minibuffer */
5059 default_face_height_and_width (frame, &real_font_height, 0);
5060 assert(real_font_height > 0);
5062 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5064 previous_minibuf_height
5065 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5066 previous_minibuf_top
5067 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5068 previous_minibuf_width
5069 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5073 previous_minibuf_height = 0;
5074 previous_minibuf_top = 0;
5075 previous_minibuf_width = 0;
5077 converted_minibuf_height =
5078 (previous_minibuf_height % real_font_height) == 0 ?
5079 - (previous_minibuf_height / real_font_height ) : /* lines */
5080 previous_minibuf_height; /* pixels */
5082 /* Temporarily avoid any problems with windows that are smaller
5083 than they are supposed to be. */
5084 window_min_height = 1;
5085 window_min_width = 1;
5087 /* OK, now restore all the windows in the window config.
5088 This may involve "undeleting" windows, since the
5089 windows in the window config may be deleted.
5091 for (k = 0; k < config->saved_windows_count; k++)
5093 p = SAVED_WINDOW_N (config, k);
5094 w = XWINDOW (p->window);
5097 /* The window might be dead. In this case, its redisplay
5098 structures were freed, so we need to reallocate them. */
5099 if (!w->face_cachels)
5101 w->face_cachels = Dynarr_new (face_cachel);
5102 reset_face_cachels (w);
5104 if (!w->glyph_cachels)
5105 w->glyph_cachels = Dynarr_new (glyph_cachel);
5106 if (!w->line_start_cache)
5107 w->line_start_cache = Dynarr_new (line_start_cache);
5110 if (p->parent_index >= 0)
5111 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5115 if (p->prev_index >= 0)
5117 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5119 /* This is true for a minibuffer-only frame. */
5120 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5123 XWINDOW (w->prev)->next = p->window;
5128 if (!NILP (w->parent))
5130 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5132 XWINDOW (w->parent)->vchild = p->window;
5133 XWINDOW (w->parent)->hchild = Qnil;
5137 XWINDOW (w->parent)->hchild = p->window;
5138 XWINDOW (w->parent)->vchild = Qnil;
5142 if (!w->config_mark)
5144 /* #### This should be equivalent to the window previously
5145 having been dead. If we're brave, we'll put in an
5146 assertion to this effect. */
5147 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5149 else /* if (!EQ (w->buffer, p->buffer)) */
5151 /* With the new redisplay we let it know that a change has
5152 been made and it will take care of the rest. If we don't
5153 tell it something has possibly changed it could lead to
5154 incorrect display. */
5155 MARK_WINDOWS_CHANGED (w);
5158 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5159 WINDOW_TOP (w) = WINDOW_TOP (p);
5160 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5161 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5162 w->hscroll = p->hscroll;
5163 w->modeline_hscroll = p->modeline_hscroll;
5164 w->line_cache_last_updated = Qzero;
5165 SET_LAST_MODIFIED (w, 1);
5166 SET_LAST_FACECHANGE (w);
5169 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5170 #include "winslots.h"
5172 /* Reinstall the saved buffer and pointers into it. */
5173 if (NILP (p->buffer))
5174 w->buffer = p->buffer;
5177 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5178 /* If saved buffer is alive, install it. */
5180 w->buffer = p->buffer;
5181 w->start_at_line_beg = p->start_at_line_beg;
5182 set_marker_restricted (w->start[CURRENT_DISP],
5183 Fmarker_position (p->start),
5185 set_marker_restricted (w->pointm[CURRENT_DISP],
5186 Fmarker_position (p->pointm),
5188 set_marker_restricted (w->sb_point,
5189 Fmarker_position (p->sb_point),
5191 Fset_marker (XBUFFER (w->buffer)->mark,
5192 Fmarker_position (p->mark), w->buffer);
5194 /* As documented in Fcurrent_window_configuration, don't
5195 save the location of point in the buffer which was current
5196 when the window configuration was recorded. */
5197 if (!EQ (p->buffer, new_current_buffer) &&
5198 XBUFFER (p->buffer) == current_buffer)
5199 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5201 else if (NILP (w->buffer) ||
5202 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5203 /* Else if window's old buffer is dead too, get a live one. */
5205 /* #### The following line makes me nervous... */
5206 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5207 w->buffer = Fget_buffer_create (QSscratch);
5208 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5209 /* This will set the markers to beginning of visible
5211 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5212 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5214 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5215 w->start_at_line_beg = 1;
5218 /* Keeping window's old buffer; make sure the markers
5221 /* Set window markers at start of visible range. */
5222 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5223 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5225 if (XMARKER (w->sb_point)->buffer == 0)
5226 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5227 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5228 set_marker_restricted (w->pointm[CURRENT_DISP],
5230 (BUF_PT (XBUFFER (w->buffer))),
5232 w->start_at_line_beg = 1;
5237 FRAME_ROOT_WINDOW (f) = config->root_window;
5238 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5239 then calls do_switch_frame() below to select the frame that was
5240 recorded in the window config as being selected.
5242 Instead, we don't ever change the selected frame, and either
5243 call Fselect_window() below if the window config's frame is
5244 currently selected, or just set the selected window of the
5245 window config's frame. */
5248 /* Set the frame height to the value it had before this function. */
5249 if (previous_frame_height != FRAME_HEIGHT (f)
5250 || previous_frame_width != FRAME_WIDTH (f))
5251 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5253 /* We just reset the size and position of the minibuffer, to its old
5254 value, which needn't be valid. So we do some magic to see which value
5255 to actually take. Then we set it.
5258 We take the old value if is in the same units but differs from the
5261 #### Now we get more cases correct then ever before, but
5262 are we treating all? For instance what if the frames minibuf window
5263 is no longer the same one?
5265 target_minibuf_height = previous_minibuf_height;
5266 if (converted_minibuf_height &&
5267 (converted_minibuf_height * config->minibuf_height) > 0 &&
5268 (converted_minibuf_height != config->minibuf_height))
5270 target_minibuf_height = config->minibuf_height < 0 ?
5271 - (config->minibuf_height * real_font_height) :
5272 config->minibuf_height;
5273 target_minibuf_height =
5274 max(target_minibuf_height,real_font_height);
5276 if (previous_minibuf_height)
5278 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5279 = previous_minibuf_top -
5280 (target_minibuf_height - previous_minibuf_height);
5281 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5282 target_minibuf_height, 0);
5283 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5284 previous_minibuf_width, 0);
5287 /* This is a better way to deal with frame resizing, etc.
5288 What we _actually_ want is for the old (just restored)
5290 into the place of the new one. So we just do that. Simple! */
5291 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5292 /* Note that this function also updates the subwindow
5294 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5295 previous_pixel_height -
5296 (target_minibuf_height - previous_minibuf_height), 0);
5297 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5298 /* Note that this function also updates the subwindow
5300 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5302 /* If restoring in the current frame make the window current,
5303 otherwise just update the frame selected_window slot to be
5304 the restored current_window. */
5305 if (f == selected_frame ())
5307 /* When using `pop-window-configuration', often the minibuffer
5308 ends up as the selected window even though it's not active ...
5309 I really don't know the cause of this, but it should never
5310 happen. This kludge should fix it.
5312 #### Find out why this is really going wrong. */
5313 if (!minibuf_level &&
5314 MINI_WINDOW_P (XWINDOW (config->current_window)))
5315 Fselect_window (Fnext_window (config->current_window,
5319 Fselect_window (config->current_window, Qnil);
5320 if (!NILP (new_current_buffer))
5321 Fset_buffer (new_current_buffer);
5323 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5326 set_frame_selected_window (f, config->current_window);
5329 old_window_config = Qnil; /* Warning suppression */
5331 /* Restore the minimum heights recorded in the configuration. */
5332 window_min_height = config->min_height;
5333 window_min_width = config->min_width;
5336 /* see above comment */
5337 /* Fselect_window will have made f the selected frame, so we
5338 reselect the proper frame here. Fhandle_switch_frame will change the
5339 selected window too, but that doesn't make the call to
5340 Fselect_window above totally superfluous; it still sets f's
5342 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5343 do_switch_frame (config->selected_frame, Qnil, 0);
5346 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5348 if (FRAME_LIVE_P (f))
5350 /* Do this before calling recompute_all_cached_specifiers_in_window()
5351 so that things like redisplay_redraw_cursor() won't abort due
5352 to no window mirror present. */
5353 f->mirror_dirty = 1;
5355 config = XWINDOW_CONFIGURATION (old_window_config);
5356 for (k = 0; k < config->saved_windows_count; k++)
5358 p = SAVED_WINDOW_N (config, k);
5359 w = XWINDOW (p->window);
5360 /* Remember, we set w->config_mark on all currently visible
5361 windows, and reset it on all newly visible windows.
5362 Any windows still marked need to be deleted. */
5365 mark_window_as_deleted (w);
5370 /* We just potentially changed the window's buffer and
5371 potentially turned a dead window into a live one,
5372 so we need to recompute the cached specifier values. */
5373 recompute_all_cached_specifiers_in_window (w);
5378 /* Now restore things, when everything else if OK. */
5380 unbind_to (specpdl_count, Qnil);
5387 /* Mark all subwindows of a window as deleted. The argument
5388 W is actually the subwindow tree of the window in question. */
5391 delete_all_subwindows (struct window *w)
5393 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5394 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5395 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5397 mark_window_as_deleted (w);
5402 count_windows (struct window *window)
5405 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5406 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5407 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5411 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5414 for (j = 0; j < lim; j++)
5416 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5420 return 0; /* suppress compiler warning */
5424 save_window_save (Lisp_Object window, struct window_config *config, int i)
5428 for (; !NILP (window); window = w->next)
5430 struct saved_window *p = SAVED_WINDOW_N (config, i);
5432 w = XWINDOW (window);
5435 p->buffer = w->buffer;
5436 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5437 WINDOW_TOP (p) = WINDOW_TOP (w);
5438 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5439 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5440 p->hscroll = w->hscroll;
5441 p->modeline_hscroll = w->modeline_hscroll;
5443 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5444 #include "winslots.h"
5446 if (!NILP (w->buffer))
5448 /* Save w's value of point in the window configuration.
5449 If w is the selected window, then get the value of point
5450 from the buffer; pointm is garbage in the selected window. */
5451 if (EQ (window, Fselected_window (Qnil)))
5453 p->pointm = noseeum_make_marker ();
5454 Fset_marker (p->pointm,
5455 make_int (BUF_PT (XBUFFER (w->buffer))),
5459 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5461 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5462 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5463 p->start_at_line_beg = w->start_at_line_beg;
5465 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5473 p->start_at_line_beg = 0;
5476 if (NILP (w->parent))
5477 p->parent_index = -1;
5479 p->parent_index = saved_window_index (w->parent, config, i);
5483 p->prev_index = saved_window_index (w->prev, config, i);
5484 if (!NILP (w->vchild))
5485 i = save_window_save (w->vchild, config, i);
5486 if (!NILP (w->hchild))
5487 i = save_window_save (w->hchild, config, i);
5494 /* Added to doc string:
5496 This also records the currently selected frame, and FRAME's focus
5497 redirection (see `redirect-frame-focus').
5502 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5503 Return an object representing the current window configuration of FRAME.
5504 If FRAME is nil or omitted, use the selected frame.
5505 This describes the number of windows, their sizes and current buffers,
5506 and for each displayed buffer, where display starts, and the positions of
5507 point and mark. An exception is made for point in the current buffer:
5508 its value is -not- saved.
5513 struct frame *f = decode_frame (frame);
5514 struct window_config *config;
5515 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5517 int real_font_height;
5519 if (n_windows <= countof (Vwindow_configuration_free_list))
5520 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5521 (Vwindow_configuration_free_list
5524 /* More than ten windows; just allocate directly */
5525 config = (struct window_config *)
5526 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5527 &lrecord_window_configuration);
5528 XSETWINDOW_CONFIGURATION (result, config);
5530 config->frame_width = FRAME_WIDTH (f);
5531 config->frame_height = FRAME_HEIGHT (f); */
5532 config->current_window = FRAME_SELECTED_WINDOW (f);
5533 XSETBUFFER (config->current_buffer, current_buffer);
5534 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5535 config->root_window = FRAME_ROOT_WINDOW (f);
5536 config->min_height = window_min_height;
5537 config->min_width = window_min_width;
5538 config->saved_windows_count = n_windows;
5539 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5541 /* save the minibuffer height using the heuristics from
5542 change_frame_size_1 */
5544 XSETFRAME (frame, f); /* frame could have been nil ! */
5545 default_face_height_and_width (frame, &real_font_height, 0);
5546 assert(real_font_height > 0);
5548 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5549 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5552 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5553 - (minibuf_height / real_font_height ) : /* lines */
5554 minibuf_height; /* pixels */
5560 save_window_excursion_unwind (Lisp_Object window_config)
5562 Lisp_Object val = Fset_window_configuration (window_config);
5563 free_window_configuration (window_config);
5567 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5568 Execute body, preserving window sizes and contents.
5569 Restores which buffer appears in which window, where display starts,
5570 as well as the current buffer.
5571 Does not restore the value of point in current buffer.
5575 /* This function can GC */
5577 int speccount = specpdl_depth ();
5579 record_unwind_protect (save_window_excursion_unwind,
5580 Fcurrent_window_configuration (Qnil));
5581 val = Fprogn (args);
5582 return unbind_to (speccount, val);
5585 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5586 Return the horizontal pixel position of POS in window.
5587 Beginning of line is column 0. This is calculated using the redisplay
5588 display tables. If WINDOW is nil, the current window is assumed.
5589 If POS is nil, point is assumed. Note that POS must be visible for
5590 a non-nil result to be returned.
5594 struct window* w = decode_window (window);
5595 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5597 struct display_line *dl = 0;
5598 struct display_block *db = 0;
5599 struct rune* rb = 0;
5600 int y = w->last_point_y[CURRENT_DISP];
5601 int x = w->last_point_x[CURRENT_DISP];
5603 if (MINI_WINDOW_P (w))
5606 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5612 pos = Fwindow_point (window);
5617 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5622 for (i = first_line; i < Dynarr_length (dla); i++)
5624 dl = Dynarr_atp (dla, i);
5625 /* find the vertical location first */
5626 if (point >= dl->bufpos && point <= dl->end_bufpos)
5628 db = get_display_block_from_line (dl, TEXT);
5629 for (i = 0; i < Dynarr_length (db->runes); i++)
5631 rb = Dynarr_atp (db->runes, i);
5632 if (point <= rb->bufpos)
5644 /* optimised case */
5645 dl = Dynarr_atp (dla, y);
5646 db = get_display_block_from_line (dl, TEXT);
5648 if (x >= Dynarr_length (db->runes))
5651 rb = Dynarr_atp (db->runes, x);
5654 return make_int (rb->xpos - WINDOW_LEFT (w));
5659 /* This is short and simple in elisp, but... it was written to debug
5660 problems purely on the C side. That is where we need to call it so
5663 debug_print_window (Lisp_Object window, int level)
5666 Lisp_Object child = Fwindow_first_vchild (window);
5669 child = Fwindow_first_hchild (window);
5671 for (i = level; i > 0; i--)
5672 putc ('\t', stderr);
5674 fputs ("#<window", stderr);
5676 Lisp_Object buffer = XWINDOW (window)->buffer;
5677 if (!NILP (buffer) && BUFFERP (buffer))
5678 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5680 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5682 while (!NILP (child))
5684 debug_print_window (child, level + 1);
5685 child = Fwindow_next_child (child);
5689 void debug_print_windows (struct frame *f);
5691 debug_print_windows (struct frame *f)
5693 debug_print_window (f->root_window, 0);
5694 putc ('\n', stderr);
5696 #endif /* DEBUG_XEMACS */
5699 /************************************************************************/
5700 /* initialization */
5701 /************************************************************************/
5704 syms_of_window (void)
5706 defsymbol (&Qwindowp, "windowp");
5707 defsymbol (&Qwindow_live_p, "window-live-p");
5708 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5709 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5710 defsymbol (&Qdisplay_buffer, "display-buffer");
5712 #ifdef MEMORY_USAGE_STATS
5713 defsymbol (&Qface_cache, "face-cache");
5714 defsymbol (&Qglyph_cache, "glyph-cache");
5715 defsymbol (&Qline_start_cache, "line-start-cache");
5716 #ifdef HAVE_SCROLLBARS
5717 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5719 defsymbol (&Qother_redisplay, "other-redisplay");
5720 /* Qother in general.c */
5723 DEFSUBR (Fselected_window);
5724 DEFSUBR (Flast_nonminibuf_window);
5725 DEFSUBR (Fminibuffer_window);
5726 DEFSUBR (Fwindow_minibuffer_p);
5728 DEFSUBR (Fwindow_live_p);
5729 DEFSUBR (Fwindow_first_hchild);
5730 DEFSUBR (Fwindow_first_vchild);
5731 DEFSUBR (Fwindow_next_child);
5732 DEFSUBR (Fwindow_previous_child);
5733 DEFSUBR (Fwindow_parent);
5734 DEFSUBR (Fwindow_lowest_p);
5735 DEFSUBR (Fwindow_truncated_p);
5736 DEFSUBR (Fwindow_highest_p);
5737 DEFSUBR (Fwindow_leftmost_p);
5738 DEFSUBR (Fwindow_rightmost_p);
5739 DEFSUBR (Fpos_visible_in_window_p);
5740 DEFSUBR (Fwindow_buffer);
5741 DEFSUBR (Fwindow_frame);
5742 DEFSUBR (Fwindow_height);
5743 DEFSUBR (Fwindow_displayed_height);
5744 DEFSUBR (Fwindow_width);
5745 DEFSUBR (Fwindow_pixel_height);
5746 DEFSUBR (Fwindow_pixel_width);
5747 DEFSUBR (Fwindow_text_area_pixel_height);
5748 DEFSUBR (Fwindow_displayed_text_pixel_height);
5749 DEFSUBR (Fwindow_text_area_pixel_width);
5750 DEFSUBR (Fwindow_hscroll);
5751 DEFSUBR (Fset_window_hscroll);
5752 DEFSUBR (Fmodeline_hscroll);
5753 DEFSUBR (Fset_modeline_hscroll);
5754 #if 0 /* bogus FSF crock */
5755 DEFSUBR (Fwindow_redisplay_end_trigger);
5756 DEFSUBR (Fset_window_redisplay_end_trigger);
5758 DEFSUBR (Fwindow_pixel_edges);
5759 DEFSUBR (Fwindow_text_area_pixel_edges);
5760 DEFSUBR (Fwindow_point);
5761 DEFSUBR (Fwindow_start);
5762 DEFSUBR (Fwindow_end);
5763 DEFSUBR (Fset_window_point);
5764 DEFSUBR (Fset_window_start);
5765 DEFSUBR (Fwindow_dedicated_p);
5766 DEFSUBR (Fset_window_dedicated_p);
5767 DEFSUBR (Fnext_window);
5768 DEFSUBR (Fprevious_window);
5769 DEFSUBR (Fnext_vertical_window);
5770 DEFSUBR (Fother_window);
5771 DEFSUBR (Fget_lru_window);
5772 DEFSUBR (Fget_largest_window);
5773 DEFSUBR (Fget_buffer_window);
5774 DEFSUBR (Fwindow_left_margin_pixel_width);
5775 DEFSUBR (Fwindow_right_margin_pixel_width);
5776 DEFSUBR (Fdelete_other_windows);
5777 DEFSUBR (Fdelete_windows_on);
5778 DEFSUBR (Freplace_buffer_in_windows);
5779 DEFSUBR (Fdelete_window);
5780 DEFSUBR (Fset_window_buffer);
5781 DEFSUBR (Fselect_window);
5782 DEFSUBR (Fsplit_window);
5783 DEFSUBR (Fenlarge_window);
5784 DEFSUBR (Fenlarge_window_pixels);
5785 DEFSUBR (Fshrink_window);
5786 DEFSUBR (Fshrink_window_pixels);
5787 DEFSUBR (Fscroll_up);
5788 DEFSUBR (Fscroll_down);
5789 DEFSUBR (Fscroll_left);
5790 DEFSUBR (Fscroll_right);
5791 DEFSUBR (Fother_window_for_scrolling);
5792 DEFSUBR (Fscroll_other_window);
5793 DEFSUBR (Fcenter_to_window_line);
5794 DEFSUBR (Fmove_to_window_line);
5795 #ifdef MEMORY_USAGE_STATS
5796 DEFSUBR (Fwindow_memory_usage);
5798 DEFSUBR (Fwindow_configuration_p);
5799 DEFSUBR (Fset_window_configuration);
5800 DEFSUBR (Fcurrent_window_configuration);
5801 DEFSUBR (Fsave_window_excursion);
5802 DEFSUBR (Fcurrent_pixel_column);
5806 reinit_vars_of_window (void)
5809 /* Make sure all windows get marked */
5810 minibuf_window = Qnil;
5811 staticpro_nodump (&minibuf_window);
5813 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5815 Vwindow_configuration_free_list[i] =
5816 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5817 &lrecord_window_configuration);
5818 staticpro_nodump (&Vwindow_configuration_free_list[i]);
5823 vars_of_window (void)
5825 reinit_vars_of_window ();
5827 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5828 *Non-nil means to scroll if point lands on a line which is clipped.
5830 scroll_on_clipped_lines = 1;
5832 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5833 See `temp-buffer-show-function'.
5835 Vtemp_buffer_show_hook = Qnil;
5837 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5838 Non-nil means call as function to display a help buffer.
5839 The function is called with one argument, the buffer to be displayed.
5840 Used by `with-output-to-temp-buffer'.
5841 If this function is used, then it must do the entire job of showing
5842 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5844 Vtemp_buffer_show_function = Qnil;
5846 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5847 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5849 Vminibuffer_scroll_window = Qnil;
5851 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5852 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5854 Vother_window_scroll_buffer = Qnil;
5856 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
5857 *Number of pixels to scroll by per requested line.
5858 If nil then normal line scrolling occurs regardless of line height.
5859 If t then scrolling is done in increments equal to the height of the default face.
5861 Vwindow_pixel_scroll_increment = Qt;
5863 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5864 *Number of lines of continuity when scrolling by screenfuls.
5866 next_screen_context_lines = 2;
5868 DEFVAR_INT ("window-min-height", &window_min_height /*
5869 *Delete any window less than this tall (including its modeline).
5871 window_min_height = 4;
5873 DEFVAR_INT ("window-min-width", &window_min_width /*
5874 *Delete any window less than this wide.
5876 window_min_width = 10;
5880 specifier_vars_of_window (void)
5882 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5883 *How thick to draw 3D shadows around modelines.
5884 If this is set to 0, modelines will be the traditional 2D. Sizes above
5885 10 will be accepted but the maximum thickness that will be drawn is 10.
5886 This is a specifier; use `set-specifier' to change it.
5888 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5889 /* The initial value for modeline-shadow-thickness is 2, but if the
5890 user removes all specifications we provide a fallback value of 0,
5891 which is probably what was expected. */
5892 set_specifier_fallback (Vmodeline_shadow_thickness,
5893 list1 (Fcons (Qnil, Qzero)));
5894 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5896 set_specifier_caching (Vmodeline_shadow_thickness,
5897 offsetof (struct window, modeline_shadow_thickness),
5898 modeline_shadow_thickness_changed,
5901 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5902 *Whether the modeline should be displayed.
5903 This is a specifier; use `set-specifier' to change it.
5905 Vhas_modeline_p = Fmake_specifier (Qboolean);
5906 set_specifier_fallback (Vhas_modeline_p,
5907 list1 (Fcons (Qnil, Qt)));
5908 set_specifier_caching (Vhas_modeline_p,
5909 offsetof (struct window, has_modeline_p),
5910 /* #### It's strange that we need a special
5911 flag to indicate that the shadow-thickness
5912 has changed, but not one to indicate that
5913 the modeline has been turned off or on. */
5914 some_window_value_changed,
5917 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5918 &Vvertical_divider_always_visible_p /*
5919 *Should XEmacs always display vertical dividers between windows.
5921 When this is non-nil, vertical dividers are always shown, and are
5922 draggable. When it is nil, vertical dividers are shown only when
5923 there are no scrollbars in between windows, and are not draggable.
5925 This is a specifier; use `set-specifier' to change it.
5927 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5928 set_specifier_fallback (Vvertical_divider_always_visible_p,
5929 list1 (Fcons (Qnil, Qt)));
5930 set_specifier_caching (Vvertical_divider_always_visible_p,
5931 offsetof (struct window,
5932 vertical_divider_always_visible_p),
5933 vertical_divider_changed_in_window,
5936 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5937 *How thick to draw 3D shadows around vertical dividers.
5938 This is a specifier; use `set-specifier' to change it.
5940 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5941 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5942 list1 (Fcons (Qnil, Qzero)));
5943 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5945 set_specifier_caching (Vvertical_divider_shadow_thickness,
5946 offsetof (struct window,
5947 vertical_divider_shadow_thickness),
5948 vertical_divider_changed_in_window,
5950 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5951 *The width of the vertical dividers, not including shadows.
5953 For TTY windows, divider line is always one character wide. When
5954 instance of this specifier is zero in a TTY window, no divider is
5955 drawn at all between windows. When non-zero, a one character wide
5956 divider is displayed.
5958 This is a specifier; use `set-specifier' to change it.
5961 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5963 Lisp_Object fb = Qnil;
5965 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
5967 #ifdef HAVE_X_WINDOWS
5968 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5970 #ifdef HAVE_MS_WINDOWS
5971 /* #### This should be made magic and made to obey system settings */
5972 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5974 set_specifier_fallback (Vvertical_divider_line_width, fb);
5976 set_specifier_caching (Vvertical_divider_line_width,
5977 offsetof (struct window,
5978 vertical_divider_line_width),
5979 vertical_divider_changed_in_window,
5982 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5983 *How much space to leave around the vertical dividers.
5985 In TTY windows, spacing is always zero, and the value of this
5986 specifier is ignored.
5988 This is a specifier; use `set-specifier' to change it.
5990 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5992 Lisp_Object fb = Qnil;
5994 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5996 #ifdef HAVE_X_WINDOWS
5997 /* #### 3D dividers look great on MS Windows with spacing = 0.
5998 Should not the same value be the fallback under X? - kkm */
5999 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6001 #ifdef HAVE_MS_WINDOWS
6002 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6004 set_specifier_fallback (Vvertical_divider_spacing, fb);
6006 set_specifier_caching (Vvertical_divider_spacing,
6007 offsetof (struct window, vertical_divider_spacing),
6008 vertical_divider_changed_in_window,