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, 1, 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 #ifdef MODELINE_IS_SCROLLABLE
1441 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1442 Return the number of columns by which WINDOW's modeline is scrolled from
1443 left margin. If the window has no modeline, return nil.
1447 struct window *w = decode_window (window);
1449 return (WINDOW_HAS_MODELINE_P (w)) ? make_int (w->modeline_hscroll) : Qnil;
1452 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1453 Set number of columns WINDOW's modeline is scrolled from left margin to NCOL.
1454 NCOL should be zero or positive. If NCOL is negative, it will be forced to 0.
1455 If the window has no modeline, do nothing and return nil.
1459 struct window *w = decode_window (window);
1461 if (WINDOW_HAS_MODELINE_P (w))
1465 ncols = XINT (ncol);
1466 if (ncols < 0) ncols = 0;
1467 if (w->modeline_hscroll != ncols)
1468 MARK_MODELINE_CHANGED;
1469 w->modeline_hscroll = ncols;
1474 #endif /* MODELINE_IS_SCROLLABLE */
1476 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1477 Set number of columns WINDOW is scrolled from left margin to NCOL.
1478 NCOL should be zero or positive.
1486 ncols = XINT (ncol);
1487 if (ncols < 0) ncols = 0;
1488 w = decode_window (window);
1489 if (w->hscroll != ncols)
1490 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1495 #if 0 /* bogus FSF crock */
1497 xxDEFUN ("window-redisplay-end-trigger",
1498 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1499 Return WINDOW's redisplay end trigger value.
1500 See `set-window-redisplay-end-trigger' for more information.
1504 return decode_window (window)->redisplay_end_trigger;
1507 xxDEFUN ("set-window-redisplay-end-trigger",
1508 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1509 Set WINDOW's redisplay end trigger value to VALUE.
1510 VALUE should be a buffer position (typically a marker) or nil.
1511 If it is a buffer position, then if redisplay in WINDOW reaches a position
1512 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1513 with two arguments: WINDOW, and the end trigger value.
1514 Afterwards the end-trigger value is reset to nil.
1518 return (decode_window (window)->redisplay_end_trigger = value);
1523 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1524 Return a list of the pixel edge coordinates of WINDOW.
1525 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1526 The frame toolbars and menubars are considered to be outside of this area.
1530 struct window *w = decode_window (window);
1531 struct frame *f = XFRAME (w->frame);
1533 int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
1534 int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
1536 return list4 (make_int (left),
1538 make_int (left + w->pixel_width),
1539 make_int (top + w->pixel_height));
1542 DEFUN ("window-text-area-pixel-edges",
1543 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1544 Return a list of the pixel edge coordinates of the text area of WINDOW.
1545 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1546 top left corner of the window.
1550 struct window *w = decode_window (window);
1552 int left = window_left_gutter_width (w, /* modeline = */ 0);
1553 int top = window_top_gutter_height (w);
1554 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1555 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1557 return list4 (make_int (left),
1563 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1564 Return current value of point in WINDOW.
1565 For a nonselected window, this is the value point would have
1566 if that window were selected.
1568 Note that, when WINDOW is the selected window and its buffer
1569 is also currently selected, the value returned is the same as (point).
1570 It would be more strictly correct to return the `top-level' value
1571 of point, outside of any save-excursion forms.
1572 But that is hard to define.
1576 struct window *w = decode_window (window);
1578 /* The special check for current buffer is necessary for this
1579 function to work as defined when called within an excursion. */
1580 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1581 && current_buffer == XBUFFER (w->buffer))
1582 return Fpoint (Qnil);
1583 return Fmarker_position (w->pointm[CURRENT_DISP]);
1586 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1587 Return position at which display currently starts in WINDOW.
1588 This is updated by redisplay or by calling `set-window-start'.
1592 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1595 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1596 Return position at which display currently ends in WINDOW.
1597 This is updated by redisplay, when it runs to completion.
1598 Simply changing the buffer text or setting `window-start'
1599 does not update this value.
1600 If GUARANTEE is non-nil, then the return value is guaranteed to be
1601 the value of window-end at the end of the next full redisplay assuming
1602 nothing else changes in the meantime. This function is potentially much
1603 slower with this flag set.
1605 (window, guarantee))
1607 struct window *w = decode_window (window);
1609 if (NILP (guarantee))
1614 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1618 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1619 return make_int (end_of_last_line (w, startp));
1623 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1624 Make point value in WINDOW be at position POS in WINDOW's buffer.
1628 struct window *w = decode_window (window);
1630 CHECK_INT_COERCE_MARKER (pos);
1631 if (w == XWINDOW (Fselected_window (Qnil)))
1632 Fgoto_char (pos, Qnil);
1634 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1640 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1641 Make display in WINDOW start at position POS in WINDOW's buffer.
1642 Optional third arg NOFORCE non-nil inhibits next redisplay
1643 from overriding motion of point in order to display at this exact start.
1645 (window, pos, noforce))
1647 struct window *w = decode_window (window);
1649 CHECK_INT_COERCE_MARKER (pos);
1650 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1651 /* this is not right, but much easier than doing what is right. */
1652 /* w->start_at_line_beg = 0; */
1653 /* WTF is the above supposed to mean? GE */
1654 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1655 marker_position (w->start[CURRENT_DISP]));
1658 w->redo_modeline = 1;
1659 SET_LAST_MODIFIED (w, 0);
1660 SET_LAST_FACECHANGE (w);
1662 MARK_WINDOWS_CHANGED (w);
1667 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1668 Return WINDOW's dedicated object, usually t or nil.
1669 See also `set-window-dedicated-p'.
1673 return decode_window (window)->dedicated;
1676 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1677 Control whether WINDOW is dedicated to the buffer it displays.
1678 If it is dedicated, Emacs will not automatically change
1679 which buffer appears in it.
1680 The second argument is the new value for the dedication flag;
1685 struct window *w = decode_window (window);
1687 w->dedicated = NILP (arg) ? Qnil : Qt;
1689 return w->dedicated;
1692 /* FSFmacs has window-display-table here. We have display table as a
1696 /* Record info on buffer window w is displaying
1697 when it is about to cease to display that buffer. */
1699 unshow_buffer (struct window *w)
1701 Lisp_Object buf = w->buffer;
1703 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1706 /* FSF disables this check, so I'll do it too. I hope it won't
1707 break things. --ben */
1709 if (w == XWINDOW (Fselected_window (Qnil))
1710 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1711 /* Do this except when the selected window's buffer
1712 is being removed from some other window. */
1714 /* last_window_start records the start position that this buffer
1715 had in the last window to be disconnected from it.
1716 Now that this statement is unconditional,
1717 it is possible for the buffer to be displayed in the
1718 selected window, while last_window_start reflects another
1719 window which was recently showing the same buffer.
1720 Some people might say that might be a good thing. Let's see. */
1721 XBUFFER (buf)->last_window_start =
1722 marker_position (w->start[CURRENT_DISP]);
1724 /* Point in the selected window's buffer
1725 is actually stored in that buffer, and the window's pointm isn't used.
1726 So don't clobber point in that buffer. */
1727 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1729 struct buffer *b= XBUFFER (buf);
1730 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1731 marker_position (w->pointm[CURRENT_DISP]),
1736 /* Put REPLACEMENT into the window structure in place of OLD. */
1738 replace_window (Lisp_Object old, Lisp_Object replacement)
1741 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1743 /* If OLD is its frame's root_window, then replacement is the new
1744 root_window for that frame. */
1746 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1747 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1749 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1750 WINDOW_TOP (p) = WINDOW_TOP (o);
1751 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1752 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1754 p->next = tem = o->next;
1756 XWINDOW (tem)->prev = replacement;
1758 p->prev = tem = o->prev;
1760 XWINDOW (tem)->next = replacement;
1762 p->parent = tem = o->parent;
1765 if (EQ (XWINDOW (tem)->vchild, old))
1766 XWINDOW (tem)->vchild = replacement;
1767 if (EQ (XWINDOW (tem)->hchild, old))
1768 XWINDOW (tem)->hchild = replacement;
1771 /* #### Here, if replacement is a vertical combination
1772 and so is its new parent, we should make replacement's
1773 children be children of that parent instead. */
1776 /* we're deleting W; set the structure of W to indicate this. */
1779 mark_window_as_deleted (struct window *w)
1782 (while t (split-window) (delete-window))
1783 we end up with a tree of deleted windows which are all connected
1784 through the `next' slot. This might not seem so bad, as they're
1785 deleted, and will presumably be GCed - but if even *one* of those
1786 windows is still being pointed to, by the user, or by a window
1787 configuration, then *all* of those windows stick around.
1789 Since the window-configuration code doesn't need any of the
1790 pointers to other windows (they are all recreated from the
1791 window-config data), we set them all to nil so that we
1792 are able to collect more actual garbage.
1802 /* Free the extra data structures attached to windows immediately so
1803 they don't sit around consuming excess space. They will be
1804 reinitialized by the window-configuration code as necessary. */
1805 finalize_window ((void *) w, 0);
1808 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1809 Remove WINDOW from the display. Default is selected window.
1810 If window is the only one on the frame, the frame is destroyed.
1811 Normally, you cannot delete the last non-minibuffer-only frame (you must
1812 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1813 second argument FORCE is non-nil, you can delete the last frame. (This
1814 will automatically call `save-buffers-kill-emacs'.)
1818 /* This function can GC if this is the only window in the frame */
1826 /* Note: this function is called by other C code on non-leaf
1829 /* Do the equivalent of decode_window() but don't error out on
1830 deleted window; it's OK to delete an already-deleted window. */
1832 window = Fselected_window (Qnil);
1834 CHECK_WINDOW (window);
1835 w = XWINDOW (window);
1837 /* It's okay to delete an already-deleted window. */
1838 if (! WINDOW_LIVE_P (w))
1841 frame = WINDOW_FRAME (w);
1843 d = XDEVICE (FRAME_DEVICE (f));
1845 if (TOP_LEVEL_WINDOW_P (w))
1847 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1848 /* this frame isn't fully initialized yet; don't blow up. */
1851 if (MINI_WINDOW_P (XWINDOW (window)))
1852 error ("Attempt to delete the minibuffer window");
1854 /* It has been suggested that it's a good thing for C-x 0 to have this
1855 behavior, but not such a good idea for #'delete-window to have it.
1856 Maybe C-x 0 should be bound to something else, or maybe frame
1857 deletion should only happen when this is called interactively.
1859 delete_frame_internal (f, !NILP (force), 0, 0);
1863 /* At this point, we know the window has a parent. */
1865 par = XWINDOW (parent);
1867 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1868 /* It's quite likely that deleting a window will result in
1869 subwindows needing to be deleted also (since they are cached
1870 per-window). So we mark them as changed, so that the cachels will
1871 get reset by redisplay and thus deleted subwindows can get
1873 MARK_FRAME_SUBWINDOWS_CHANGED (f);
1875 /* Are we trying to delete any frame's selected window?
1876 Note that we could be dealing with a non-leaf window
1877 where the selected window is one of our children.
1878 So, we check by scanning all the ancestors of the
1879 frame's selected window and comparing each one with
1882 Lisp_Object pwindow;
1884 pwindow = FRAME_SELECTED_WINDOW (f);
1886 while (!NILP (pwindow))
1888 if (EQ (window, pwindow))
1890 pwindow = XWINDOW (pwindow)->parent;
1893 if (EQ (window, pwindow))
1895 /* OK, we found it. */
1896 Lisp_Object alternative;
1897 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1899 /* If we're about to delete the selected window on the
1900 selected frame, then we should use Fselect_window to select
1901 the new window. On the other hand, if we're about to
1902 delete the selected window on any other frame, we shouldn't do
1903 anything but set the frame's selected_window slot. */
1904 if (EQ (frame, Fselected_frame (Qnil)))
1905 Fselect_window (alternative, Qnil);
1907 set_frame_selected_window (f, alternative);
1911 /* w->buffer is nil in a non-leaf window; in this case,
1912 get rid of the markers we maintain that point into that buffer. */
1913 if (!NILP (w->buffer))
1916 unchain_marker (w->pointm[CURRENT_DISP]);
1917 unchain_marker (w->pointm[DESIRED_DISP]);
1918 unchain_marker (w->pointm[CMOTION_DISP]);
1919 unchain_marker (w->start[CURRENT_DISP]);
1920 unchain_marker (w->start[DESIRED_DISP]);
1921 unchain_marker (w->start[CMOTION_DISP]);
1922 unchain_marker (w->sb_point);
1923 /* This breaks set-window-configuration if windows in the saved
1924 configuration get deleted and multiple frames are in use. */
1925 /* w->buffer = Qnil; */
1928 /* close up the hole in the sibling list */
1929 if (!NILP (w->next))
1930 XWINDOW (w->next)->prev = w->prev;
1931 if (!NILP (w->prev))
1932 XWINDOW (w->prev)->next = w->next;
1933 if (EQ (window, par->hchild))
1934 par->hchild = w->next;
1935 if (EQ (window, par->vchild))
1936 par->vchild = w->next;
1938 /* Find one of our siblings to give our space to. */
1940 Lisp_Object sib = w->prev;
1943 /* If w gives its space to its next sibling, that sibling needs
1944 to have its top/left side pulled back to where w's is.
1945 set_window_{height,width} will re-position the sibling's
1948 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1949 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1952 /* Stretch that sibling. */
1953 if (!NILP (par->vchild))
1954 set_window_pixheight
1955 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1956 if (!NILP (par->hchild))
1958 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1961 /* If parent now has only one child,
1962 put the child into the parent's place. */
1964 Lisp_Object parchild = par->hchild;
1965 if (NILP (parchild))
1966 parchild = par->vchild;
1967 if (NILP (XWINDOW (parchild)->next))
1969 replace_window (parent, parchild);
1970 mark_window_as_deleted (XWINDOW (parent));
1974 /* Since we may be deleting combination windows, we must make sure that
1975 not only W but all its children have been marked as deleted. */
1976 if (!NILP (w->hchild))
1977 delete_all_subwindows (XWINDOW (w->hchild));
1978 else if (!NILP (w->vchild))
1979 delete_all_subwindows (XWINDOW (w->vchild));
1981 mark_window_as_deleted (w);
1983 f->mirror_dirty = 1;
1988 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
1989 Return next window after WINDOW in canonical ordering of windows.
1990 If omitted, WINDOW defaults to the selected window.
1992 Optional second arg MINIBUF t means count the minibuffer window even
1993 if not active. MINIBUF nil or omitted means count the minibuffer iff
1994 it is active. MINIBUF neither t nor nil means not to count the
1995 minibuffer even if it is active.
1997 Several frames may share a single minibuffer; if the minibuffer
1998 counts, all windows on all frames that share that minibuffer count
1999 too. Therefore, `next-window' can be used to iterate through the
2000 set of windows even when the minibuffer is on another frame. If the
2001 minibuffer does not count, only windows from WINDOW's frame count.
2003 Optional third arg ALL-FRAMES t means include windows on all frames.
2004 ALL-FRAMES nil or omitted means cycle within the frames as specified
2005 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2006 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2007 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2008 Anything else means restrict to WINDOW's frame.
2010 Optional fourth argument CONSOLE controls which consoles or devices the
2011 returned window may be on. If CONSOLE is a console, return windows only
2012 on that console. If CONSOLE is a device, return windows only on that
2013 device. If CONSOLE is a console type, return windows only on consoles
2014 of that type. If CONSOLE is 'window-system, return any windows on any
2015 window-system consoles. If CONSOLE is nil or omitted, return windows only
2016 on WINDOW's console. Otherwise, all windows are considered.
2018 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2019 can use `next-window' to iterate through the entire cycle of acceptable
2020 windows, eventually ending up back at the window you started with.
2021 `previous-window' traverses the same cycle, in the reverse order.
2023 (window, minibuf, all_frames, console))
2026 Lisp_Object start_window;
2029 window = Fselected_window (Qnil);
2031 CHECK_LIVE_WINDOW (window);
2033 start_window = window;
2035 /* minibuf == nil may or may not include minibuffers.
2036 Decide if it does. */
2038 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2039 else if (! EQ (minibuf, Qt))
2041 /* Now minibuf can be t => count all minibuffer windows,
2042 lambda => count none of them,
2043 or a specific minibuffer window (the active one) to count. */
2045 /* all_frames == nil doesn't specify which frames to include. */
2046 if (NILP (all_frames))
2047 all_frames = (! EQ (minibuf, Qlambda)
2048 ? (FRAME_MINIBUF_WINDOW
2051 (XWINDOW (window)))))
2053 else if (EQ (all_frames, Qvisible))
2055 else if (ZEROP (all_frames))
2057 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2058 /* If all_frames is a frame and window arg isn't on that frame, just
2059 return the first window on the frame. */
2060 return frame_first_window (XFRAME (all_frames));
2061 else if (! EQ (all_frames, Qt))
2063 /* Now all_frames is t meaning search all frames,
2064 nil meaning search just current frame,
2065 visible meaning search just visible frames,
2066 0 meaning search visible and iconified frames,
2067 or a window, meaning search the frame that window belongs to. */
2069 /* Do this loop at least once, to get the next window, and perhaps
2070 again, if we hit the minibuffer and that is not acceptable. */
2073 /* Find a window that actually has a next one. This loop
2074 climbs up the tree. */
2075 while (tem = XWINDOW (window)->next, NILP (tem))
2076 if (tem = XWINDOW (window)->parent, !NILP (tem))
2078 else /* window must be minibuffer window now */
2080 /* We've reached the end of this frame.
2081 Which other frames are acceptable? */
2082 tem = WINDOW_FRAME (XWINDOW (window));
2084 if (! NILP (all_frames))
2089 tem = next_frame (tem, all_frames, console);
2090 /* In the case where the minibuffer is active,
2091 and we include its frame as well as the selected one,
2092 next_frame may get stuck in that frame.
2093 If that happens, go back to the selected frame
2094 so we can complete the cycle. */
2096 XSETFRAME (tem, selected_frame ());
2099 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2105 /* If we're in a combination window, find its first child and
2106 recurse on that. Otherwise, we've found the window we want. */
2109 if (!NILP (XWINDOW (window)->hchild))
2110 window = XWINDOW (window)->hchild;
2111 else if (!NILP (XWINDOW (window)->vchild))
2112 window = XWINDOW (window)->vchild;
2116 /* "acceptable" is the correct spelling. */
2117 /* Which windows are acceptable?
2118 Exit the loop and accept this window if
2119 this isn't a minibuffer window,
2120 or we're accepting all minibuffer windows,
2121 or this is the active minibuffer and we are accepting that one, or
2122 we've come all the way around and we're back at the original window. */
2123 while (MINI_WINDOW_P (XWINDOW (window))
2124 && ! EQ (minibuf, Qt)
2125 && ! EQ (minibuf, window)
2126 && ! EQ (window, start_window));
2131 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2132 Return the window preceding WINDOW in canonical ordering of windows.
2133 If omitted, WINDOW defaults to the selected window.
2135 Optional second arg MINIBUF t means count the minibuffer window even
2136 if not active. MINIBUF nil or omitted means count the minibuffer iff
2137 it is active. MINIBUF neither t nor nil means not to count the
2138 minibuffer even if it is active.
2140 Several frames may share a single minibuffer; if the minibuffer
2141 counts, all windows on all frames that share that minibuffer count
2142 too. Therefore, `previous-window' can be used to iterate through
2143 the set of windows even when the minibuffer is on another frame. If
2144 the minibuffer does not count, only windows from WINDOW's frame count
2146 If optional third arg ALL-FRAMES t means include windows on all frames.
2147 ALL-FRAMES nil or omitted means cycle within the frames as specified
2148 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2149 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2150 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2151 Anything else means restrict to WINDOW's frame.
2153 Optional fourth argument CONSOLE controls which consoles or devices the
2154 returned window may be on. If CONSOLE is a console, return windows only
2155 on that console. If CONSOLE is a device, return windows only on that
2156 device. If CONSOLE is a console type, return windows only on consoles
2157 of that type. If CONSOLE is 'window-system, return any windows on any
2158 window-system consoles. If CONSOLE is nil or omitted, return windows only
2159 on WINDOW's console. Otherwise, all windows are considered.
2161 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2162 can use `previous-window' to iterate through the entire cycle of acceptable
2163 windows, eventually ending up back at the window you started with.
2164 `next-window' traverses the same cycle, in the reverse order.
2166 (window, minibuf, all_frames, console))
2169 Lisp_Object start_window;
2172 window = Fselected_window (Qnil);
2174 CHECK_LIVE_WINDOW (window);
2176 start_window = window;
2178 /* minibuf == nil may or may not include minibuffers.
2179 Decide if it does. */
2181 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2182 else if (! EQ (minibuf, Qt))
2184 /* Now minibuf can be t => count all minibuffer windows,
2185 lambda => count none of them,
2186 or a specific minibuffer window (the active one) to count. */
2188 /* all_frames == nil doesn't specify which frames to include.
2189 Decide which frames it includes. */
2190 if (NILP (all_frames))
2191 all_frames = (! EQ (minibuf, Qlambda)
2192 ? (FRAME_MINIBUF_WINDOW
2195 (XWINDOW (window)))))
2197 else if (EQ (all_frames, Qvisible))
2199 else if (ZEROP (all_frames))
2201 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2202 /* If all_frames is a frame and window arg isn't on that frame, just
2203 return the first window on the frame. */
2204 return frame_first_window (XFRAME (all_frames));
2205 else if (! EQ (all_frames, Qt))
2207 /* Now all_frames is t meaning search all frames,
2208 nil meaning search just current frame,
2209 visible meaning search just visible frames,
2210 0 meaning search visible and iconified frames,
2211 or a window, meaning search the frame that window belongs to. */
2213 /* Do this loop at least once, to get the next window, and perhaps
2214 again, if we hit the minibuffer and that is not acceptable. */
2217 /* Find a window that actually has a next one. This loop
2218 climbs up the tree. */
2219 while (tem = XWINDOW (window)->prev, NILP (tem))
2220 if (tem = XWINDOW (window)->parent, !NILP (tem))
2222 else /* window must be minibuffer window now */
2224 /* We have found the top window on the frame.
2225 Which frames are acceptable? */
2226 tem = WINDOW_FRAME (XWINDOW (window));
2228 if (! NILP (all_frames))
2229 /* It's actually important that we use prev_frame here,
2230 rather than next_frame. All the windows acceptable
2231 according to the given parameters should form a ring;
2232 Fnext_window and Fprevious_window should go back and
2233 forth around the ring. If we use next_frame here,
2234 then Fnext_window and Fprevious_window take different
2235 paths through the set of acceptable windows.
2236 window_loop assumes that these `ring' requirement are
2242 tem = prev_frame (tem, all_frames, console);
2243 /* In the case where the minibuffer is active,
2244 and we include its frame as well as the selected one,
2245 next_frame may get stuck in that frame.
2246 If that happens, go back to the selected frame
2247 so we can complete the cycle. */
2249 XSETFRAME (tem, selected_frame ());
2252 /* If this frame has a minibuffer, find that window first,
2253 because it is conceptually the last window in that frame. */
2254 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2255 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2257 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2264 /* If we're in a combination window, find its first child and
2265 recurse on that. Otherwise, we've found the window we want. */
2268 if (!NILP (XWINDOW (window)->hchild))
2269 window = XWINDOW (window)->hchild;
2270 else if (!NILP (XWINDOW (window)->vchild))
2271 window = XWINDOW (window)->vchild;
2273 while (tem = XWINDOW (window)->next, !NILP (tem))
2277 /* Which windows are acceptable?
2278 Exit the loop and accept this window if
2279 this isn't a minibuffer window,
2280 or we're accepting all minibuffer windows,
2281 or this is the active minibuffer and we are accepting that one, or
2282 we've come all the way around and we're back at the original window. */
2283 while (MINI_WINDOW_P (XWINDOW (window))
2284 && ! EQ (minibuf, Qt)
2285 && ! EQ (minibuf, window)
2286 && ! EQ (window, start_window));
2291 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2292 Return the next window which is vertically after WINDOW.
2297 struct window *w = decode_window (window);
2298 XSETWINDOW (window, w);
2300 if (MINI_WINDOW_P (XWINDOW (window)))
2303 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2305 if (EQ (window, root))
2308 if (!NILP (XWINDOW (window)->hchild))
2309 window = XWINDOW (window)->hchild;
2310 else if (!NILP (XWINDOW (window)->vchild))
2311 window = XWINDOW (window)->vchild;
2318 if (!NILP (XWINDOW (window)->parent) &&
2319 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2321 if (!NILP (XWINDOW (window)->next))
2322 return XWINDOW (window)->next;
2324 window = XWINDOW (window)->parent;
2327 window = XWINDOW (window)->parent;
2329 while (!EQ (window, root));
2332 if (!NILP (XWINDOW (window)->hchild))
2333 window = XWINDOW (window)->hchild;
2334 else if (!NILP (XWINDOW (window)->vchild))
2335 window = XWINDOW (window)->vchild;
2340 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2341 Select the N'th different window on this frame.
2342 All windows on current frame are arranged in a cyclic order.
2343 This command selects the window N steps away in that order.
2344 A negative N moves in the opposite order.
2346 If optional argument FRAME is `visible', search all visible frames.
2347 If FRAME is 0, search all visible and iconified frames.
2348 If FRAME is t, search all frames.
2349 If FRAME is nil, search only the selected frame.
2350 If FRAME is a frame, search only that frame.
2352 Optional third argument CONSOLE controls which consoles or devices the
2353 returned window may be on. If CONSOLE is a console, return windows only
2354 on that console. If CONSOLE is a device, return windows only on that
2355 device. If CONSOLE is a console type, return windows only on consoles
2356 of that type. If CONSOLE is 'window-system, return any windows on any
2357 window-system consoles. If CONSOLE is nil or omitted, return windows only
2358 on FRAME'S console, or on the selected console if FRAME is not a frame.
2359 Otherwise, all windows are considered.
2361 (n, frame, console))
2367 w = Fselected_window (Qnil);
2372 w = Fnext_window (w, Qnil, frame, console);
2377 w = Fprevious_window (w, Qnil, frame, console);
2380 Fselect_window (w, Qnil);
2385 /* Look at all windows, performing an operation specified by TYPE
2388 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2389 frame. If FRAMES is a frame, just look at windows on that frame.
2390 If MINI is non-zero, perform the operation on minibuffer windows too.
2396 GET_BUFFER_WINDOW, /* Arg is buffer */
2397 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2398 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2399 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2401 UNSHOW_BUFFER, /* Arg is buffer */
2402 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2403 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2407 window_loop (enum window_loop type,
2412 Lisp_Object console)
2414 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2416 Lisp_Object best_window = Qnil;
2417 Lisp_Object next_window;
2418 Lisp_Object last_window;
2419 struct frame *frame;
2420 Lisp_Object frame_arg = Qt;
2421 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2422 /* #### I think the change of "precomputing" last_window and next_window
2423 * #### catch the lossage this is meant(?) to punt on...
2426 Lisp_Object devcons, concons;
2428 /* FRAME_ARG is Qlambda to stick to one frame,
2429 Qvisible to consider all visible frames,
2432 /* If we're only looping through windows on a particular frame,
2433 FRAME points to that frame. If we're looping through windows
2434 on all frames, FRAME is 0. */
2436 if (FRAMEP (frames))
2437 frame = XFRAME (frames);
2438 else if (NILP (frames))
2439 frame = selected_frame ();
2443 frame_arg = Qlambda;
2444 else if (ZEROP (frames))
2446 else if (EQ (frames, Qvisible))
2449 DEVICE_LOOP_NO_BREAK (devcons, concons)
2451 Lisp_Object device = XCAR (devcons);
2452 Lisp_Object the_frame;
2455 XSETFRAME (the_frame, frame);
2457 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2459 if (NILP (the_frame))
2462 if (!device_matches_console_spec (the_frame, device, console))
2465 /* Pick a window to start with. */
2469 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2471 /* Figure out the last window we're going to mess with. Since
2472 Fnext_window, given the same options, is guaranteed to go in a
2473 ring, we can just use Fprevious_window to find the last one.
2475 We can't just wait until we hit the first window again,
2476 because it might be deleted. */
2478 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2483 struct window *p = XWINDOW (w);
2484 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2486 /* Pick the next window now, since some operations will delete
2487 the current window. */
2488 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2490 /* #### Still needed ?? */
2491 /* Given the outstanding quality of the rest of this code,
2492 I feel no shame about putting this piece of shit in. */
2493 if (++lose_lose >= 500)
2496 /* Note that we do not pay attention here to whether
2497 the frame is visible, since Fnext_window skips non-visible frames
2498 if that is desired, under the control of frame_arg. */
2499 if (! MINI_WINDOW_P (p)
2500 || (mini && minibuf_level > 0))
2503 case GET_BUFFER_WINDOW:
2505 if (XBUFFER (p->buffer) == XBUFFER (obj))
2510 case GET_BUFFER_WINDOW_COUNT:
2512 if (XBUFFER (p->buffer) == XBUFFER (obj))
2517 case GET_LRU_WINDOW:
2519 /* t as arg means consider only full-width windows */
2521 && !window_full_width_p (p))
2523 /* Ignore dedicated windows and minibuffers. */
2524 if (MINI_WINDOW_P (p)
2525 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2527 if (NILP (best_window)
2528 || (XINT (XWINDOW (best_window)->use_time)
2529 > XINT (p->use_time)))
2534 case GET_BUFFER_MRU_WINDOW:
2536 /* #### what about the first check in GET_LRU_WINDOW? */
2537 /* Ignore dedicated windows and minibuffers. */
2538 if (MINI_WINDOW_P (p)
2539 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2542 if (XBUFFER (p->buffer) == XBUFFER (obj))
2544 if (NILP (best_window)
2545 || (XINT (XWINDOW (best_window)->use_time)
2546 < XINT (p->use_time)))
2552 case DELETE_OTHER_WINDOWS:
2554 /* Don't delete the last window on a frame; this can
2555 happen when the minibuffer is selected, and would
2556 cause the frame to be deleted. */
2557 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2558 Fdelete_window (w, Qnil);
2562 case DELETE_BUFFER_WINDOWS:
2564 if (EQ (p->buffer, obj))
2566 struct frame *f = XFRAME (WINDOW_FRAME (p));
2568 /* If this window is dedicated, and in a frame
2569 of its own, kill the frame. */
2570 if (EQ (w, FRAME_ROOT_WINDOW (f))
2571 && !NILP (p->dedicated)
2572 && other_visible_frames (f))
2574 /* Skip the other windows on this frame.
2575 There might be one, the minibuffer! */
2576 if (! EQ (w, last_window))
2577 while (f == XFRAME (WINDOW_FRAME
2578 (XWINDOW (next_window))))
2580 /* As we go, check for the end of the
2581 loop. We mustn't start going
2582 around a second time. */
2583 if (EQ (next_window, last_window))
2588 next_window = Fnext_window (next_window,
2592 /* Now we can safely delete the frame. */
2593 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2596 /* If we're deleting the buffer displayed in
2597 the only window on the frame, find a new
2598 buffer to display there. */
2599 if (NILP (p->parent))
2601 Lisp_Object new_buffer;
2602 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2603 if (NILP (new_buffer))
2604 new_buffer = Fget_buffer_create (QSscratch);
2605 Fset_window_buffer (w, new_buffer);
2606 if (EQ (w, Fselected_window (Qnil)))
2607 Fset_buffer (p->buffer);
2610 Fdelete_window (w, Qnil);
2615 case GET_LARGEST_WINDOW:
2617 /* Ignore dedicated windows and minibuffers. */
2618 if (MINI_WINDOW_P (p)
2619 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2622 /* write the check as follows to avoid tripping
2623 error_check_window() --ben */
2624 struct window *b = NILP (best_window) ? 0 :
2625 XWINDOW (best_window);
2626 if (NILP (best_window)
2627 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2628 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2636 if (EQ (p->buffer, obj))
2638 /* Find another buffer to show in this window. */
2639 Lisp_Object another_buffer =
2640 Fother_buffer (obj, Qnil, Qnil);
2641 if (NILP (another_buffer))
2643 = Fget_buffer_create (QSscratch);
2644 /* If this window is dedicated, and in a frame
2645 of its own, kill the frame. */
2646 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2647 && !NILP (p->dedicated)
2648 && other_visible_frames (w_frame))
2650 /* Skip the other windows on this frame.
2651 There might be one, the minibuffer! */
2652 if (! EQ (w, last_window))
2653 while (w_frame == XFRAME (WINDOW_FRAME
2654 (XWINDOW (next_window))))
2656 /* As we go, check for the end of the
2657 loop. We mustn't start going
2658 around a second time. */
2659 if (EQ (next_window, last_window))
2664 next_window = Fnext_window (next_window,
2668 /* Now we can safely delete the frame. */
2669 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2674 /* Otherwise show a different buffer in the
2676 p->dedicated = Qnil;
2677 Fset_window_buffer (w, another_buffer);
2678 if (EQ (w, Fselected_window (Qnil)))
2679 Fset_buffer (p->buffer);
2689 if (EQ (w, last_window))
2696 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2699 #if 0 /* not currently used */
2702 buffer_window_count (struct buffer *b, struct frame *f)
2704 Lisp_Object buffer, frame;
2706 XSETFRAME (frame, f);
2707 XSETBUFFER (buffer, b);
2709 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2714 buffer_window_mru (struct window *w)
2716 Lisp_Object window =
2717 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2721 else if (XWINDOW (window) == w)
2730 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2731 Return the window least recently selected or used for display.
2732 If optional argument FRAME is `visible', search all visible frames.
2733 If FRAME is 0, search all visible and iconified frames.
2734 If FRAME is t, search all frames.
2735 If FRAME is nil, search only the selected frame.
2736 If FRAME is a frame, search only that frame.
2738 Optional second argument CONSOLE controls which consoles or devices the
2739 returned window may be on. If CONSOLE is a console, return windows only
2740 on that console. If CONSOLE is a device, return windows only on that
2741 device. If CONSOLE is a console type, return windows only on consoles
2742 of that type. If CONSOLE is 'window-system, return any windows on any
2743 window-system consoles. If CONSOLE is nil or omitted, return windows only
2744 on FRAME'S console, or on the selected console if FRAME is not a frame.
2745 Otherwise, all windows are considered.
2750 /* First try for a non-dedicated window that is full-width */
2751 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2752 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2755 /* Then try for any non-dedicated window */
2756 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2757 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2761 /* FSFmacs never returns a dedicated window here. If we do,
2762 it makes `display-buffer' not work right. #### All of this
2763 shit is so disgusting and awful that it needs to be rethought
2765 /* then try for a dedicated window that is full-width */
2766 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2767 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2770 /* If none of them, then all windows, dedicated or not. */
2771 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2773 /* At this point we damn well better have found something. */
2774 if (NILP (w)) abort ();
2780 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2781 Return the window largest in area.
2782 If optional argument FRAME is `visible', search all visible frames.
2783 If FRAME is 0, search all visible and iconified frames.
2784 If FRAME is t, search all frames.
2785 If FRAME is nil, search only the selected frame.
2786 If FRAME is a frame, search only that frame.
2788 Optional second argument CONSOLE controls which consoles or devices the
2789 returned window may be on. If CONSOLE is a console, return windows only
2790 on that console. If CONSOLE is a device, return windows only on that
2791 device. If CONSOLE is a console type, return windows only on consoles
2792 of that type. If CONSOLE is 'window-system, return any windows on any
2793 window-system consoles. If CONSOLE is nil or omitted, return windows only
2794 on FRAME'S console, or on the selected console if FRAME is not a frame.
2795 Otherwise, all windows are considered.
2799 /* Don't search dedicated windows because FSFmacs doesn't.
2800 This stuff is all black magic so don't try to apply common
2802 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2805 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2806 Return a window currently displaying BUFFER, or nil if none.
2807 If optional argument FRAME is `visible', search all visible frames.
2808 If optional argument FRAME is 0, search all visible and iconified frames.
2809 If FRAME is t, search all frames.
2810 If FRAME is nil, search only the selected frame.
2811 If FRAME is a frame, search only that frame.
2813 Optional third argument CONSOLE controls which consoles or devices the
2814 returned window may be on. If CONSOLE is a console, return windows only
2815 on that console. If CONSOLE is a device, return windows only on that
2816 device. If CONSOLE is a console type, return windows only on consoles
2817 of that type. If CONSOLE is 'window-system, return any windows on any
2818 window-system consoles. If CONSOLE is nil or omitted, return windows only
2819 on FRAME'S console, or on the selected console if FRAME is not a frame.
2820 Otherwise, all windows are considered.
2822 (buffer, frame, console))
2824 buffer = Fget_buffer (buffer);
2825 if (BUFFERP (buffer))
2826 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2827 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2832 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2833 but there is no sensible way to implement those functions, since
2834 you can't in general derive a window from a buffer. */
2836 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2838 Return the width in pixels of the left outside margin of window WINDOW.
2839 If WINDOW is nil, the selected window is assumed.
2843 return make_int (window_left_margin_width (decode_window (window)));
2846 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2848 Return the width in pixels of the right outside margin of window WINDOW.
2849 If WINDOW is nil, the selected window is assumed.
2853 return make_int (window_right_margin_width (decode_window (window)));
2856 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2857 Make WINDOW (or the selected window) fill its frame.
2858 Only the frame WINDOW is on is affected.
2859 This function tries to reduce display jumps
2860 by keeping the text previously visible in WINDOW
2861 in the same place on the frame. Doing this depends on
2862 the value of (window-start WINDOW), so if calling this function
2863 in a program gives strange scrolling, make sure the window-start
2864 value is reasonable when this function is called.
2868 struct window *w = decode_window (window);
2869 struct buffer *b = XBUFFER (w->buffer);
2871 int old_top = WINDOW_TOP (w);
2873 XSETWINDOW (window, w);
2875 if (MINI_WINDOW_P (w) && old_top > 0)
2876 error ("Can't expand minibuffer to full frame");
2878 /* Ignore dedicated windows. */
2879 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2881 start_pos = marker_position (w->start[CURRENT_DISP]);
2883 /* Try to minimize scrolling, by setting the window start to the
2884 point which will cause the text at the old window start to be at
2885 the same place on the frame. But don't try to do this if the
2886 window start is outside the visible portion (as might happen when
2887 the display is not current, due to typeahead). */
2888 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2889 && !MINI_WINDOW_P (w))
2891 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2893 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2895 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2897 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2899 /* We need to do this, so that the window-scroll-functions
2907 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2908 "bDelete windows on (buffer): ", /*
2909 Delete all windows showing BUFFER.
2910 Optional second argument FRAME controls which frames are affected.
2911 If nil or omitted, delete all windows showing BUFFER in any frame.
2912 If t, delete only windows showing BUFFER in the selected frame.
2913 If `visible', delete all windows showing BUFFER in any visible frame.
2914 If a frame, delete only windows showing BUFFER in that frame.
2916 Optional third argument CONSOLE controls which consoles or devices the
2917 returned window may be on. If CONSOLE is a console, return windows only
2918 on that console. If CONSOLE is a device, return windows only on that
2919 device. If CONSOLE is a console type, return windows only on consoles
2920 of that type. If CONSOLE is 'window-system, return any windows on any
2921 window-system consoles. If CONSOLE is nil or omitted, return windows only
2922 on FRAME'S console, or on the selected console if FRAME is not a frame.
2923 Otherwise, all windows are considered.
2925 (buffer, frame, console))
2927 /* This function can GC */
2928 /* FRAME uses t and nil to mean the opposite of what window_loop
2930 if (!FRAMEP (frame))
2931 frame = NILP (frame) ? Qt : Qnil;
2935 buffer = Fget_buffer (buffer);
2936 CHECK_BUFFER (buffer);
2937 /* Ignore dedicated windows. */
2938 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2943 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2944 "bReplace buffer in windows: ", /*
2945 Replace BUFFER with some other buffer in all windows showing it.
2949 /* This function can GC */
2952 buffer = Fget_buffer (buffer);
2953 CHECK_BUFFER (buffer);
2954 /* Ignore dedicated windows. */
2955 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2960 /* The smallest acceptable dimensions for a window. Anything smaller
2961 might crash Emacs. */
2962 #define MIN_SAFE_WINDOW_WIDTH (2)
2963 #define MIN_SAFE_WINDOW_HEIGHT (2)
2965 /* Make sure that window_min_height and window_min_width are
2966 not too small; if they are, set them to safe minima. */
2969 check_min_window_sizes (void)
2971 /* Smaller values might permit a crash. */
2972 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2973 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2974 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2975 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2978 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2979 minimum allowable size. */
2981 check_frame_size (struct frame *frame, int *rows, int *cols)
2983 /* For height, we have to see whether the frame has a minibuffer, and
2984 whether it wants a modeline. */
2986 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2987 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2988 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2990 if (*rows < min_height)
2992 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2993 *cols = MIN_SAFE_WINDOW_WIDTH;
2996 /* Normally the window is deleted if it gets too small.
2997 nodelete nonzero means do not do this.
2998 (The caller should check later and do so if appropriate) */
3000 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3003 struct window *w = XWINDOW (window);
3004 struct frame *f = XFRAME (w->frame);
3006 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3007 Lisp_Object child, minor_kid, major_kid;
3010 int defheight, defwidth;
3012 /* #### This is very likely incorrect and instead the char_to_pixel_
3013 functions should be called. */
3014 default_face_height_and_width (window, &defheight, &defwidth);
3015 line_size = (set_height ? defheight : defwidth);
3017 check_min_window_sizes ();
3019 minsize = (set_height ? window_min_height : window_min_width);
3020 minsize *= line_size;
3023 && !TOP_LEVEL_WINDOW_P (w)
3024 && new_pixsize < minsize)
3026 Fdelete_window (window, Qnil);
3030 SET_LAST_MODIFIED (w, 0);
3031 SET_LAST_FACECHANGE (w);
3032 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3035 WINDOW_HEIGHT (w) = new_pixsize;
3036 major_kid = w->vchild;
3037 minor_kid = w->hchild;
3041 WINDOW_WIDTH (w) = new_pixsize;
3042 major_kid = w->hchild;
3043 minor_kid = w->vchild;
3046 if (!NILP (minor_kid))
3048 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3051 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3053 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3055 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3058 else if (!NILP (major_kid))
3060 int last_pos, last_old_pos, pos, old_pos, first;
3061 int pixel_adj_left = new_pixsize - old_pixsize;
3062 int div_val = old_pixsize << 1;
3065 * Previously we bailed out here if there was no size change.
3066 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3067 * toolbar appears or disappears, windows may not change size,
3068 * but their top and left coordinates need to be updated.
3070 * So we don't bail until after the loop below.
3073 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3076 for (child = major_kid; !NILP (child); child = c->next)
3078 c = XWINDOW (child);
3082 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3083 WINDOW_TOP (c) = last_pos;
3087 old_pos = last_old_pos + WINDOW_WIDTH (c);
3088 WINDOW_LEFT (c) = last_pos;
3091 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3092 /* All but the last window should have a height which is
3093 a multiple of the default line height. */
3094 if (!NILP (c->next))
3095 pos = (pos / line_size) * line_size;
3097 /* Avoid confusion: don't delete child if it becomes too small */
3098 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3100 last_pos = pos + first;
3101 last_old_pos = old_pos;
3104 /* Sometimes we may get called with our old size. In that case
3105 we don't need to do anything else. */
3106 if (!pixel_adj_left)
3109 /* Now delete any children that became too small. */
3111 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3114 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3116 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3121 /* Set the height of WINDOW and all its inferiors. */
3123 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3125 set_window_pixsize (window, new_pixheight, nodelete, 1);
3128 /* Recursively set width of WINDOW and its inferiors. */
3130 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3132 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3136 static int window_select_count;
3138 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
3139 Make WINDOW display BUFFER as its contents.
3140 BUFFER can be a buffer or buffer name.
3145 struct window *w = decode_window (window);
3147 buffer = Fget_buffer (buffer);
3148 CHECK_BUFFER (buffer);
3150 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3151 error ("Attempt to display deleted buffer");
3155 error ("Window is deleted");
3157 /* While this seems like a logical thing to do, it causes problems
3158 because of saved window configurations. It is possible for a
3159 buffer to get restored into a window in which it is already being
3160 displayed, but start and point are actually at completely
3161 different locations. So we let this function complete fully and
3162 it will then make sure redisplay correctly updates things.
3164 #### This is a kludge. The correct approach is not to do this
3165 but to fix set-window-configuration. */
3167 else if (EQ (tem, buffer))
3170 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3171 is first being set up. */
3173 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3174 error ("Window is dedicated to buffer %s",
3175 XSTRING_DATA (XBUFFER (tem)->name));
3181 w->window_end_pos[CURRENT_DISP] = 0;
3183 w->modeline_hscroll = 0;
3184 Fset_marker (w->pointm[CURRENT_DISP],
3185 make_int (BUF_PT (XBUFFER (buffer))),
3187 set_marker_restricted (w->start[CURRENT_DISP],
3188 make_int (XBUFFER (buffer)->last_window_start),
3190 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3191 /* set start_at_line_beg correctly. GE */
3192 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3193 marker_position (w->start[CURRENT_DISP]));
3194 w->force_start = 0; /* Lucid fix */
3195 SET_LAST_MODIFIED (w, 1);
3196 SET_LAST_FACECHANGE (w);
3197 MARK_WINDOWS_CHANGED (w);
3198 recompute_all_cached_specifiers_in_window (w);
3199 if (EQ (window, Fselected_window (Qnil)))
3201 Fset_buffer (buffer);
3206 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3207 Select WINDOW. Most editing will apply to WINDOW's buffer.
3208 The main editor command loop selects the buffer of the selected window
3209 before each command.
3211 With non-nil optional argument `norecord', do not modify the
3212 global or per-frame buffer ordering.
3217 Lisp_Object old_selected_window = Fselected_window (Qnil);
3219 CHECK_LIVE_WINDOW (window);
3220 w = XWINDOW (window);
3222 /* we have already caught dead-window errors */
3223 if (!NILP (w->hchild) || !NILP (w->vchild))
3224 error ("Trying to select non-leaf window");
3226 w->use_time = make_int (++window_select_count);
3227 if (EQ (window, old_selected_window))
3230 /* deselect the old window, if it exists (it might not exist if
3231 the selected device has no frames, which occurs at startup) */
3232 if (!NILP (old_selected_window))
3234 struct window *ow = XWINDOW (old_selected_window);
3236 Fset_marker (ow->pointm[CURRENT_DISP],
3237 make_int (BUF_PT (XBUFFER (ow->buffer))),
3240 MARK_WINDOWS_CHANGED (ow);
3243 /* now select the window's frame */
3244 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3246 select_frame_1 (WINDOW_FRAME (w));
3248 /* also select the window's buffer */
3249 if (NILP (norecord))
3250 Frecord_buffer (w->buffer);
3251 Fset_buffer (w->buffer);
3253 /* Go to the point recorded in the window.
3254 This is important when the buffer is in more
3255 than one window. It also matters when
3256 redisplay_window has altered point after scrolling,
3257 because it makes the change only in the window. */
3259 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3260 if (new_point < BUF_BEGV (current_buffer))
3261 new_point = BUF_BEGV (current_buffer);
3262 else if (new_point > BUF_ZV (current_buffer))
3263 new_point = BUF_ZV (current_buffer);
3265 BUF_SET_PT (current_buffer, new_point);
3268 MARK_WINDOWS_CHANGED (w);
3274 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3275 Lisp_Object override_frame)
3277 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3281 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3283 /* This function can GC */
3286 struct buffer *b = XBUFFER (buf);
3288 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3289 widen_buffer (b, 0);
3290 BUF_SET_PT (b, BUF_BEG (b));
3292 if (!NILP (Vtemp_buffer_show_function))
3293 call1 (Vtemp_buffer_show_function, buf);
3296 window = display_buffer (buf, Qnil, same_frame);
3298 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3299 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3301 Vminibuffer_scroll_window = window;
3302 w = XWINDOW (window);
3304 w->modeline_hscroll = 0;
3305 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3306 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3307 set_marker_restricted (w->sb_point, make_int (1), buf);
3309 /* Run temp-buffer-show-hook, with the chosen window selected. */
3310 if (!preparing_for_armageddon)
3313 tem = Fboundp (Qtemp_buffer_show_hook);
3316 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3319 int count = specpdl_depth ();
3321 /* Select the window that was chosen, for running
3323 record_unwind_protect (save_window_excursion_unwind,
3324 Fcurrent_window_configuration (Qnil));
3326 Fselect_window (window, Qnil);
3327 run_hook (Qtemp_buffer_show_hook);
3328 unbind_to (count, Qnil);
3336 make_dummy_parent (Lisp_Object window)
3339 struct window *o = XWINDOW (window);
3340 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3342 XSETWINDOW (new, p);
3343 copy_lcrecord (p, o);
3345 /* Don't copy the pointers to the line start cache or the face
3347 p->line_start_cache = Dynarr_new (line_start_cache);
3348 p->face_cachels = Dynarr_new (face_cachel);
3349 p->glyph_cachels = Dynarr_new (glyph_cachel);
3351 /* Put new into window structure in place of window */
3352 replace_window (window, new);
3360 p->start[CURRENT_DISP] = Qnil;
3361 p->start[DESIRED_DISP] = Qnil;
3362 p->start[CMOTION_DISP] = Qnil;
3363 p->pointm[CURRENT_DISP] = Qnil;
3364 p->pointm[DESIRED_DISP] = Qnil;
3365 p->pointm[CMOTION_DISP] = Qnil;
3370 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3371 Split WINDOW, putting SIZE lines in the first of the pair.
3372 WINDOW defaults to selected one and SIZE to half its size.
3373 If optional third arg HOR-FLAG is non-nil, split side by side
3374 and put SIZE columns in the first of the pair.
3376 (window, chsize, horflag))
3379 struct window *o, *p;
3385 window = Fselected_window (Qnil);
3387 CHECK_LIVE_WINDOW (window);
3389 o = XWINDOW (window);
3390 f = XFRAME (WINDOW_FRAME (o));
3394 if (!NILP (horflag))
3395 /* In the new scheme, we are symmetric with respect to separators
3396 so there is no need to do weird things here. */
3398 psize = WINDOW_WIDTH (o) >> 1;
3399 size = window_pixel_width_to_char_width (o, psize, 0);
3403 psize = WINDOW_HEIGHT (o) >> 1;
3404 size = window_pixel_height_to_char_height (o, psize, 1);
3410 size = XINT (chsize);
3411 if (!NILP (horflag))
3412 psize = window_char_width_to_pixel_width (o, size, 0);
3414 psize = window_char_height_to_pixel_height (o, size, 1);
3417 if (MINI_WINDOW_P (o))
3418 error ("Attempt to split minibuffer window");
3419 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3420 error ("Attempt to split unsplittable frame");
3422 check_min_window_sizes ();
3426 if (size < window_min_height)
3427 error ("Window height %d too small (after splitting)", size);
3428 if (size + window_min_height > window_char_height (o, 1))
3429 error ("Window height %d too small (after splitting)",
3430 window_char_height (o, 1) - size);
3431 if (NILP (o->parent)
3432 || NILP (XWINDOW (o->parent)->vchild))
3434 make_dummy_parent (window);
3435 reset_face_cachels (XWINDOW (window));
3437 XWINDOW (new)->vchild = window;
3438 XFRAME (o->frame)->mirror_dirty = 1;
3443 if (size < window_min_width)
3444 error ("Window width %d too small (after splitting)", size);
3445 if (size + window_min_width > window_char_width (o, 0))
3446 error ("Window width %d too small (after splitting)",
3447 window_char_width (o, 0) - size);
3448 if (NILP (o->parent)
3449 || NILP (XWINDOW (o->parent)->hchild))
3451 make_dummy_parent (window);
3452 reset_face_cachels (XWINDOW (window));
3454 XWINDOW (new)->hchild = window;
3455 XFRAME (o->frame)->mirror_dirty = 1;
3459 /* Now we know that window's parent is a vertical combination
3460 if we are dividing vertically, or a horizontal combination
3461 if we are making side-by-side windows */
3463 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3464 new = allocate_window ();
3467 p->frame = o->frame;
3469 if (!NILP (p->next))
3470 XWINDOW (p->next)->prev = new;
3473 p->parent = o->parent;
3476 reset_face_cachels (p);
3477 reset_glyph_cachels (p);
3480 /* Apportion the available frame space among the two new windows */
3482 if (!NILP (horflag))
3484 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3485 WINDOW_TOP (p) = WINDOW_TOP (o);
3486 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3487 WINDOW_WIDTH (o) = psize;
3488 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3492 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3493 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3494 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3495 WINDOW_HEIGHT (o) = psize;
3496 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3499 XFRAME (p->frame)->mirror_dirty = 1;
3500 /* do this last (after the window is completely initialized and
3501 the mirror-dirty flag is set) so that specifier recomputation
3502 caused as a result of this will work properly and not abort. */
3503 Fset_window_buffer (new, o->buffer);
3508 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3509 Make the selected window N lines bigger.
3510 From program, optional second arg SIDE non-nil means grow sideways N columns,
3511 and optional third arg WINDOW specifies the window to change instead of the
3516 struct window *w = decode_window (window);
3518 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3522 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3523 Make the selected window N pixels bigger.
3524 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3525 and optional third arg WINDOW specifies the window to change instead of the
3530 struct window *w = decode_window (window);
3532 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3536 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3537 Make the selected window N lines smaller.
3538 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3539 and optional third arg WINDOW specifies the window to change instead of the
3545 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3550 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3551 Make the selected window N pixels smaller.
3552 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3553 and optional third arg WINDOW specifies the window to change instead of the
3559 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3565 window_pixel_height (Lisp_Object window)
3567 return WINDOW_HEIGHT (XWINDOW (window));
3571 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3572 int include_gutters_p)
3575 int defheight, defwidth;
3579 XSETWINDOW (window, w);
3581 avail_height = (pixel_height -
3582 (include_gutters_p ? 0 :
3583 window_top_gutter_height (w) +
3584 window_bottom_gutter_height (w)));
3586 default_face_height_and_width (window, &defheight, &defwidth);
3588 char_height = avail_height / defheight;
3590 /* It's the calling function's responsibility to check these values
3591 and make sure they're not out of range.
3593 #### We need to go through the calling functions and actually
3595 return max (0, char_height);
3599 window_char_height_to_pixel_height (struct window *w, int char_height,
3600 int include_gutters_p)
3603 int defheight, defwidth;
3608 XSETWINDOW (window, w);
3610 default_face_height_and_width (window, &defheight, &defwidth);
3612 avail_height = char_height * defheight;
3613 pixel_height = (avail_height +
3614 (include_gutters_p ? 0 :
3615 window_top_gutter_height (w) +
3616 window_bottom_gutter_height (w)));
3618 /* It's the calling function's responsibility to check these values
3619 and make sure they're not out of range.
3621 #### We need to go through the calling functions and actually
3623 return max (0, pixel_height);
3626 /* Return number of default lines of text can fit in the window W.
3627 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3628 horizontal scrollbar) in the space that is used for the calculation.
3631 window_char_height (struct window *w, int include_gutters_p)
3633 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3638 * Return number of lines currently displayed in window w. If
3639 * end-of-buffer is displayed then the area below end-of-buffer is assume
3640 * to be blank lines of default height.
3641 * Does not include the modeline.
3644 window_displayed_height (struct window *w)
3646 struct buffer *b = XBUFFER (w->buffer);
3647 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3649 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3651 : w->window_end_pos[CURRENT_DISP]);
3653 if (!Dynarr_length (dla))
3654 return window_char_height (w, 0);
3656 num_lines = Dynarr_length (dla);
3658 /* #### Document and assert somewhere that w->window_end_pos == -1
3659 indicates that end-of-buffer is being displayed. */
3662 struct display_line *dl = Dynarr_atp (dla, 0);
3663 int ypos1 = dl->ypos + dl->descent;
3664 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3666 int defheight, defwidth;
3668 XSETWINDOW (window, w);
3674 if (Dynarr_length (dla) == 1)
3675 ypos1 = WINDOW_TEXT_TOP (w);
3678 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3679 /* If this line is clipped then we know that there is no
3680 blank room between eob and the modeline. If we are
3681 scrolling on clipped lines just know off the clipped
3683 if (scroll_on_clipped_lines && dl->clip)
3684 return num_lines - 1;
3685 ypos1 = dl->ypos + dl->descent - dl->clip;
3689 default_face_height_and_width (window, &defheight, &defwidth);
3690 /* #### This probably needs to know about the clipping area once a
3691 final definition is decided on. */
3692 num_lines += ((ypos2 - ypos1) / defheight);
3696 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3699 if (scroll_on_clipped_lines
3700 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3708 window_pixel_width (Lisp_Object window)
3710 return WINDOW_WIDTH (XWINDOW (window));
3714 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3715 int include_margins_p)
3719 int defheight, defwidth;
3722 XSETWINDOW (window, w);
3724 avail_width = (pixel_width -
3725 window_left_gutter_width (w, 0) -
3726 window_right_gutter_width (w, 0) -
3727 (include_margins_p ? 0 : window_left_margin_width (w)) -
3728 (include_margins_p ? 0 : window_right_margin_width (w)));
3730 default_face_height_and_width (window, &defheight, &defwidth);
3732 char_width = (avail_width / defwidth);
3734 /* It's the calling function's responsibility to check these values
3735 and make sure they're not out of range.
3737 #### We need to go through the calling functions and actually
3739 return max (0, char_width);
3743 window_char_width_to_pixel_width (struct window *w, int char_width,
3744 int include_margins_p)
3748 int defheight, defwidth;
3751 XSETWINDOW (window, w);
3753 default_face_height_and_width (window, &defheight, &defwidth);
3755 avail_width = char_width * defwidth;
3756 pixel_width = (avail_width +
3757 window_left_gutter_width (w, 0) +
3758 window_right_gutter_width (w, 0) +
3759 (include_margins_p ? 0 : window_left_margin_width (w)) +
3760 (include_margins_p ? 0 : window_right_margin_width (w)));
3762 /* It's the calling function's responsibility to check these values
3763 and make sure they're not out of range.
3765 #### We need to go through the calling functions and actually
3767 return max (0, pixel_width);
3770 /* This returns the usable space which doesn't include space needed by
3771 scrollbars or divider lines. */
3773 window_char_width (struct window *w, int include_margins_p)
3775 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3779 #define MINSIZE(w) \
3781 ? window_min_width * defwidth \
3782 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3785 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3787 #define CURSIZE(w) \
3788 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3790 #define CURCHARSIZE(w) \
3791 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3793 #define MINCHARSIZE(window) \
3794 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3795 ? 1 : window_min_height)
3797 /* Unlike set_window_pixheight, this function
3798 also changes the heights of the siblings so as to
3799 keep everything consistent. */
3802 change_window_height (struct window *win, int delta, int widthflag,
3810 int (*sizefun) (Lisp_Object) = (widthflag
3811 ? window_pixel_width
3812 : window_pixel_height);
3813 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3814 ? set_window_pixwidth
3815 : set_window_pixheight);
3817 int defheight, defwidth;
3822 check_min_window_sizes ();
3824 XSETWINDOW (window, win);
3825 f = XFRAME (win->frame);
3826 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3827 error ("Won't change only window");
3829 /* #### This is very likely incorrect and instead the char_to_pixel_
3830 functions should be called. */
3831 default_face_height_and_width (window, &defheight, &defwidth);
3835 w = XWINDOW (window);
3840 error ("No other window to side of this one");
3844 ? !NILP (XWINDOW (parent)->hchild)
3845 : !NILP (XWINDOW (parent)->vchild))
3850 sizep = &CURSIZE (w);
3851 dim = CURCHARSIZE (w);
3853 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3854 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3856 if (MINI_WINDOW_P (XWINDOW (window)))
3858 else if (!NILP (parent))
3860 Fdelete_window (window, Qnil);
3866 delta *= (widthflag ? defwidth : defheight);
3871 maxdelta = ((!NILP (parent))
3872 ? (*sizefun) (parent) - *sizep
3873 : ((!NILP (w->next))
3874 ? (*sizefun) (w->next) - MINSIZE (w->next)
3875 : ((!NILP (w->prev))
3876 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3877 /* This is a frame with only one window,
3878 a minibuffer-only or a minibufferless frame. */
3881 if (delta > maxdelta)
3882 /* This case traps trying to make the minibuffer
3883 the full frame, or make the only window aside from the
3884 minibuffer the full frame. */
3891 /* #### Chuck: is this correct? */
3892 if (*sizep + delta < MINSIZE (window))
3894 Fdelete_window (window);
3900 if (!NILP (w->next) &&
3901 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3903 CURBEG (XWINDOW (w->next)) += delta;
3904 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3905 (*setsizefun) (window, *sizep + delta, 0);
3907 else if (!NILP (w->prev) &&
3908 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3910 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3911 CURBEG (w) -= delta;
3912 (*setsizefun) (window, *sizep + delta, 0);
3917 int opht = (*sizefun) (parent);
3919 /* If trying to grow this window to or beyond size of the parent,
3920 make delta1 so big that, on shrinking back down,
3921 all the siblings end up with less than one line and are deleted. */
3922 if (opht <= *sizep + delta)
3923 delta1 = opht * opht * 2;
3924 /* Otherwise, make delta1 just right so that if we add delta1
3925 lines to this window and to the parent, and then shrink
3926 the parent back to its original size, the new proportional
3927 size of this window will increase by delta. */
3929 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3931 /* Add delta1 lines or columns to this window, and to the parent,
3932 keeping things consistent while not affecting siblings. */
3933 CURSIZE (XWINDOW (parent)) = opht + delta1;
3934 (*setsizefun) (window, *sizep + delta1, 0);
3936 /* Squeeze out delta1 lines or columns from our parent,
3937 shrinking this window and siblings proportionately.
3938 This brings parent back to correct size.
3939 Delta1 was calculated so this makes this window the desired size,
3940 taking it all out of the siblings. */
3941 (*setsizefun) (parent, opht, 0);
3944 SET_LAST_MODIFIED (w, 0);
3945 SET_LAST_FACECHANGE (w);
3946 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3947 /* overkill maybe, but better to be correct */
3948 MARK_FRAME_GUTTERS_CHANGED (f);
3958 /* Scroll contents of window WINDOW up N lines. If N < (top line height /
3959 average line height) then we just adjust the top clip. */
3961 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
3962 Error_behavior errb)
3964 struct window *w = XWINDOW (window);
3965 struct buffer *b = XBUFFER (w->buffer);
3966 int selected = EQ (window, Fselected_window (Qnil));
3968 Lisp_Object point, tem;
3969 display_line_dynarr *dla;
3970 int fheight, fwidth, modeline = 0;
3971 struct display_line* dl;
3974 point = make_int (BUF_PT (b));
3977 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
3979 if (pos < BUF_BEGV (b))
3981 else if (pos > BUF_ZV (b))
3984 point = make_int (pos);
3987 /* Always set force_start so that redisplay_window will run
3988 the window-scroll-functions. */
3991 /* #### When the fuck does this happen? I'm so glad that history has
3992 completely documented the behavior of the scrolling functions under
3993 all circumstances. */
3994 tem = Fpos_visible_in_window_p (point, window);
3997 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
3999 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4000 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4001 WINDOW_TEXT_TOP_CLIP (w) = 0;
4002 MARK_WINDOWS_CHANGED (w);
4011 n = Fprefix_numeric_value (n);
4012 value = XINT (n) * direction;
4015 return; /* someone just made a pointless call */
4019 /* If the user didn't specify how far to scroll then we have to figure it
4020 out by ourselves. */
4021 if (NILP (n) || EQ (n, Qminus))
4023 /* Going forwards is easy. If that is what we are doing then just
4024 set value and the section which handles the user specifying a
4025 positive value will work. */
4028 value = window_displayed_height (w) - next_screen_context_lines;
4029 value = (value < 1 ? 1 : value);
4032 /* Going backwards is hard. We can't use the same loop used if the
4033 user specified a negative value because we care about
4034 next_screen_context_lines. In a variable height world you don't
4035 know how many lines above you can actually be displayed and still
4036 have the context lines appear. So we leave value set to 0 and add
4037 a separate section to deal with this. */
4041 if (direction == 1 && !value)
4046 /* Determine parameters to test for partial line scrolling with. */
4047 dla = window_display_lines (w, CURRENT_DISP);
4049 if (INTP (Vwindow_pixel_scroll_increment))
4050 fheight = XINT (Vwindow_pixel_scroll_increment);
4051 else if (!NILP (Vwindow_pixel_scroll_increment));
4052 default_face_height_and_width (window, &fheight, &fwidth);
4054 if (Dynarr_length (dla) >= 1)
4055 modeline = Dynarr_atp (dla, 0)->modeline;
4057 dl = Dynarr_atp (dla, modeline);
4061 /* Go for partial display line scrolling. This just means bumping
4062 the clip by a reasonable amount and redisplaying, everything else
4063 remains unchanged. */
4064 if (!NILP (Vwindow_pixel_scroll_increment)
4066 Dynarr_length (dla) >= (1 + modeline)
4068 (dl->ascent - dl->top_clip) - fheight * value > 0)
4070 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4071 MARK_WINDOWS_CHANGED (w);
4076 Bufpos startp, old_start;
4078 if (WINDOW_TEXT_TOP_CLIP (w))
4080 WINDOW_TEXT_TOP_CLIP (w) = 0;
4081 MARK_WINDOWS_CHANGED (w);
4084 old_start = marker_position (w->start[CURRENT_DISP]);
4085 startp = vmotion (w, old_start, value, &vtarget);
4087 if (vtarget < value &&
4088 (w->window_end_pos[CURRENT_DISP] == -1
4089 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4091 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4096 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4099 w->start_at_line_beg = beginning_of_line_p (b, startp);
4100 MARK_WINDOWS_CHANGED (w);
4102 if (!point_would_be_visible (w, startp, XINT (point)))
4105 BUF_SET_PT (b, startp);
4107 set_marker_restricted (w->pointm[CURRENT_DISP],
4116 /* Go for partial display line scrolling. This just means bumping
4117 the clip by a reasonable amount and redisplaying, everything else
4118 remains unchanged. */
4119 if (!NILP (Vwindow_pixel_scroll_increment)
4121 Dynarr_length (dla) >= (1 + modeline)
4123 (dl->ascent - dl->top_clip) - fheight * value <
4124 (dl->ascent + dl->descent - dl->clip)
4126 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4128 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4129 MARK_WINDOWS_CHANGED (w);
4134 Bufpos startp, old_start;
4136 if (WINDOW_TEXT_TOP_CLIP (w))
4138 WINDOW_TEXT_TOP_CLIP (w) = 0;
4139 MARK_WINDOWS_CHANGED (w);
4142 old_start = marker_position (w->start[CURRENT_DISP]);
4143 startp = vmotion (w, old_start, value, &vtarget);
4146 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4148 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4153 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4156 w->start_at_line_beg = beginning_of_line_p (b, startp);
4157 MARK_WINDOWS_CHANGED (w);
4159 if (!point_would_be_visible (w, startp, XINT (point)))
4163 if (MINI_WINDOW_P (w))
4166 new_point = start_of_last_line (w, startp);
4169 BUF_SET_PT (b, new_point);
4171 set_marker_restricted (w->pointm[CURRENT_DISP],
4172 make_int (new_point),
4178 else /* value == 0 && direction == -1 */
4180 if (WINDOW_TEXT_TOP_CLIP (w))
4182 WINDOW_TEXT_TOP_CLIP (w) = 0;
4183 MARK_WINDOWS_CHANGED (w);
4185 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4187 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4193 int movement = next_screen_context_lines - 1;
4194 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4195 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4197 start_with_point_on_display_line (w, bottom,
4198 -1 - (movement - vtarget));
4200 if (startp >= old_startp)
4201 startp = vmotion (w, old_startp, -1, NULL);
4203 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4206 w->start_at_line_beg = beginning_of_line_p (b, startp);
4207 MARK_WINDOWS_CHANGED (w);
4209 if (!point_would_be_visible (w, startp, XINT (point)))
4211 Bufpos new_point = start_of_last_line (w, startp);
4214 BUF_SET_PT (b, new_point);
4216 set_marker_restricted (w->pointm[CURRENT_DISP],
4217 make_int (new_point),
4224 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4225 Scroll text of current window upward N lines; or near full screen if no arg.
4226 A near full screen is `next-screen-context-lines' less than a full screen.
4227 Negative N means scroll downward.
4228 When calling from a program, supply an integer as argument or nil.
4229 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4230 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4235 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4239 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4240 Scroll text of current window downward N lines; or near full screen if no arg.
4241 A near full screen is `next-screen-context-lines' less than a full screen.
4242 Negative N means scroll upward.
4243 When calling from a program, supply a number as argument or nil.
4244 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4245 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4250 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4254 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4255 Return the other window for "other window scroll" commands.
4256 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4257 specifies the window.
4258 If `other-window-scroll-buffer' is non-nil, a window
4259 showing that buffer is used.
4264 Lisp_Object selected_window = Fselected_window (Qnil);
4266 if (MINI_WINDOW_P (XWINDOW (selected_window))
4267 && !NILP (Vminibuffer_scroll_window))
4268 window = Vminibuffer_scroll_window;
4269 /* If buffer is specified, scroll that buffer. */
4270 else if (!NILP (Vother_window_scroll_buffer))
4272 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4274 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4278 /* Nothing specified; look for a neighboring window on the same
4280 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4282 if (EQ (window, selected_window))
4283 /* That didn't get us anywhere; look for a window on another
4286 window = Fnext_window (window, Qnil, Qt, Qnil);
4287 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4288 && ! EQ (window, selected_window));
4291 CHECK_LIVE_WINDOW (window);
4293 if (EQ (window, selected_window))
4294 error ("There is no other window");
4299 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4300 Scroll next window upward N lines; or near full frame if no arg.
4301 The next window is the one below the current one; or the one at the top
4302 if the current one is at the bottom. Negative N means scroll downward.
4303 When calling from a program, supply a number as argument or nil.
4305 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4306 specifies the window to scroll.
4307 If `other-window-scroll-buffer' is non-nil, scroll the window
4308 showing that buffer, popping the buffer up if necessary.
4312 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4316 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4317 Scroll selected window display N columns left.
4318 Default for N is window width minus 2.
4322 Lisp_Object window = Fselected_window (Qnil);
4323 struct window *w = XWINDOW (window);
4324 int count = (NILP (n) ?
4325 window_char_width (w, 0) - 2 :
4326 XINT (Fprefix_numeric_value (n)));
4328 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4331 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4332 Scroll selected window display N columns right.
4333 Default for N is window width minus 2.
4337 Lisp_Object window = Fselected_window (Qnil);
4338 struct window *w = XWINDOW (window);
4339 int count = (NILP (n) ?
4340 window_char_width (w, 0) - 2 :
4341 XINT (Fprefix_numeric_value (n)));
4343 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4346 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4347 Center point in WINDOW. With N, put point on line N.
4348 The desired position of point is always relative to the window.
4349 If WINDOW is nil, the selected window is used.
4353 struct window *w = decode_window (window);
4354 struct buffer *b = XBUFFER (w->buffer);
4355 Bufpos opoint = BUF_PT (b);
4359 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4362 n = Fprefix_numeric_value (n);
4364 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4367 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4369 w->start_at_line_beg = beginning_of_line_p (b, startp);
4371 MARK_WINDOWS_CHANGED (w);
4375 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4376 Position point relative to WINDOW.
4377 With no argument, position text at center of window.
4378 An argument specifies window line; zero means top of window,
4379 negative means relative to bottom of window.
4380 If WINDOW is nil, the selected window is used.
4387 Bufpos start, new_point;
4390 /* Don't use decode_window() because we need the new value of
4393 window = Fselected_window (Qnil);
4395 CHECK_LIVE_WINDOW (window);
4396 w = XWINDOW (window);
4397 b = XBUFFER (w->buffer);
4399 height = window_displayed_height (w);
4400 selected = EQ (window, Fselected_window (w->frame));
4406 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4407 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4409 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4412 BUF_SET_PT (b, new_point);
4414 Fset_window_point (window, make_int (new_point));
4416 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4420 start = marker_position (w->start[CURRENT_DISP]);
4421 if (start < BUF_BEGV (b))
4422 start = BUF_BEGV (b);
4423 else if (start > BUF_ZV (b))
4427 new_point = BUF_PT (b);
4429 new_point = marker_position (w->pointm[CURRENT_DISP]);
4431 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4434 BUF_SET_PT (b, new_point);
4436 Fset_window_point (window, make_int (new_point));
4438 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4441 return make_int (retval);
4445 /* #### Is this going to work right when at eob? */
4446 arg = Fprefix_numeric_value (arg);
4448 XSETINT (arg, XINT (arg) + height);
4451 start = marker_position (w->start[CURRENT_DISP]);
4452 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4455 new_point = BUF_PT (b);
4457 new_point = marker_position (w->pointm[CURRENT_DISP]);
4459 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4462 BUF_SET_PT (b, new_point);
4464 Fset_window_point (window, make_int (new_point));
4466 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4468 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4474 BUF_SET_PT (b, start);
4476 Fset_window_point (window, make_int (start));
4480 return Fvertical_motion (arg, window, Qnil);
4484 new_point = vmotion (XWINDOW (window),
4485 marker_position (w->pointm[CURRENT_DISP]),
4487 Fset_window_point (window, make_int (new_point));
4488 return make_int (vpos);
4494 map_windows_1 (Lisp_Object window,
4495 int (*mapfun) (struct window *w, void *closure),
4498 for (; !NILP (window); window = XWINDOW (window)->next)
4501 struct window *w = XWINDOW (window);
4503 if (!NILP (w->vchild))
4504 retval = map_windows_1 (w->vchild, mapfun, closure);
4505 else if (!NILP (w->hchild))
4506 retval = map_windows_1 (w->hchild, mapfun, closure);
4508 retval = (mapfun) (w, closure);
4517 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4518 invocation of MAPFUN. If any invocation of MAPFUN returns
4519 non-zero, the mapping is halted. Otherwise, map_windows() maps
4520 over all windows in F.
4522 If MAPFUN creates or deletes windows, the behavior is undefined. */
4525 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4529 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4532 Lisp_Object frmcons, devcons, concons;
4534 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4536 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4548 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4551 w->shadow_thickness_changed = 1;
4552 MARK_WINDOWS_CHANGED (w);
4556 vertical_divider_changed_in_window (Lisp_Object specifier,
4560 MARK_WINDOWS_CHANGED (w);
4561 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4564 /* also used in scrollbar.c */
4566 some_window_value_changed (Lisp_Object specifier, struct window *w,
4569 MARK_WINDOWS_CHANGED (w);
4572 #ifdef MEMORY_USAGE_STATS
4578 #ifdef HAVE_SCROLLBARS
4582 int other_redisplay;
4587 compute_window_mirror_usage (struct window_mirror *mir,
4588 struct window_stats *stats,
4589 struct overhead_stats *ovstats)
4593 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4595 #ifdef HAVE_SCROLLBARS
4597 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4600 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4603 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4606 #endif /* HAVE_SCROLLBARS */
4607 stats->other_redisplay +=
4608 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4609 stats->other_redisplay +=
4610 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4614 compute_window_usage (struct window *w, struct window_stats *stats,
4615 struct overhead_stats *ovstats)
4618 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4619 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4620 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4621 stats->line_start +=
4622 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4623 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4626 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4627 Return stats about the memory usage of window WINDOW.
4628 The values returned are in the form of an alist of usage types and byte
4629 counts. The byte counts attempt to encompass all the memory used
4630 by the window (separate from the memory logically associated with a
4631 buffer or frame), including internal structures and any malloc()
4632 overhead associated with them. In practice, the byte counts are
4633 underestimated because certain memory usage is very hard to determine
4634 \(e.g. the amount of memory used inside the Xt library or inside the
4635 X server) and because there is other stuff that might logically
4636 be associated with a window, buffer, or frame (e.g. window configurations,
4637 glyphs) but should not obviously be included in the usage counts.
4639 Multiple slices of the total memory usage may be returned, separated
4640 by a nil. Each slice represents a particular view of the memory, a
4641 particular way of partitioning it into groups. Within a slice, there
4642 is no overlap between the groups of memory, and each slice collectively
4643 represents all the memory concerned.
4647 struct window_stats stats;
4648 struct overhead_stats ovstats;
4649 Lisp_Object val = Qnil;
4651 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4653 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4655 val = acons (Qface_cache, make_int (stats.face), val);
4656 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4657 #ifdef HAVE_SCROLLBARS
4658 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4660 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4661 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4662 val = acons (Qother, make_int (stats.other), val);
4663 val = Fcons (Qnil, val);
4664 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4665 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4666 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4668 return Fnreverse (val);
4671 #endif /* MEMORY_USAGE_STATS */
4674 /************************************************************************/
4675 /* Window configurations */
4676 /************************************************************************/
4678 /* #### This window configuration stuff has had serious bugs lurking in it
4679 for years; it would be a -huge- win if this was reimplemented in lisp.
4682 /* If you add anything to this structure make sure saved_window_equal
4686 Lisp_Object window; /* window */
4687 Lisp_Object buffer; /* buffer */
4688 Lisp_Object start; /* copied marker */
4689 Lisp_Object pointm; /* copied marker */
4690 Lisp_Object sb_point; /* copied marker */
4691 Lisp_Object mark; /* copied marker */
4697 int modeline_hscroll;
4698 int parent_index; /* index into saved_windows */
4699 int prev_index; /* index into saved_windows */
4700 char start_at_line_beg; /* boolean */
4702 #define WINDOW_SLOT_DECLARATION
4703 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4704 #include "winslots.h"
4707 /* If you add anything to this structure make sure window_config_equal
4709 struct window_config
4711 struct lcrecord_header header;
4712 /* int frame_width; No longer needed, JV
4713 int frame_height; */
4715 Lisp_Object selected_frame;
4717 Lisp_Object current_window;
4718 Lisp_Object current_buffer;
4719 Lisp_Object minibuffer_scroll_window;
4720 Lisp_Object root_window;
4721 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4722 /* Record the values of window-min-width and window-min-height
4723 so that window sizes remain consistent with them. */
4724 int min_width, min_height;
4725 int saved_windows_count;
4726 /* Zero-sized arrays aren't ANSI C */
4727 struct saved_window saved_windows[1];
4730 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4731 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4732 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4733 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4734 #define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
4735 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4738 mark_window_config (Lisp_Object obj)
4740 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4742 mark_object (config->current_window);
4743 mark_object (config->current_buffer);
4744 mark_object (config->minibuffer_scroll_window);
4745 mark_object (config->root_window);
4747 for (i = 0; i < config->saved_windows_count; i++)
4749 struct saved_window *s = SAVED_WINDOW_N (config, i);
4750 mark_object (s->window);
4751 mark_object (s->buffer);
4752 mark_object (s->start);
4753 mark_object (s->pointm);
4754 mark_object (s->sb_point);
4755 mark_object (s->mark);
4757 /* #### This looked like this. I do not see why specifier cached
4758 values should not be marked, as such specifiers as toolbars
4759 might have GC-able instances. Freed configs are not marked,
4760 aren't they? -- kkm */
4761 mark_object (s->dedicated);
4763 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
4764 #include "winslots.h"
4771 sizeof_window_config_for_n_windows (int n)
4773 return (sizeof (struct window_config) +
4774 /* n - 1 because zero-sized arrays aren't ANSI C */
4775 (n - 1) *sizeof (struct saved_window));
4779 sizeof_window_config (CONST void *h)
4781 CONST struct window_config *c = (CONST struct window_config *) h;
4782 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4786 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4788 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4791 error ("printing unreadable object #<window-configuration 0x%x>",
4792 config->header.uid);
4793 write_c_string ("#<window-configuration ", printcharfun);
4794 sprintf (buf, "0x%x>", config->header.uid);
4795 write_c_string (buf, printcharfun);
4798 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4799 window_configuration,
4801 print_window_config,
4802 0, 0, 0, 0, sizeof_window_config,
4803 struct window_config);
4806 /* Returns a boolean indicating whether the two saved windows are
4809 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4811 #define WINDOW_SLOT(slot, compare) \
4812 if (!compare (win1->slot, win2->slot)) \
4814 #include "winslots.h"
4817 EQ (win1->window, win2->window) &&
4818 EQ (win1->buffer, win2->buffer) &&
4819 internal_equal (win1->start, win2->start, 0) &&
4820 internal_equal (win1->pointm, win2->pointm, 0) &&
4821 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4822 internal_equal (win1->mark, win2->mark, 0) &&
4823 win1->pixel_left == win2->pixel_left &&
4824 win1->pixel_top == win2->pixel_top &&
4825 win1->pixel_width == win2->pixel_width &&
4826 win1->pixel_height == win2->pixel_height &&
4827 win1->hscroll == win2->hscroll &&
4828 win1->modeline_hscroll == win2->modeline_hscroll &&
4829 win1->parent_index == win2->parent_index &&
4830 win1->prev_index == win2->prev_index &&
4831 win1->start_at_line_beg == win2->start_at_line_beg;
4834 /* Returns a boolean indicating whether the two given configurations
4837 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4839 struct window_config *fig1, *fig2;
4842 /* First check if they are truly the same. */
4843 if (EQ (conf1, conf2))
4846 fig1 = XWINDOW_CONFIGURATION (conf1);
4847 fig2 = XWINDOW_CONFIGURATION (conf2);
4849 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4850 EQ (fig1->current_window, fig2->current_window) &&
4851 EQ (fig1->current_buffer, fig2->current_buffer) &&
4852 EQ (fig1->root_window, fig2->root_window) &&
4853 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
4855 fig1->frame_width == fig2->frame_width &&
4856 fig1->frame_height == fig2->frame_height)) */
4859 for (i = 0; i < fig1->saved_windows_count; i++)
4861 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4862 SAVED_WINDOW_N (fig2, i)))
4869 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4870 Return t if OBJECT is a window-configuration object.
4874 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4878 mark_windows_in_use_closure (struct window *w, void *closure)
4880 int mark = *(int *)closure;
4881 w->config_mark = mark;
4886 mark_windows_in_use (struct frame *f, int mark)
4888 map_windows (f, mark_windows_in_use_closure, &mark);
4891 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4893 free_window_configuration (Lisp_Object window_config)
4896 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4898 /* Free all the markers. It's not completely necessary that
4899 we do this (window configs sitting in a free list aren't
4900 marked normally so the markers wouldn't be marked anyway)
4901 but it's more efficient. */
4902 for (i = 0; i < config->saved_windows_count; i++)
4904 struct saved_window *p = SAVED_WINDOW_N (config, i);
4906 if (!NILP (p->pointm))
4908 free_marker (XMARKER (p->pointm));
4911 if (!NILP (p->start))
4913 free_marker (XMARKER (p->start));
4916 if (!NILP (p->sb_point))
4918 free_marker (XMARKER (p->sb_point));
4921 if (!NILP (p->mark))
4923 free_marker (XMARKER (p->mark));
4928 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
4929 free_managed_lcrecord (Vwindow_configuration_free_list
4930 [config->saved_windows_count - 1],
4936 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
4937 Set the configuration of windows and buffers as specified by CONFIGURATION.
4938 CONFIGURATION must be a value previously returned
4939 by `current-window-configuration' (which see).
4944 struct window_config *config;
4945 struct saved_window *p;
4946 Lisp_Object new_current_buffer;
4950 struct gcpro gcpro1;
4951 Lisp_Object old_window_config;
4952 /* int previous_frame_height;
4953 int previous_frame_width;*/
4954 int previous_pixel_top;
4955 int previous_pixel_height;
4956 int previous_pixel_left;
4957 int previous_pixel_width;
4958 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
4959 int real_font_height;
4960 int converted_minibuf_height,target_minibuf_height;
4961 int specpdl_count = specpdl_depth ();
4963 GCPRO1 (configuration);
4965 CHECK_WINDOW_CONFIGURATION (configuration);
4966 config = XWINDOW_CONFIGURATION (configuration);
4968 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
4971 /* Do not signal an error here if the frame was deleted. There are
4972 reasonable cases where we could get here with a deleted frame and
4973 just want to do close to nothing instead. */
4975 if (FRAME_LIVE_P (f))
4977 /* restore the frame characteristics */
4979 new_current_buffer = config->current_buffer;
4980 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
4981 new_current_buffer = Qnil;
4984 * Assumed precondition: w->config_mark = 0 for all w
4985 * This procedure should ensure this is true by the time it exits
4986 * to ensure the precondition for future calls.
4988 * We use w->config_mark to know whether we're modifying a
4989 * window that is currently visible on the frame (#### we
4990 * should just be able to check whether the window is dead
4991 * or not, but this way is safer?). As we process each
4992 * window, we set its config_mark to 0. At the end, we
4993 * go through all the windows that used to be on the frame,
4994 * set each one's config_mark to 0 (to maintain the
4995 * assumed precondition) and delete each one that's no
4998 * #### Using a window-configuration to keep track of
4999 * the current windows is wasteful. All we need is the
5000 * list of windows, so we could just use a dynarr.
5002 old_window_config = Fcurrent_window_configuration (frame);
5004 /* If the new configuration is already equal to the old, then stop
5005 right here. This saves the work below and it also saves
5006 triggering a full redisplay of this window. This is a huge win
5007 when using the mouse since the mode motion code uses
5008 save-window-excursion extensively but will rarely cause the
5009 configuration to actually change. */
5010 if (window_config_equal (configuration, old_window_config))
5012 free_window_configuration (old_window_config);
5017 /* We can't quit or even check for quit because that may cause
5018 investigation of the frame state, which may crash if the frame is
5019 in an inconsistent state. */
5020 begin_dont_check_for_quit ();
5021 record_unwind_protect (free_window_configuration, old_window_config);
5023 mark_windows_in_use (f, 1);
5026 /* JV: This is bogus,
5027 First of all, the units are inconsistent. The frame sizes are measured
5028 in characters but the window sizes are stored in pixels. So if a
5029 font size change happened between saving and restoring, the
5030 frame "sizes" maybe equal but the windows still should be
5031 resized. This is tickled alot by the new "character size
5032 stays constant" policy in 21.0. It leads to very wierd
5033 glitches (and possibly craches when asserts are tickled).
5035 Just changing the units doens't help because changing the
5036 toolbar configuration can also change the pixel positions.
5037 Luckily there is a much simpler way of doing this, see below.
5039 previous_frame_width = FRAME_WIDTH (f);
5040 previous_frame_height = FRAME_HEIGHT (f);
5041 /* If the frame has been resized since this window configuration was
5042 made, we change the frame to the size specified in the
5043 configuration, restore the configuration, and then resize it
5044 back. We keep track of the prevailing height in these variables. */
5045 if (config->frame_height != FRAME_HEIGHT (f)
5046 || config->frame_width != FRAME_WIDTH (f))
5047 change_frame_size (f, config->frame_height, config->frame_width, 0);
5050 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5051 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5052 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5053 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5055 /* remember some properties of the minibuffer */
5057 default_face_height_and_width (frame, &real_font_height, 0);
5058 assert(real_font_height > 0);
5060 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5062 previous_minibuf_height
5063 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5064 previous_minibuf_top
5065 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5066 previous_minibuf_width
5067 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5071 previous_minibuf_height = 0;
5072 previous_minibuf_width = 0;
5074 converted_minibuf_height =
5075 (previous_minibuf_height % real_font_height) == 0 ?
5076 - (previous_minibuf_height / real_font_height ) : /* lines */
5077 previous_minibuf_height; /* pixels */
5079 /* Temporarily avoid any problems with windows that are smaller
5080 than they are supposed to be. */
5081 window_min_height = 1;
5082 window_min_width = 1;
5084 /* OK, now restore all the windows in the window config.
5085 This may involve "undeleting" windows, since the
5086 windows in the window config may be deleted.
5088 for (k = 0; k < config->saved_windows_count; k++)
5090 p = SAVED_WINDOW_N (config, k);
5091 w = XWINDOW (p->window);
5094 /* The window might be dead. In this case, its redisplay
5095 structures were freed, so we need to reallocate them. */
5096 if (!w->face_cachels)
5098 w->face_cachels = Dynarr_new (face_cachel);
5099 reset_face_cachels (w);
5101 if (!w->glyph_cachels)
5102 w->glyph_cachels = Dynarr_new (glyph_cachel);
5103 if (!w->line_start_cache)
5104 w->line_start_cache = Dynarr_new (line_start_cache);
5107 if (p->parent_index >= 0)
5108 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5112 if (p->prev_index >= 0)
5114 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5116 /* This is true for a minibuffer-only frame. */
5117 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5120 XWINDOW (w->prev)->next = p->window;
5125 if (!NILP (w->parent))
5127 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5129 XWINDOW (w->parent)->vchild = p->window;
5130 XWINDOW (w->parent)->hchild = Qnil;
5134 XWINDOW (w->parent)->hchild = p->window;
5135 XWINDOW (w->parent)->vchild = Qnil;
5139 if (!w->config_mark)
5141 /* #### This should be equivalent to the window previously
5142 having been dead. If we're brave, we'll put in an
5143 assertion to this effect. */
5144 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5146 else /* if (!EQ (w->buffer, p->buffer)) */
5148 /* With the new redisplay we let it know that a change has
5149 been made and it will take care of the rest. If we don't
5150 tell it something has possibly changed it could lead to
5151 incorrect display. */
5152 MARK_WINDOWS_CHANGED (w);
5155 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5156 WINDOW_TOP (w) = WINDOW_TOP (p);
5157 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5158 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5159 w->hscroll = p->hscroll;
5160 w->modeline_hscroll = p->modeline_hscroll;
5161 w->line_cache_last_updated = Qzero;
5162 SET_LAST_MODIFIED (w, 1);
5163 SET_LAST_FACECHANGE (w);
5166 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5167 #include "winslots.h"
5169 /* Reinstall the saved buffer and pointers into it. */
5170 if (NILP (p->buffer))
5171 w->buffer = p->buffer;
5174 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5175 /* If saved buffer is alive, install it. */
5177 w->buffer = p->buffer;
5178 w->start_at_line_beg = p->start_at_line_beg;
5179 set_marker_restricted (w->start[CURRENT_DISP],
5180 Fmarker_position (p->start),
5182 set_marker_restricted (w->pointm[CURRENT_DISP],
5183 Fmarker_position (p->pointm),
5185 set_marker_restricted (w->sb_point,
5186 Fmarker_position (p->sb_point),
5188 Fset_marker (XBUFFER (w->buffer)->mark,
5189 Fmarker_position (p->mark), w->buffer);
5191 /* As documented in Fcurrent_window_configuration, don't
5192 save the location of point in the buffer which was current
5193 when the window configuration was recorded. */
5194 if (!EQ (p->buffer, new_current_buffer) &&
5195 XBUFFER (p->buffer) == current_buffer)
5196 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5198 else if (NILP (w->buffer) ||
5199 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5200 /* Else if window's old buffer is dead too, get a live one. */
5202 /* #### The following line makes me nervous... */
5203 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5204 w->buffer = Fget_buffer_create (QSscratch);
5205 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5206 /* This will set the markers to beginning of visible
5208 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5209 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5211 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5212 w->start_at_line_beg = 1;
5215 /* Keeping window's old buffer; make sure the markers
5218 /* Set window markers at start of visible range. */
5219 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5220 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5222 if (XMARKER (w->sb_point)->buffer == 0)
5223 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5224 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5225 set_marker_restricted (w->pointm[CURRENT_DISP],
5227 (BUF_PT (XBUFFER (w->buffer))),
5229 w->start_at_line_beg = 1;
5234 FRAME_ROOT_WINDOW (f) = config->root_window;
5235 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5236 then calls do_switch_frame() below to select the frame that was
5237 recorded in the window config as being selected.
5239 Instead, we don't ever change the selected frame, and either
5240 call Fselect_window() below if the window config's frame is
5241 currently selected, or just set the selected window of the
5242 window config's frame. */
5245 /* Set the frame height to the value it had before this function. */
5246 if (previous_frame_height != FRAME_HEIGHT (f)
5247 || previous_frame_width != FRAME_WIDTH (f))
5248 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5250 /* We just reset the size and position of the minibuffer, to its old
5251 value, which needn't be valid. So we do some magic to see which value
5252 to actually take. Then we set it.
5255 We take the old value if is in the same units but differs from the
5258 #### Now we get more cases correct then ever before, but
5259 are we treating all? For instance what if the frames minibuf window
5260 is no longer the same one?
5262 target_minibuf_height = previous_minibuf_height;
5263 if (converted_minibuf_height &&
5264 (converted_minibuf_height * config->minibuf_height) > 0 &&
5265 (converted_minibuf_height != config->minibuf_height))
5267 target_minibuf_height = config->minibuf_height < 0 ?
5268 - (config->minibuf_height * real_font_height) :
5269 config->minibuf_height;
5270 target_minibuf_height =
5271 max(target_minibuf_height,real_font_height);
5273 if (previous_minibuf_height)
5275 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5276 = previous_minibuf_top -
5277 (target_minibuf_height - previous_minibuf_height);
5278 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5279 target_minibuf_height, 0);
5280 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5281 previous_minibuf_width, 0);
5284 /* This is a better way to deal with frame resizing, etc.
5285 What we _actually_ want is for the old (just restored)
5287 into the place of the new one. So we just do that. Simple! */
5288 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5289 /* Note that this function also updates the subwindow
5291 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5292 previous_pixel_height -
5293 (target_minibuf_height - previous_minibuf_height), 0);
5294 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5295 /* Note that this function also updates the subwindow
5297 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5299 /* If restoring in the current frame make the window current,
5300 otherwise just update the frame selected_window slot to be
5301 the restored current_window. */
5302 if (f == selected_frame ())
5304 /* When using `pop-window-configuration', often the minibuffer
5305 ends up as the selected window even though it's not active ...
5306 I really don't know the cause of this, but it should never
5307 happen. This kludge should fix it.
5309 #### Find out why this is really going wrong. */
5310 if (!minibuf_level &&
5311 MINI_WINDOW_P (XWINDOW (config->current_window)))
5312 Fselect_window (Fnext_window (config->current_window,
5316 Fselect_window (config->current_window, Qnil);
5317 if (!NILP (new_current_buffer))
5318 Fset_buffer (new_current_buffer);
5320 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5323 set_frame_selected_window (f, config->current_window);
5326 old_window_config = Qnil; /* Warning suppression */
5328 /* Restore the minimum heights recorded in the configuration. */
5329 window_min_height = config->min_height;
5330 window_min_width = config->min_width;
5333 /* see above comment */
5334 /* Fselect_window will have made f the selected frame, so we
5335 reselect the proper frame here. Fhandle_switch_frame will change the
5336 selected window too, but that doesn't make the call to
5337 Fselect_window above totally superfluous; it still sets f's
5339 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5340 do_switch_frame (config->selected_frame, Qnil, 0);
5343 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5345 if (FRAME_LIVE_P (f))
5347 /* Do this before calling recompute_all_cached_specifiers_in_window()
5348 so that things like redisplay_redraw_cursor() won't abort due
5349 to no window mirror present. */
5350 f->mirror_dirty = 1;
5352 config = XWINDOW_CONFIGURATION (old_window_config);
5353 for (k = 0; k < config->saved_windows_count; k++)
5355 p = SAVED_WINDOW_N (config, k);
5356 w = XWINDOW (p->window);
5357 /* Remember, we set w->config_mark on all currently visible
5358 windows, and reset it on all newly visible windows.
5359 Any windows still marked need to be deleted. */
5362 mark_window_as_deleted (w);
5367 /* We just potentially changed the window's buffer and
5368 potentially turned a dead window into a live one,
5369 so we need to recompute the cached specifier values. */
5370 recompute_all_cached_specifiers_in_window (w);
5375 /* Now restore things, when everything else if OK. */
5377 unbind_to (specpdl_count, Qnil);
5384 /* Mark all subwindows of a window as deleted. The argument
5385 W is actually the subwindow tree of the window in question. */
5388 delete_all_subwindows (struct window *w)
5390 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5391 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5392 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5394 mark_window_as_deleted (w);
5399 count_windows (struct window *window)
5402 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5403 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5404 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5408 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5411 for (j = 0; j < lim; j++)
5413 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5417 return 0; /* suppress compiler warning */
5421 save_window_save (Lisp_Object window, struct window_config *config, int i)
5425 for (; !NILP (window); window = w->next)
5427 struct saved_window *p = SAVED_WINDOW_N (config, i);
5429 w = XWINDOW (window);
5432 p->buffer = w->buffer;
5433 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5434 WINDOW_TOP (p) = WINDOW_TOP (w);
5435 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5436 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5437 p->hscroll = w->hscroll;
5438 p->modeline_hscroll = w->modeline_hscroll;
5440 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5441 #include "winslots.h"
5443 if (!NILP (w->buffer))
5445 /* Save w's value of point in the window configuration.
5446 If w is the selected window, then get the value of point
5447 from the buffer; pointm is garbage in the selected window. */
5448 if (EQ (window, Fselected_window (Qnil)))
5450 p->pointm = noseeum_make_marker ();
5451 Fset_marker (p->pointm,
5452 make_int (BUF_PT (XBUFFER (w->buffer))),
5456 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5458 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5459 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5460 p->start_at_line_beg = w->start_at_line_beg;
5462 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5470 p->start_at_line_beg = 0;
5473 if (NILP (w->parent))
5474 p->parent_index = -1;
5476 p->parent_index = saved_window_index (w->parent, config, i);
5480 p->prev_index = saved_window_index (w->prev, config, i);
5481 if (!NILP (w->vchild))
5482 i = save_window_save (w->vchild, config, i);
5483 if (!NILP (w->hchild))
5484 i = save_window_save (w->hchild, config, i);
5491 /* Added to doc string:
5493 This also records the currently selected frame, and FRAME's focus
5494 redirection (see `redirect-frame-focus').
5499 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5500 Return an object representing the current window configuration of FRAME.
5501 If FRAME is nil or omitted, use the selected frame.
5502 This describes the number of windows, their sizes and current buffers,
5503 and for each displayed buffer, where display starts, and the positions of
5504 point and mark. An exception is made for point in the current buffer:
5505 its value is -not- saved.
5510 struct frame *f = decode_frame (frame);
5511 struct window_config *config;
5512 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5514 int real_font_height;
5516 if (n_windows <= countof (Vwindow_configuration_free_list))
5517 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5518 (Vwindow_configuration_free_list
5521 /* More than ten windows; just allocate directly */
5522 config = (struct window_config *)
5523 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5524 &lrecord_window_configuration);
5525 XSETWINDOW_CONFIGURATION (result, config);
5527 config->frame_width = FRAME_WIDTH (f);
5528 config->frame_height = FRAME_HEIGHT (f); */
5529 config->current_window = FRAME_SELECTED_WINDOW (f);
5530 XSETBUFFER (config->current_buffer, current_buffer);
5531 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5532 config->root_window = FRAME_ROOT_WINDOW (f);
5533 config->min_height = window_min_height;
5534 config->min_width = window_min_width;
5535 config->saved_windows_count = n_windows;
5536 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5538 /* save the minibuffer height using the heuristics from
5539 change_frame_size_1 */
5541 XSETFRAME (frame, f); /* frame could have been nil ! */
5542 default_face_height_and_width (frame, &real_font_height, 0);
5543 assert(real_font_height > 0);
5545 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5546 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5549 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5550 - (minibuf_height / real_font_height ) : /* lines */
5551 minibuf_height; /* pixels */
5557 save_window_excursion_unwind (Lisp_Object window_config)
5559 Lisp_Object val = Fset_window_configuration (window_config);
5560 free_window_configuration (window_config);
5564 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5565 Execute body, preserving window sizes and contents.
5566 Restores which buffer appears in which window, where display starts,
5567 as well as the current buffer.
5568 Does not restore the value of point in current buffer.
5572 /* This function can GC */
5574 int speccount = specpdl_depth ();
5576 record_unwind_protect (save_window_excursion_unwind,
5577 Fcurrent_window_configuration (Qnil));
5578 val = Fprogn (args);
5579 return unbind_to (speccount, val);
5582 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5583 Return the horizontal pixel position of POS in window.
5584 Beginning of line is column 0. This is calculated using the redisplay
5585 display tables. If WINDOW is nil, the current window is assumed.
5586 If POS is nil, point is assumed. Note that POS must be visible for
5587 a non-nil result to be returned.
5591 struct window* w = decode_window (window);
5592 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5594 struct display_line *dl = 0;
5595 struct display_block *db = 0;
5596 struct rune* rb = 0;
5597 int y = w->last_point_y[CURRENT_DISP];
5598 int x = w->last_point_x[CURRENT_DISP];
5600 if (MINI_WINDOW_P (w))
5603 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5609 pos = Fwindow_point (window);
5614 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5619 for (i = first_line; i < Dynarr_length (dla); i++)
5621 dl = Dynarr_atp (dla, i);
5622 /* find the vertical location first */
5623 if (point >= dl->bufpos && point <= dl->end_bufpos)
5625 db = get_display_block_from_line (dl, TEXT);
5626 for (i = 0; i < Dynarr_length (db->runes); i++)
5628 rb = Dynarr_atp (db->runes, i);
5629 if (point <= rb->bufpos)
5641 /* optimised case */
5642 dl = Dynarr_atp (dla, y);
5643 db = get_display_block_from_line (dl, TEXT);
5645 if (x >= Dynarr_length (db->runes))
5648 rb = Dynarr_atp (db->runes, x);
5651 return make_int (rb->xpos - WINDOW_LEFT (w));
5656 /* This is short and simple in elisp, but... it was written to debug
5657 problems purely on the C side. That is where we need to call it so
5660 debug_print_window (Lisp_Object window, int level)
5663 Lisp_Object child = Fwindow_first_vchild (window);
5666 child = Fwindow_first_hchild (window);
5668 for (i = level; i > 0; i--)
5669 putc ('\t', stderr);
5671 fputs ("#<window", stderr);
5673 Lisp_Object buffer = XWINDOW (window)->buffer;
5674 if (!NILP (buffer) && BUFFERP (buffer))
5675 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5677 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5679 while (!NILP (child))
5681 debug_print_window (child, level + 1);
5682 child = Fwindow_next_child (child);
5686 void debug_print_windows (struct frame *f);
5688 debug_print_windows (struct frame *f)
5690 debug_print_window (f->root_window, 0);
5691 putc ('\n', stderr);
5693 #endif /* DEBUG_XEMACS */
5696 /************************************************************************/
5697 /* initialization */
5698 /************************************************************************/
5701 syms_of_window (void)
5703 defsymbol (&Qwindowp, "windowp");
5704 defsymbol (&Qwindow_live_p, "window-live-p");
5705 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5706 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5707 defsymbol (&Qdisplay_buffer, "display-buffer");
5709 #ifdef MEMORY_USAGE_STATS
5710 defsymbol (&Qface_cache, "face-cache");
5711 defsymbol (&Qglyph_cache, "glyph-cache");
5712 defsymbol (&Qline_start_cache, "line-start-cache");
5713 #ifdef HAVE_SCROLLBARS
5714 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5716 defsymbol (&Qother_redisplay, "other-redisplay");
5717 /* Qother in general.c */
5720 DEFSUBR (Fselected_window);
5721 DEFSUBR (Flast_nonminibuf_window);
5722 DEFSUBR (Fminibuffer_window);
5723 DEFSUBR (Fwindow_minibuffer_p);
5725 DEFSUBR (Fwindow_live_p);
5726 DEFSUBR (Fwindow_first_hchild);
5727 DEFSUBR (Fwindow_first_vchild);
5728 DEFSUBR (Fwindow_next_child);
5729 DEFSUBR (Fwindow_previous_child);
5730 DEFSUBR (Fwindow_parent);
5731 DEFSUBR (Fwindow_lowest_p);
5732 DEFSUBR (Fwindow_truncated_p);
5733 DEFSUBR (Fwindow_highest_p);
5734 DEFSUBR (Fwindow_leftmost_p);
5735 DEFSUBR (Fwindow_rightmost_p);
5736 DEFSUBR (Fpos_visible_in_window_p);
5737 DEFSUBR (Fwindow_buffer);
5738 DEFSUBR (Fwindow_frame);
5739 DEFSUBR (Fwindow_height);
5740 DEFSUBR (Fwindow_displayed_height);
5741 DEFSUBR (Fwindow_width);
5742 DEFSUBR (Fwindow_pixel_height);
5743 DEFSUBR (Fwindow_pixel_width);
5744 DEFSUBR (Fwindow_text_area_pixel_height);
5745 DEFSUBR (Fwindow_displayed_text_pixel_height);
5746 DEFSUBR (Fwindow_text_area_pixel_width);
5747 DEFSUBR (Fwindow_hscroll);
5748 #ifdef MODELINE_IS_SCROLLABLE
5749 DEFSUBR (Fmodeline_hscroll);
5750 DEFSUBR (Fset_modeline_hscroll);
5751 #endif /* MODELINE_IS_SCROLLABLE */
5752 #if 0 /* bogus FSF crock */
5753 DEFSUBR (Fwindow_redisplay_end_trigger);
5754 DEFSUBR (Fset_window_redisplay_end_trigger);
5756 DEFSUBR (Fset_window_hscroll);
5757 DEFSUBR (Fwindow_pixel_edges);
5758 DEFSUBR (Fwindow_text_area_pixel_edges);
5759 DEFSUBR (Fwindow_point);
5760 DEFSUBR (Fwindow_start);
5761 DEFSUBR (Fwindow_end);
5762 DEFSUBR (Fset_window_point);
5763 DEFSUBR (Fset_window_start);
5764 DEFSUBR (Fwindow_dedicated_p);
5765 DEFSUBR (Fset_window_dedicated_p);
5766 DEFSUBR (Fnext_window);
5767 DEFSUBR (Fprevious_window);
5768 DEFSUBR (Fnext_vertical_window);
5769 DEFSUBR (Fother_window);
5770 DEFSUBR (Fget_lru_window);
5771 DEFSUBR (Fget_largest_window);
5772 DEFSUBR (Fget_buffer_window);
5773 DEFSUBR (Fwindow_left_margin_pixel_width);
5774 DEFSUBR (Fwindow_right_margin_pixel_width);
5775 DEFSUBR (Fdelete_other_windows);
5776 DEFSUBR (Fdelete_windows_on);
5777 DEFSUBR (Freplace_buffer_in_windows);
5778 DEFSUBR (Fdelete_window);
5779 DEFSUBR (Fset_window_buffer);
5780 DEFSUBR (Fselect_window);
5781 DEFSUBR (Fsplit_window);
5782 DEFSUBR (Fenlarge_window);
5783 DEFSUBR (Fenlarge_window_pixels);
5784 DEFSUBR (Fshrink_window);
5785 DEFSUBR (Fshrink_window_pixels);
5786 DEFSUBR (Fscroll_up);
5787 DEFSUBR (Fscroll_down);
5788 DEFSUBR (Fscroll_left);
5789 DEFSUBR (Fscroll_right);
5790 DEFSUBR (Fother_window_for_scrolling);
5791 DEFSUBR (Fscroll_other_window);
5792 DEFSUBR (Fcenter_to_window_line);
5793 DEFSUBR (Fmove_to_window_line);
5794 #ifdef MEMORY_USAGE_STATS
5795 DEFSUBR (Fwindow_memory_usage);
5797 DEFSUBR (Fwindow_configuration_p);
5798 DEFSUBR (Fset_window_configuration);
5799 DEFSUBR (Fcurrent_window_configuration);
5800 DEFSUBR (Fsave_window_excursion);
5801 DEFSUBR (Fcurrent_pixel_column);
5805 reinit_vars_of_window (void)
5808 /* Make sure all windows get marked */
5809 minibuf_window = Qnil;
5810 staticpro_nodump (&minibuf_window);
5812 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5814 Vwindow_configuration_free_list[i] =
5815 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5816 &lrecord_window_configuration);
5817 staticpro_nodump (&Vwindow_configuration_free_list[i]);
5822 vars_of_window (void)
5824 reinit_vars_of_window ();
5826 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5827 *Non-nil means to scroll if point lands on a line which is clipped.
5829 scroll_on_clipped_lines = 1;
5831 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5832 See `temp-buffer-show-function'.
5834 Vtemp_buffer_show_hook = Qnil;
5836 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5837 Non-nil means call as function to display a help buffer.
5838 The function is called with one argument, the buffer to be displayed.
5839 Used by `with-output-to-temp-buffer'.
5840 If this function is used, then it must do the entire job of showing
5841 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5843 Vtemp_buffer_show_function = Qnil;
5845 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5846 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5848 Vminibuffer_scroll_window = Qnil;
5850 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5851 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5853 Vother_window_scroll_buffer = Qnil;
5855 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
5856 *Number of pixels to scroll by per requested line.
5857 If nil then normal line scrolling occurs regardless of line height.
5858 If t then scrolling is done in increments equal to the height of the default face.
5860 Vwindow_pixel_scroll_increment = Qt;
5862 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5863 *Number of lines of continuity when scrolling by screenfuls.
5865 next_screen_context_lines = 2;
5867 DEFVAR_INT ("window-min-height", &window_min_height /*
5868 *Delete any window less than this tall (including its modeline).
5870 window_min_height = 4;
5872 DEFVAR_INT ("window-min-width", &window_min_width /*
5873 *Delete any window less than this wide.
5875 window_min_width = 10;
5879 specifier_vars_of_window (void)
5881 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5882 *How thick to draw 3D shadows around modelines.
5883 If this is set to 0, modelines will be the traditional 2D. Sizes above
5884 10 will be accepted but the maximum thickness that will be drawn is 10.
5885 This is a specifier; use `set-specifier' to change it.
5887 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5888 /* The initial value for modeline-shadow-thickness is 2, but if the
5889 user removes all specifications we provide a fallback value of 0,
5890 which is probably what was expected. */
5891 set_specifier_fallback (Vmodeline_shadow_thickness,
5892 list1 (Fcons (Qnil, Qzero)));
5893 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5895 set_specifier_caching (Vmodeline_shadow_thickness,
5896 slot_offset (struct window,
5897 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 slot_offset (struct window,
5911 /* #### It's strange that we need a special
5912 flag to indicate that the shadow-thickness
5913 has changed, but not one to indicate that
5914 the modeline has been turned off or on. */
5915 some_window_value_changed,
5918 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5919 &Vvertical_divider_always_visible_p /*
5920 *Should XEmacs always display vertical dividers between windows.
5922 When this is non-nil, vertical dividers are always shown, and are
5923 draggable. When it is nil, vertical dividers are shown only when
5924 there are no scrollbars in between windows, and are not draggable.
5926 This is a specifier; use `set-specifier' to change it.
5928 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
5929 set_specifier_fallback (Vvertical_divider_always_visible_p,
5930 list1 (Fcons (Qnil, Qt)));
5931 set_specifier_caching (Vvertical_divider_always_visible_p,
5932 slot_offset (struct window,
5933 vertical_divider_always_visible_p),
5934 vertical_divider_changed_in_window,
5937 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
5938 *How thick to draw 3D shadows around vertical dividers.
5939 This is a specifier; use `set-specifier' to change it.
5941 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
5942 set_specifier_fallback (Vvertical_divider_shadow_thickness,
5943 list1 (Fcons (Qnil, Qzero)));
5944 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
5946 set_specifier_caching (Vvertical_divider_shadow_thickness,
5947 slot_offset (struct window,
5948 vertical_divider_shadow_thickness),
5949 vertical_divider_changed_in_window,
5951 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
5952 *The width of the vertical dividers, not including shadows.
5954 For TTY windows, divider line is always one character wide. When
5955 instance of this specifier is zero in a TTY window, no divider is
5956 drawn at all between windows. When non-zero, a one character wide
5957 divider is displayed.
5959 This is a specifier; use `set-specifier' to change it.
5962 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
5964 Lisp_Object fb = Qnil;
5966 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
5968 #ifdef HAVE_X_WINDOWS
5969 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
5971 #ifdef HAVE_MS_WINDOWS
5972 /* #### This should be made magic and made to obey system settings */
5973 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
5975 set_specifier_fallback (Vvertical_divider_line_width, fb);
5977 set_specifier_caching (Vvertical_divider_line_width,
5978 slot_offset (struct window,
5979 vertical_divider_line_width),
5980 vertical_divider_changed_in_window,
5983 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
5984 *How much space to leave around the vertical dividers.
5986 In TTY windows, spacing is always zero, and the value of this
5987 specifier is ignored.
5989 This is a specifier; use `set-specifier' to change it.
5991 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
5993 Lisp_Object fb = Qnil;
5995 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
5997 #ifdef HAVE_X_WINDOWS
5998 /* #### 3D dividers look great on MS Windows with spacing = 0.
5999 Should not the same value be the fallback under X? - kkm */
6000 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6002 #ifdef HAVE_MS_WINDOWS
6003 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6005 set_specifier_fallback (Vvertical_divider_spacing, fb);
6007 set_specifier_caching (Vvertical_divider_spacing,
6008 slot_offset (struct window,
6009 vertical_divider_spacing),
6010 vertical_divider_changed_in_window,