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 if text in the window is truncated.
740 struct window *w = decode_window (window);
742 return window_truncation_on (w) ? Qt : Qnil;
747 have_undivided_common_edge (struct window *w_right, void *closure)
749 struct window *w_left = (struct window *) closure;
750 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right)
751 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right)
752 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left)
753 #ifdef HAVE_SCROLLBARS
754 && (NILP (w_right->scrollbar_on_left_p)
755 || NILP (w_right->vertical_scrollbar_visible_p)
756 || ZEROP (w_right->scrollbar_width))
762 window_needs_vertical_divider_1 (struct window *w)
764 /* Never if we're on the right */
765 if (window_is_rightmost (w))
768 /* Always if draggable */
769 if (!NILP (w->vertical_divider_always_visible_p))
772 #ifdef HAVE_SCROLLBARS
773 /* Our right scrollbar is enough to separate us at the right */
774 if (NILP (w->scrollbar_on_left_p)
775 && !NILP (w->vertical_scrollbar_visible_p)
776 && !ZEROP (w->scrollbar_width))
780 /* Ok. to determine whether we need a divider on the left, we must
781 check that our right neighbor windows have scrollbars on their
782 left sides. We must check all such windows which have common
783 left edge with our window's right edge. */
784 return map_windows (XFRAME (WINDOW_FRAME (w)),
785 have_undivided_common_edge, (void*)w);
789 window_needs_vertical_divider (struct window *w)
791 if (!w->need_vertical_divider_valid_p)
793 w->need_vertical_divider_p =
794 window_needs_vertical_divider_1 (w);
795 w->need_vertical_divider_valid_p = 1;
797 return w->need_vertical_divider_p;
800 /* Called from invalidate_vertical_divider_cache_in_frame */
802 invalidate_vertical_divider_cache_in_window (struct window *w,
805 w->need_vertical_divider_valid_p = 0;
809 /* Calculate width of vertical divider, including its shadows
810 and spacing. The returned value is effectively the distance
811 between adjacent window edges. This function does not check
812 whether a window needs a vertical divider, so the returned
813 value is a "theoretical" one */
815 window_divider_width (struct window *w)
817 /* the shadow thickness can be negative. This means that the divider
818 will have a depressed look */
820 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w))))
822 XINT (w->vertical_divider_line_width)
823 + 2 * XINT (w->vertical_divider_spacing)
824 + 2 * abs (XINT (w->vertical_divider_shadow_thickness));
826 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1;
830 window_scrollbar_width (struct window *w)
832 #ifdef HAVE_SCROLLBARS
833 if (!WINDOW_WIN_P (w)
836 || NILP (w->vertical_scrollbar_visible_p))
837 /* #### when does NILP (w->buffer) happen? */
840 return XINT (w->scrollbar_width);
843 #endif /* HAVE_SCROLLBARS */
846 /* Horizontal scrollbars are only active on windows with truncation
849 window_scrollbar_height (struct window *w)
851 #ifdef HAVE_SCROLLBARS
852 if (!WINDOW_WIN_P (w)
855 || NILP (w->horizontal_scrollbar_visible_p)
856 || !window_truncation_on (w))
859 return XINT (w->scrollbar_height);
862 #endif /* HAVE_SCROLLBARS */
866 window_modeline_height (struct window *w)
868 struct frame *f = XFRAME (w->frame);
871 if (MINI_WINDOW_P (w) || NILP (w->buffer))
875 else if (!WINDOW_HAS_MODELINE_P (w))
877 if (window_scrollbar_height (w))
881 modeline_height = FRAMEMETH (f, divider_height, ());
883 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
884 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
893 display_line_dynarr *dla;
895 /* We don't force a regeneration of the modeline here.
896 Instead it is now a precondition that any function calling
897 this should make sure that one of these structures is
898 up-to-date. In practice this only affects two internal
899 redisplay functions, regenerate_window and
900 regenerate_window_point_center. */
901 /* We check DESIRED_DISP because if it is valid it is more
902 up-to-date than CURRENT_DISP. For calls to this outside
903 of redisplay it doesn't matter which structure we check
904 since there is a redisplay condition that these
905 structures be identical outside of redisplay. */
906 dla = window_display_lines (w, DESIRED_DISP);
907 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
908 modeline_height = (Dynarr_atp (dla, 0)->ascent +
909 Dynarr_atp (dla, 0)->descent);
912 dla = window_display_lines (w, CURRENT_DISP);
913 if (dla && Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
914 modeline_height = (Dynarr_atp (dla, 0)->ascent +
915 Dynarr_atp (dla, 0)->descent);
917 /* This should be an abort except I'm not yet 100%
918 confident that it won't ever get hit (though I
919 haven't been able to trigger it). It is extremely
920 unlikely to cause any noticeable problem and even if
921 it does it will be a minor display glitch. */
922 /* #### Bullshit alert. It does get hit and it causes
923 noticeable glitches. real_current_modeline_height
924 is a kludge to fix this for 19.14. */
925 modeline_height = real_current_modeline_height (w);
928 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
929 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
933 return modeline_height;
936 /*****************************************************************************
937 margin_width_internal
939 For a given window, return the width in pixels of the specified margin.
940 ****************************************************************************/
942 margin_width_internal (struct window *w, int left_margin)
945 int window_cwidth = window_char_width (w, 1);
950 /* We might be getting called on a non-leaf. */
951 if (NILP (w->buffer))
954 /* The minibuffer never has margins. */
955 if (MINI_WINDOW_P (w))
958 XSETWINDOW (window, w);
959 b = XBUFFER (w->buffer);
960 margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
961 XINT (w->right_margin_width));
963 default_face_height_and_width (window, 0, &font_width);
965 /* The left margin takes precedence over the right margin so we
966 subtract its width from the space available for the right
969 window_cwidth -= XINT (w->left_margin_width);
971 /* The margin cannot be wider than the window is. We allow the
972 value to be bigger since it is possible for the user to enlarge
973 the window such that the left margin value would no longer be too
974 big, but we won't return a value that is larger. */
975 if (margin_cwidth > window_cwidth)
976 margin_cwidth = window_cwidth;
978 /* At the user level the margin is always specified in characters.
979 Internally however it is manipulated in terms of pixels. */
980 return margin_cwidth * font_width;
984 window_left_margin_width (struct window *w)
986 return margin_width_internal (w, 1);
990 window_right_margin_width (struct window *w)
992 return margin_width_internal (w, 0);
995 /*****************************************************************************
998 The gutters of a window are those areas in the boundary defined by
999 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
1000 do not contain text. Items which may be in the gutters include
1001 scrollbars, toolbars and modelines. The margin areas are not
1002 included. This is an exception made because redisplay special cases
1003 the handling of those areas in many places in such a way that
1004 including them in the gutter area would make life difficult.
1006 The size functions refer to height for the bottom and top gutters and
1007 width for the left and right gutters. The starting position
1008 functions refer to the Y coord for bottom and top gutters and the X
1009 coord for left and right gutters. All starting positions are
1010 relative to the frame, not the window.
1011 ****************************************************************************/
1014 window_top_gutter_height (struct window *w)
1016 int gutter = WINDOW_REAL_TOP_GUTTER_BOUNDS (w);
1018 if (!NILP (w->hchild) || !NILP (w->vchild))
1021 #ifdef HAVE_SCROLLBARS
1022 if (!NILP (w->scrollbar_on_top_p))
1023 return window_scrollbar_height (w) + gutter;
1030 window_bottom_gutter_height (struct window *w)
1032 int gutter = WINDOW_REAL_BOTTOM_GUTTER_BOUNDS (w);
1034 if (!NILP (w->hchild) || !NILP (w->vchild))
1037 gutter += window_modeline_height (w);
1039 #ifdef HAVE_SCROLLBARS
1040 if (NILP (w->scrollbar_on_top_p))
1041 return window_scrollbar_height (w) + gutter;
1048 window_left_gutter_width (struct window *w, int modeline)
1050 int gutter = WINDOW_REAL_LEFT_GUTTER_BOUNDS (w);
1052 if (!NILP (w->hchild) || !NILP (w->vchild))
1055 #ifdef HAVE_SCROLLBARS
1056 if (!modeline && !NILP (w->scrollbar_on_left_p))
1057 gutter += window_scrollbar_width (w);
1064 window_right_gutter_width (struct window *w, int modeline)
1066 int gutter = WINDOW_REAL_RIGHT_GUTTER_BOUNDS (w);
1068 if (!NILP (w->hchild) || !NILP (w->vchild))
1071 #ifdef HAVE_SCROLLBARS
1072 if (!modeline && NILP (w->scrollbar_on_left_p))
1073 gutter += window_scrollbar_width (w);
1076 if (window_needs_vertical_divider (w))
1077 gutter += window_divider_width (w);
1083 DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
1084 Return t if OBJ is a window.
1088 return WINDOWP (obj) ? Qt : Qnil;
1091 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /*
1092 Return t if OBJ is a window which is currently visible.
1096 return WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil;
1099 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /*
1100 Return the window that the cursor now appears in and commands apply to.
1101 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1102 the selected window used by that frame. If CON-DEV-OR-FRAME is a device,
1103 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1104 is a console, the selected frame on that console's selected device will
1105 be used. Otherwise, the selected frame is used.
1109 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1110 return Qnil; /* happens at startup */
1113 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1114 return FRAME_SELECTED_WINDOW (f);
1118 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /*
1119 Return the last selected window that is not a minibuffer window.
1120 If the optional argument CON-DEV-OR-FRAME is specified and is a frame,
1121 return the last non-minibuffer window used by that frame. If
1122 CON-DEV-OR-FRAME is a device, then the selected frame on that device
1123 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on
1124 that console's selected device will be used. Otherwise, the selected
1129 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil)))
1130 return Qnil; /* happens at startup */
1133 struct frame *f = decode_frame_or_selected (con_dev_or_frame);
1134 return FRAME_LAST_NONMINIBUF_WINDOW (f);
1138 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /*
1139 Return the window used now for minibuffers.
1140 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return
1141 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device,
1142 then the selected frame on that device will be used. If CON-DEV-OR-FRAME
1143 is a console, the selected frame on that console's selected device will
1144 be used. Otherwise, the selected frame is used.
1148 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
1151 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
1152 Return non-nil if WINDOW is a minibuffer window.
1156 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil;
1159 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /*
1160 Return the first horizontal child of WINDOW, or nil.
1164 return decode_window (window)->hchild;
1167 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /*
1168 Return the first vertical child of WINDOW, or nil.
1172 return decode_window (window)->vchild;
1175 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /*
1176 Return the next window on the same level as WINDOW, or nil.
1180 return decode_window (window)->next;
1183 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /*
1184 Return the previous window on the same level as WINDOW, or nil.
1188 return decode_window (window)->prev;
1191 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /*
1192 Return the parent of WINDOW, or nil.
1196 return decode_window (window)->parent;
1199 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /*
1200 Return non-nil if WINDOW is along the bottom of its frame.
1204 return window_is_lowest (decode_window (window)) ? Qt : Qnil;
1207 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /*
1208 Return non-nil if WINDOW is along the top of its frame.
1212 return window_is_highest (decode_window (window)) ? Qt : Qnil;
1215 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /*
1216 Return non-nil if WINDOW is along the left edge of its frame.
1220 return window_is_leftmost (decode_window (window)) ? Qt : Qnil;
1223 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /*
1224 Return non-nil if WINDOW is along the right edge of its frame.
1228 return window_is_rightmost (decode_window (window)) ? Qt : Qnil;
1231 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 2, 0, /*
1232 Return t if position POS is currently on the frame in WINDOW.
1233 Returns nil if that position is scrolled vertically out of view.
1234 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.
1238 struct window *w = decode_window (window);
1239 Bufpos top = marker_position (w->start[CURRENT_DISP]);
1241 struct buffer *buf = XBUFFER (w->buffer);
1244 posint = BUF_PT (buf);
1247 CHECK_INT_COERCE_MARKER (pos);
1248 posint = XINT (pos);
1251 if (posint < top || posint > BUF_ZV (buf))
1254 /* w->start can be out of range. If it is, do something reasonable. */
1255 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
1258 return point_would_be_visible (w, top, posint) ? Qt : Qnil;
1263 decode_window (Lisp_Object window)
1266 return XWINDOW (Fselected_window (Qnil));
1268 CHECK_LIVE_WINDOW (window);
1269 return XWINDOW (window);
1272 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /*
1273 Return the buffer that WINDOW is displaying.
1277 return decode_window (window)->buffer;
1280 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /*
1281 Return the frame that window WINDOW is on.
1285 return decode_window (window)->frame;
1288 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /*
1289 Return the number of default lines in WINDOW.
1290 This actually works by dividing the window's pixel height (including
1291 the modeline and horizontal scrollbar, if any) by the height of the
1292 default font; therefore, the number of displayed lines will probably
1294 Use `window-height' to get consistent results in geometry calculations.
1295 Use `window-displayed-height' to get the actual number of lines
1296 currently displayed in a window.
1300 return make_int (window_char_height (decode_window (window), 1));
1303 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /*
1304 Return the number of lines currently displayed in WINDOW.
1305 This counts the actual number of lines displayed in WINDOW
1306 \(as opposed to `window-height'). The modeline and horizontal
1307 scrollbar do not count as lines. If there is some blank space
1308 between the end of the buffer and the end of the window, this
1309 function pretends that there are lines of text in the default
1314 return make_int (window_displayed_height (decode_window (window)));
1317 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /*
1318 Return the height of WINDOW in pixels. Defaults to current window.
1319 This includes the window's modeline and horizontal scrollbar (if any).
1323 return make_int (decode_window (window)->pixel_height);
1326 DEFUN ("window-text-area-pixel-height",
1327 Fwindow_text_area_pixel_height, 0, 1, 0, /*
1328 Return the height in pixels of the text-displaying portion of WINDOW.
1329 Unlike `window-pixel-height', the space occupied by the modeline and
1330 horizontal scrollbar, if any, is not counted.
1334 struct window *w = decode_window (window);
1336 return make_int (WINDOW_TEXT_HEIGHT (w));
1339 DEFUN ("window-displayed-text-pixel-height",
1340 Fwindow_displayed_text_pixel_height, 0, 2, 0, /*
1341 Return the height in pixels of the text displayed in WINDOW.
1342 Unlike `window-text-area-pixel-height', any blank space below the
1343 end of the buffer is not included. If optional argument NOCLIPPED
1344 is non-nil, do not include space occupied by clipped lines.
1346 (window, noclipped))
1349 Bufpos start, eobuf;
1351 int hlimit, height, prev_height = -1;
1355 line_start_cache_dynarr *cache;
1358 window = Fselected_window (Qnil);
1360 CHECK_LIVE_WINDOW (window);
1361 w = XWINDOW (window);
1363 start = marker_position (w->start[CURRENT_DISP]);
1364 hlimit = WINDOW_TEXT_HEIGHT (w);
1365 eobuf = BUF_ZV (XBUFFER (w->buffer));
1367 default_face_height_and_width (window, &defheight, NULL);
1369 /* guess lines needed in line start cache + a few extra */
1370 needed = (hlimit + defheight-1) / defheight + 3;
1373 elt = point_in_line_start_cache (w, start, needed);
1374 assert (elt >= 0); /* in the cache */
1376 cache = w->line_start_cache;
1377 nelt = Dynarr_length (cache);
1380 for (i = elt; i < nelt; i++) {
1381 line = Dynarr_atp (cache, i)->height;
1383 if (height + line > hlimit)
1384 return make_int (!NILP (noclipped) ? height : hlimit);
1388 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf)
1389 return make_int (height);
1392 /* get here => need more cache lines. try again. */
1393 assert(height > prev_height); /* progress? */
1394 prev_height = height;
1396 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3;
1399 RETURN_NOT_REACHED(make_int (0)) /* shut up compiler */
1402 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
1403 Return the number of display columns in WINDOW.
1404 This is the width that is usable columns available for text in WINDOW.
1408 return make_int (window_char_width (decode_window (window), 0));
1411 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
1412 Return the width of WINDOW in pixels. Defaults to current window.
1416 return make_int (decode_window (window)->pixel_width);
1419 DEFUN ("window-text-area-pixel-width",
1420 Fwindow_text_area_pixel_width, 0, 1, 0, /*
1421 Return the width in pixels of the text-displaying portion of WINDOW.
1422 Unlike `window-pixel-width', the space occupied by the vertical
1423 scrollbar or divider, if any, is not counted.
1427 struct window *w = decode_window (window);
1429 return make_int (WINDOW_TEXT_WIDTH (w));
1432 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /*
1433 Return the number of columns by which WINDOW is scrolled from left margin.
1437 return make_int (decode_window (window)->hscroll);
1440 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
1441 Return the horizontal scrolling ammount of WINDOW's modeline.
1442 If the window has no modeline, return nil.
1446 struct window *w = decode_window (window);
1448 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
1452 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
1453 Set the horizontal scrolling ammount of WINDOW's modeline to NCOL.
1454 If NCOL is negative, it will silently be forced to 0.
1455 If the window has no modeline, return nil. Otherwise, return the actual
1460 struct window *w = decode_window (window);
1462 if (WINDOW_HAS_MODELINE_P (w))
1467 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
1468 if (ncols != w->modeline_hscroll)
1470 MARK_MODELINE_CHANGED;
1471 w->modeline_hscroll = ncols;
1473 return make_int ((int) ncols);
1479 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
1480 Set number of columns WINDOW is scrolled from left margin to NCOL.
1481 NCOL should be zero or positive.
1489 ncols = XINT (ncol);
1490 if (ncols < 0) ncols = 0;
1491 w = decode_window (window);
1492 if (w->hscroll != ncols)
1493 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */
1498 #if 0 /* bogus FSF crock */
1500 xxDEFUN ("window-redisplay-end-trigger",
1501 Fwindow_redisplay_end_trigger, 0, 1, 0, /*
1502 Return WINDOW's redisplay end trigger value.
1503 See `set-window-redisplay-end-trigger' for more information.
1507 return decode_window (window)->redisplay_end_trigger;
1510 xxDEFUN ("set-window-redisplay-end-trigger",
1511 Fset_window_redisplay_end_trigger, 2, 2, 0, /*
1512 Set WINDOW's redisplay end trigger value to VALUE.
1513 VALUE should be a buffer position (typically a marker) or nil.
1514 If it is a buffer position, then if redisplay in WINDOW reaches a position
1515 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
1516 with two arguments: WINDOW, and the end trigger value.
1517 Afterwards the end-trigger value is reset to nil.
1521 return (decode_window (window)->redisplay_end_trigger = value);
1526 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
1527 Return a list of the pixel edge coordinates of WINDOW.
1528 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
1529 The frame toolbars and menubars are considered to be outside of this area.
1533 struct window *w = decode_window (window);
1534 struct frame *f = XFRAME (w->frame);
1536 int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
1537 int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
1539 return list4 (make_int (left),
1541 make_int (left + w->pixel_width),
1542 make_int (top + w->pixel_height));
1545 DEFUN ("window-text-area-pixel-edges",
1546 Fwindow_text_area_pixel_edges, 0, 1, 0, /*
1547 Return a list of the pixel edge coordinates of the text area of WINDOW.
1548 Returns the list \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at the
1549 top left corner of the window.
1553 struct window *w = decode_window (window);
1555 int left = window_left_gutter_width (w, /* modeline = */ 0);
1556 int top = window_top_gutter_height (w);
1557 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0);
1558 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w);
1560 return list4 (make_int (left),
1566 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
1567 Return current value of point in WINDOW.
1568 For a nonselected window, this is the value point would have
1569 if that window were selected.
1571 Note that, when WINDOW is the selected window and its buffer
1572 is also currently selected, the value returned is the same as (point).
1573 It would be more strictly correct to return the `top-level' value
1574 of point, outside of any save-excursion forms.
1575 But that is hard to define.
1579 struct window *w = decode_window (window);
1581 /* The special check for current buffer is necessary for this
1582 function to work as defined when called within an excursion. */
1583 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
1584 && current_buffer == XBUFFER (w->buffer))
1585 return Fpoint (Qnil);
1586 return Fmarker_position (w->pointm[CURRENT_DISP]);
1589 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /*
1590 Return position at which display currently starts in WINDOW.
1591 This is updated by redisplay or by calling `set-window-start'.
1595 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
1598 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /*
1599 Return position at which display currently ends in WINDOW.
1600 This is updated by redisplay, when it runs to completion.
1601 Simply changing the buffer text or setting `window-start'
1602 does not update this value.
1603 If GUARANTEE is non-nil, then the return value is guaranteed to be
1604 the value of window-end at the end of the next full redisplay assuming
1605 nothing else changes in the meantime. This function is potentially much
1606 slower with this flag set.
1608 (window, guarantee))
1610 struct window *w = decode_window (window);
1612 if (NILP (guarantee))
1617 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
1621 Bufpos startp = marker_position (w->start[CURRENT_DISP]);
1622 return make_int (end_of_last_line (w, startp));
1626 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
1627 Return pixel height of visible part of last window line if it is clipped.
1628 If the last line is not clipped, return nil.
1632 struct window *w = decode_window (window);
1633 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1634 int num_lines = Dynarr_length (dla);
1635 struct display_line *dl;
1637 /* No lines - no clipped lines */
1638 if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
1641 dl = Dynarr_atp (dla, num_lines - 1);
1645 return make_int (dl->ascent + dl->descent - dl->clip);
1648 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
1649 Make point value in WINDOW be at position POS in WINDOW's buffer.
1653 struct window *w = decode_window (window);
1655 CHECK_INT_COERCE_MARKER (pos);
1656 if (w == XWINDOW (Fselected_window (Qnil)))
1657 Fgoto_char (pos, Qnil);
1659 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
1665 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /*
1666 Make display in WINDOW start at position POS in WINDOW's buffer.
1667 Optional third arg NOFORCE non-nil inhibits next redisplay
1668 from overriding motion of point in order to display at this exact start.
1670 (window, pos, noforce))
1672 struct window *w = decode_window (window);
1674 CHECK_INT_COERCE_MARKER (pos);
1675 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
1676 /* this is not right, but much easier than doing what is right. */
1677 /* w->start_at_line_beg = 0; */
1678 /* WTF is the above supposed to mean? GE */
1679 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer),
1680 marker_position (w->start[CURRENT_DISP]));
1683 w->redo_modeline = 1;
1684 SET_LAST_MODIFIED (w, 0);
1685 SET_LAST_FACECHANGE (w);
1687 MARK_WINDOWS_CHANGED (w);
1692 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /*
1693 Return WINDOW's dedicated object, usually t or nil.
1694 See also `set-window-dedicated-p'.
1698 return decode_window (window)->dedicated;
1701 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /*
1702 Control whether WINDOW is dedicated to the buffer it displays.
1703 If it is dedicated, Emacs will not automatically change
1704 which buffer appears in it.
1705 The second argument is the new value for the dedication flag;
1710 struct window *w = decode_window (window);
1712 w->dedicated = NILP (arg) ? Qnil : Qt;
1714 return w->dedicated;
1717 /* FSFmacs has window-display-table here. We have display table as a
1721 /* Record info on buffer window w is displaying
1722 when it is about to cease to display that buffer. */
1724 unshow_buffer (struct window *w)
1726 Lisp_Object buf = w->buffer;
1728 if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
1731 /* FSF disables this check, so I'll do it too. I hope it won't
1732 break things. --ben */
1734 if (w == XWINDOW (Fselected_window (Qnil))
1735 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1736 /* Do this except when the selected window's buffer
1737 is being removed from some other window. */
1739 /* last_window_start records the start position that this buffer
1740 had in the last window to be disconnected from it.
1741 Now that this statement is unconditional,
1742 it is possible for the buffer to be displayed in the
1743 selected window, while last_window_start reflects another
1744 window which was recently showing the same buffer.
1745 Some people might say that might be a good thing. Let's see. */
1746 XBUFFER (buf)->last_window_start =
1747 marker_position (w->start[CURRENT_DISP]);
1749 /* Point in the selected window's buffer
1750 is actually stored in that buffer, and the window's pointm isn't used.
1751 So don't clobber point in that buffer. */
1752 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
1754 struct buffer *b= XBUFFER (buf);
1755 BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
1756 marker_position (w->pointm[CURRENT_DISP]),
1761 /* Put REPLACEMENT into the window structure in place of OLD. */
1763 replace_window (Lisp_Object old, Lisp_Object replacement)
1766 struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1768 /* If OLD is its frame's root_window, then replacement is the new
1769 root_window for that frame. */
1771 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1772 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1774 WINDOW_LEFT (p) = WINDOW_LEFT (o);
1775 WINDOW_TOP (p) = WINDOW_TOP (o);
1776 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
1777 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
1779 p->next = tem = o->next;
1781 XWINDOW (tem)->prev = replacement;
1783 p->prev = tem = o->prev;
1785 XWINDOW (tem)->next = replacement;
1787 p->parent = tem = o->parent;
1790 if (EQ (XWINDOW (tem)->vchild, old))
1791 XWINDOW (tem)->vchild = replacement;
1792 if (EQ (XWINDOW (tem)->hchild, old))
1793 XWINDOW (tem)->hchild = replacement;
1796 /* #### Here, if replacement is a vertical combination
1797 and so is its new parent, we should make replacement's
1798 children be children of that parent instead. */
1801 /* we're deleting W; set the structure of W to indicate this. */
1804 mark_window_as_deleted (struct window *w)
1807 (while t (split-window) (delete-window))
1808 we end up with a tree of deleted windows which are all connected
1809 through the `next' slot. This might not seem so bad, as they're
1810 deleted, and will presumably be GCed - but if even *one* of those
1811 windows is still being pointed to, by the user, or by a window
1812 configuration, then *all* of those windows stick around.
1814 Since the window-configuration code doesn't need any of the
1815 pointers to other windows (they are all recreated from the
1816 window-config data), we set them all to nil so that we
1817 are able to collect more actual garbage.
1827 /* Free the extra data structures attached to windows immediately so
1828 they don't sit around consuming excess space. They will be
1829 reinitialized by the window-configuration code as necessary. */
1830 finalize_window ((void *) w, 0);
1833 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /*
1834 Remove WINDOW from the display. Default is selected window.
1835 If window is the only one on the frame, the frame is destroyed.
1836 Normally, you cannot delete the last non-minibuffer-only frame (you must
1837 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional
1838 second argument FORCE is non-nil, you can delete the last frame. (This
1839 will automatically call `save-buffers-kill-emacs'.)
1843 /* This function can GC if this is the only window in the frame */
1851 /* Note: this function is called by other C code on non-leaf
1854 /* Do the equivalent of decode_window() but don't error out on
1855 deleted window; it's OK to delete an already-deleted window. */
1857 window = Fselected_window (Qnil);
1859 CHECK_WINDOW (window);
1860 w = XWINDOW (window);
1862 /* It's okay to delete an already-deleted window. */
1863 if (! WINDOW_LIVE_P (w))
1866 frame = WINDOW_FRAME (w);
1868 d = XDEVICE (FRAME_DEVICE (f));
1870 if (TOP_LEVEL_WINDOW_P (w))
1872 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
1873 /* this frame isn't fully initialized yet; don't blow up. */
1876 if (MINI_WINDOW_P (XWINDOW (window)))
1877 error ("Attempt to delete the minibuffer window");
1879 /* It has been suggested that it's a good thing for C-x 0 to have this
1880 behavior, but not such a good idea for #'delete-window to have it.
1881 Maybe C-x 0 should be bound to something else, or maybe frame
1882 deletion should only happen when this is called interactively.
1884 delete_frame_internal (f, !NILP (force), 0, 0);
1888 /* At this point, we know the window has a parent. */
1890 par = XWINDOW (parent);
1892 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1893 /* It's quite likely that deleting a window will result in
1894 subwindows needing to be deleted also (since they are cached
1895 per-window). So we mark them as changed, so that the cachels will
1896 get reset by redisplay and thus deleted subwindows can get
1898 MARK_FRAME_SUBWINDOWS_CHANGED (f);
1900 /* Are we trying to delete any frame's selected window?
1901 Note that we could be dealing with a non-leaf window
1902 where the selected window is one of our children.
1903 So, we check by scanning all the ancestors of the
1904 frame's selected window and comparing each one with
1907 Lisp_Object pwindow;
1909 pwindow = FRAME_SELECTED_WINDOW (f);
1911 while (!NILP (pwindow))
1913 if (EQ (window, pwindow))
1915 pwindow = XWINDOW (pwindow)->parent;
1918 if (EQ (window, pwindow))
1920 /* OK, we found it. */
1921 Lisp_Object alternative;
1922 alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
1924 /* If we're about to delete the selected window on the
1925 selected frame, then we should use Fselect_window to select
1926 the new window. On the other hand, if we're about to
1927 delete the selected window on any other frame, we shouldn't do
1928 anything but set the frame's selected_window slot. */
1929 if (EQ (frame, Fselected_frame (Qnil)))
1930 Fselect_window (alternative, Qnil);
1932 set_frame_selected_window (f, alternative);
1936 /* w->buffer is nil in a non-leaf window; in this case,
1937 get rid of the markers we maintain that point into that buffer. */
1938 if (!NILP (w->buffer))
1941 unchain_marker (w->pointm[CURRENT_DISP]);
1942 unchain_marker (w->pointm[DESIRED_DISP]);
1943 unchain_marker (w->pointm[CMOTION_DISP]);
1944 unchain_marker (w->start[CURRENT_DISP]);
1945 unchain_marker (w->start[DESIRED_DISP]);
1946 unchain_marker (w->start[CMOTION_DISP]);
1947 unchain_marker (w->sb_point);
1948 /* This breaks set-window-configuration if windows in the saved
1949 configuration get deleted and multiple frames are in use. */
1950 /* w->buffer = Qnil; */
1953 /* close up the hole in the sibling list */
1954 if (!NILP (w->next))
1955 XWINDOW (w->next)->prev = w->prev;
1956 if (!NILP (w->prev))
1957 XWINDOW (w->prev)->next = w->next;
1958 if (EQ (window, par->hchild))
1959 par->hchild = w->next;
1960 if (EQ (window, par->vchild))
1961 par->vchild = w->next;
1963 /* Find one of our siblings to give our space to. */
1965 Lisp_Object sib = w->prev;
1968 /* If w gives its space to its next sibling, that sibling needs
1969 to have its top/left side pulled back to where w's is.
1970 set_window_{height,width} will re-position the sibling's
1973 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
1974 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
1977 /* Stretch that sibling. */
1978 if (!NILP (par->vchild))
1979 set_window_pixheight
1980 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
1981 if (!NILP (par->hchild))
1983 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
1986 /* If parent now has only one child,
1987 put the child into the parent's place. */
1989 Lisp_Object parchild = par->hchild;
1990 if (NILP (parchild))
1991 parchild = par->vchild;
1992 if (NILP (XWINDOW (parchild)->next))
1994 replace_window (parent, parchild);
1995 mark_window_as_deleted (XWINDOW (parent));
1999 /* Since we may be deleting combination windows, we must make sure that
2000 not only W but all its children have been marked as deleted. */
2001 if (!NILP (w->hchild))
2002 delete_all_subwindows (XWINDOW (w->hchild));
2003 else if (!NILP (w->vchild))
2004 delete_all_subwindows (XWINDOW (w->vchild));
2006 mark_window_as_deleted (w);
2008 f->mirror_dirty = 1;
2013 DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
2014 Return next window after WINDOW in canonical ordering of windows.
2015 If omitted, WINDOW defaults to the selected window.
2017 Optional second arg MINIBUF t means count the minibuffer window even
2018 if not active. MINIBUF nil or omitted means count the minibuffer iff
2019 it is active. MINIBUF neither t nor nil means not to count the
2020 minibuffer even if it is active.
2022 Several frames may share a single minibuffer; if the minibuffer
2023 counts, all windows on all frames that share that minibuffer count
2024 too. Therefore, `next-window' can be used to iterate through the
2025 set of windows even when the minibuffer is on another frame. If the
2026 minibuffer does not count, only windows from WINDOW's frame count.
2028 Optional third arg ALL-FRAMES t means include windows on all frames.
2029 ALL-FRAMES nil or omitted means cycle within the frames as specified
2030 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2031 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2032 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2033 Anything else means restrict to WINDOW's frame.
2035 Optional fourth argument CONSOLE controls which consoles or devices the
2036 returned window may be on. If CONSOLE is a console, return windows only
2037 on that console. If CONSOLE is a device, return windows only on that
2038 device. If CONSOLE is a console type, return windows only on consoles
2039 of that type. If CONSOLE is 'window-system, return any windows on any
2040 window-system consoles. If CONSOLE is nil or omitted, return windows only
2041 on WINDOW's console. Otherwise, all windows are considered.
2043 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2044 can use `next-window' to iterate through the entire cycle of acceptable
2045 windows, eventually ending up back at the window you started with.
2046 `previous-window' traverses the same cycle, in the reverse order.
2048 (window, minibuf, all_frames, console))
2051 Lisp_Object start_window;
2054 window = Fselected_window (Qnil);
2056 CHECK_LIVE_WINDOW (window);
2058 start_window = window;
2060 /* minibuf == nil may or may not include minibuffers.
2061 Decide if it does. */
2063 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2064 else if (! EQ (minibuf, Qt))
2066 /* Now minibuf can be t => count all minibuffer windows,
2067 lambda => count none of them,
2068 or a specific minibuffer window (the active one) to count. */
2070 /* all_frames == nil doesn't specify which frames to include. */
2071 if (NILP (all_frames))
2072 all_frames = (! EQ (minibuf, Qlambda)
2073 ? (FRAME_MINIBUF_WINDOW
2076 (XWINDOW (window)))))
2078 else if (EQ (all_frames, Qvisible))
2080 else if (ZEROP (all_frames))
2082 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2083 /* If all_frames is a frame and window arg isn't on that frame, just
2084 return the first window on the frame. */
2085 return frame_first_window (XFRAME (all_frames));
2086 else if (! EQ (all_frames, Qt))
2088 /* Now all_frames is t meaning search all frames,
2089 nil meaning search just current frame,
2090 visible meaning search just visible frames,
2091 0 meaning search visible and iconified frames,
2092 or a window, meaning search the frame that window belongs to. */
2094 /* Do this loop at least once, to get the next window, and perhaps
2095 again, if we hit the minibuffer and that is not acceptable. */
2098 /* Find a window that actually has a next one. This loop
2099 climbs up the tree. */
2100 while (tem = XWINDOW (window)->next, NILP (tem))
2101 if (tem = XWINDOW (window)->parent, !NILP (tem))
2103 else /* window must be minibuffer window now */
2105 /* We've reached the end of this frame.
2106 Which other frames are acceptable? */
2107 tem = WINDOW_FRAME (XWINDOW (window));
2109 if (! NILP (all_frames))
2114 tem = next_frame (tem, all_frames, console);
2115 /* In the case where the minibuffer is active,
2116 and we include its frame as well as the selected one,
2117 next_frame may get stuck in that frame.
2118 If that happens, go back to the selected frame
2119 so we can complete the cycle. */
2121 XSETFRAME (tem, selected_frame ());
2124 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2130 /* If we're in a combination window, find its first child and
2131 recurse on that. Otherwise, we've found the window we want. */
2134 if (!NILP (XWINDOW (window)->hchild))
2135 window = XWINDOW (window)->hchild;
2136 else if (!NILP (XWINDOW (window)->vchild))
2137 window = XWINDOW (window)->vchild;
2141 /* "acceptable" is the correct spelling. */
2142 /* Which windows are acceptable?
2143 Exit the loop and accept this window if
2144 this isn't a minibuffer window,
2145 or we're accepting all minibuffer windows,
2146 or this is the active minibuffer and we are accepting that one, or
2147 we've come all the way around and we're back at the original window. */
2148 while (MINI_WINDOW_P (XWINDOW (window))
2149 && ! EQ (minibuf, Qt)
2150 && ! EQ (minibuf, window)
2151 && ! EQ (window, start_window));
2156 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
2157 Return the window preceding WINDOW in canonical ordering of windows.
2158 If omitted, WINDOW defaults to the selected window.
2160 Optional second arg MINIBUF t means count the minibuffer window even
2161 if not active. MINIBUF nil or omitted means count the minibuffer iff
2162 it is active. MINIBUF neither t nor nil means not to count the
2163 minibuffer even if it is active.
2165 Several frames may share a single minibuffer; if the minibuffer
2166 counts, all windows on all frames that share that minibuffer count
2167 too. Therefore, `previous-window' can be used to iterate through
2168 the set of windows even when the minibuffer is on another frame. If
2169 the minibuffer does not count, only windows from WINDOW's frame count
2171 If optional third arg ALL-FRAMES t means include windows on all frames.
2172 ALL-FRAMES nil or omitted means cycle within the frames as specified
2173 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2174 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2175 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2176 Anything else means restrict to WINDOW's frame.
2178 Optional fourth argument CONSOLE controls which consoles or devices the
2179 returned window may be on. If CONSOLE is a console, return windows only
2180 on that console. If CONSOLE is a device, return windows only on that
2181 device. If CONSOLE is a console type, return windows only on consoles
2182 of that type. If CONSOLE is 'window-system, return any windows on any
2183 window-system consoles. If CONSOLE is nil or omitted, return windows only
2184 on WINDOW's console. Otherwise, all windows are considered.
2186 If you use consistent values for MINIBUF, ALL-FRAMES, and CONSOLE, you
2187 can use `previous-window' to iterate through the entire cycle of acceptable
2188 windows, eventually ending up back at the window you started with.
2189 `next-window' traverses the same cycle, in the reverse order.
2191 (window, minibuf, all_frames, console))
2194 Lisp_Object start_window;
2197 window = Fselected_window (Qnil);
2199 CHECK_LIVE_WINDOW (window);
2201 start_window = window;
2203 /* minibuf == nil may or may not include minibuffers.
2204 Decide if it does. */
2206 minibuf = (minibuf_level ? minibuf_window : Qlambda);
2207 else if (! EQ (minibuf, Qt))
2209 /* Now minibuf can be t => count all minibuffer windows,
2210 lambda => count none of them,
2211 or a specific minibuffer window (the active one) to count. */
2213 /* all_frames == nil doesn't specify which frames to include.
2214 Decide which frames it includes. */
2215 if (NILP (all_frames))
2216 all_frames = (! EQ (minibuf, Qlambda)
2217 ? (FRAME_MINIBUF_WINDOW
2220 (XWINDOW (window)))))
2222 else if (EQ (all_frames, Qvisible))
2224 else if (ZEROP (all_frames))
2226 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
2227 /* If all_frames is a frame and window arg isn't on that frame, just
2228 return the first window on the frame. */
2229 return frame_first_window (XFRAME (all_frames));
2230 else if (! EQ (all_frames, Qt))
2232 /* Now all_frames is t meaning search all frames,
2233 nil meaning search just current frame,
2234 visible meaning search just visible frames,
2235 0 meaning search visible and iconified frames,
2236 or a window, meaning search the frame that window belongs to. */
2238 /* Do this loop at least once, to get the next window, and perhaps
2239 again, if we hit the minibuffer and that is not acceptable. */
2242 /* Find a window that actually has a next one. This loop
2243 climbs up the tree. */
2244 while (tem = XWINDOW (window)->prev, NILP (tem))
2245 if (tem = XWINDOW (window)->parent, !NILP (tem))
2247 else /* window must be minibuffer window now */
2249 /* We have found the top window on the frame.
2250 Which frames are acceptable? */
2251 tem = WINDOW_FRAME (XWINDOW (window));
2253 if (! NILP (all_frames))
2254 /* It's actually important that we use prev_frame here,
2255 rather than next_frame. All the windows acceptable
2256 according to the given parameters should form a ring;
2257 Fnext_window and Fprevious_window should go back and
2258 forth around the ring. If we use next_frame here,
2259 then Fnext_window and Fprevious_window take different
2260 paths through the set of acceptable windows.
2261 window_loop assumes that these `ring' requirement are
2267 tem = prev_frame (tem, all_frames, console);
2268 /* In the case where the minibuffer is active,
2269 and we include its frame as well as the selected one,
2270 next_frame may get stuck in that frame.
2271 If that happens, go back to the selected frame
2272 so we can complete the cycle. */
2274 XSETFRAME (tem, selected_frame ());
2277 /* If this frame has a minibuffer, find that window first,
2278 because it is conceptually the last window in that frame. */
2279 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
2280 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
2282 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
2289 /* If we're in a combination window, find its first child and
2290 recurse on that. Otherwise, we've found the window we want. */
2293 if (!NILP (XWINDOW (window)->hchild))
2294 window = XWINDOW (window)->hchild;
2295 else if (!NILP (XWINDOW (window)->vchild))
2296 window = XWINDOW (window)->vchild;
2298 while (tem = XWINDOW (window)->next, !NILP (tem))
2302 /* Which windows are acceptable?
2303 Exit the loop and accept this window if
2304 this isn't a minibuffer window,
2305 or we're accepting all minibuffer windows,
2306 or this is the active minibuffer and we are accepting that one, or
2307 we've come all the way around and we're back at the original window. */
2308 while (MINI_WINDOW_P (XWINDOW (window))
2309 && ! EQ (minibuf, Qt)
2310 && ! EQ (minibuf, window)
2311 && ! EQ (window, start_window));
2316 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /*
2317 Return the next window which is vertically after WINDOW.
2322 struct window *w = decode_window (window);
2323 XSETWINDOW (window, w);
2325 if (MINI_WINDOW_P (XWINDOW (window)))
2328 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
2330 if (EQ (window, root))
2333 if (!NILP (XWINDOW (window)->hchild))
2334 window = XWINDOW (window)->hchild;
2335 else if (!NILP (XWINDOW (window)->vchild))
2336 window = XWINDOW (window)->vchild;
2343 if (!NILP (XWINDOW (window)->parent) &&
2344 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
2346 if (!NILP (XWINDOW (window)->next))
2347 return XWINDOW (window)->next;
2349 window = XWINDOW (window)->parent;
2352 window = XWINDOW (window)->parent;
2354 while (!EQ (window, root));
2357 if (!NILP (XWINDOW (window)->hchild))
2358 window = XWINDOW (window)->hchild;
2359 else if (!NILP (XWINDOW (window)->vchild))
2360 window = XWINDOW (window)->vchild;
2365 DEFUN ("other-window", Fother_window, 1, 3, "p", /*
2366 Select the N'th different window on this frame.
2367 All windows on current frame are arranged in a cyclic order.
2368 This command selects the window N steps away in that order.
2369 A negative N moves in the opposite order.
2371 If optional argument FRAME is `visible', search all visible frames.
2372 If FRAME is 0, search all visible and iconified frames.
2373 If FRAME is t, search all frames.
2374 If FRAME is nil, search only the selected frame.
2375 If FRAME is a frame, search only that frame.
2377 Optional third argument CONSOLE controls which consoles or devices the
2378 returned window may be on. If CONSOLE is a console, return windows only
2379 on that console. If CONSOLE is a device, return windows only on that
2380 device. If CONSOLE is a console type, return windows only on consoles
2381 of that type. If CONSOLE is 'window-system, return any windows on any
2382 window-system consoles. If CONSOLE is nil or omitted, return windows only
2383 on FRAME'S console, or on the selected console if FRAME is not a frame.
2384 Otherwise, all windows are considered.
2386 (n, frame, console))
2392 w = Fselected_window (Qnil);
2397 w = Fnext_window (w, Qnil, frame, console);
2402 w = Fprevious_window (w, Qnil, frame, console);
2405 Fselect_window (w, Qnil);
2410 /* Look at all windows, performing an operation specified by TYPE
2413 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
2414 frame. If FRAMES is a frame, just look at windows on that frame.
2415 If MINI is non-zero, perform the operation on minibuffer windows too.
2421 GET_BUFFER_WINDOW, /* Arg is buffer */
2422 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2423 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2424 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2426 UNSHOW_BUFFER, /* Arg is buffer */
2427 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
2428 GET_BUFFER_MRU_WINDOW /* Arg is buffer */
2432 window_loop (enum window_loop type,
2437 Lisp_Object console)
2439 /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
2441 Lisp_Object best_window = Qnil;
2442 Lisp_Object next_window;
2443 Lisp_Object last_window;
2444 struct frame *frame;
2445 Lisp_Object frame_arg = Qt;
2446 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
2447 /* #### I think the change of "precomputing" last_window and next_window
2448 * #### catch the lossage this is meant(?) to punt on...
2451 Lisp_Object devcons, concons;
2453 /* FRAME_ARG is Qlambda to stick to one frame,
2454 Qvisible to consider all visible frames,
2457 /* If we're only looping through windows on a particular frame,
2458 FRAME points to that frame. If we're looping through windows
2459 on all frames, FRAME is 0. */
2461 if (FRAMEP (frames))
2462 frame = XFRAME (frames);
2463 else if (NILP (frames))
2464 frame = selected_frame ();
2468 frame_arg = Qlambda;
2469 else if (ZEROP (frames))
2471 else if (EQ (frames, Qvisible))
2474 DEVICE_LOOP_NO_BREAK (devcons, concons)
2476 Lisp_Object device = XCAR (devcons);
2477 Lisp_Object the_frame;
2480 XSETFRAME (the_frame, frame);
2482 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device));
2484 if (NILP (the_frame))
2487 if (!device_matches_console_spec (the_frame, device, console))
2490 /* Pick a window to start with. */
2494 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame));
2496 /* Figure out the last window we're going to mess with. Since
2497 Fnext_window, given the same options, is guaranteed to go in a
2498 ring, we can just use Fprevious_window to find the last one.
2500 We can't just wait until we hit the first window again,
2501 because it might be deleted. */
2503 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2508 struct window *p = XWINDOW (w);
2509 struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
2511 /* Pick the next window now, since some operations will delete
2512 the current window. */
2513 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
2515 /* #### Still needed ?? */
2516 /* Given the outstanding quality of the rest of this code,
2517 I feel no shame about putting this piece of shit in. */
2518 if (++lose_lose >= 500)
2521 /* Note that we do not pay attention here to whether
2522 the frame is visible, since Fnext_window skips non-visible frames
2523 if that is desired, under the control of frame_arg. */
2524 if (! MINI_WINDOW_P (p)
2525 || (mini && minibuf_level > 0))
2528 case GET_BUFFER_WINDOW:
2530 if (XBUFFER (p->buffer) == XBUFFER (obj))
2535 case GET_BUFFER_WINDOW_COUNT:
2537 if (XBUFFER (p->buffer) == XBUFFER (obj))
2542 case GET_LRU_WINDOW:
2544 /* t as arg means consider only full-width windows */
2546 && !window_full_width_p (p))
2548 /* Ignore dedicated windows and minibuffers. */
2549 if (MINI_WINDOW_P (p)
2550 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2552 if (NILP (best_window)
2553 || (XINT (XWINDOW (best_window)->use_time)
2554 > XINT (p->use_time)))
2559 case GET_BUFFER_MRU_WINDOW:
2561 /* #### what about the first check in GET_LRU_WINDOW? */
2562 /* Ignore dedicated windows and minibuffers. */
2563 if (MINI_WINDOW_P (p)
2564 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2567 if (XBUFFER (p->buffer) == XBUFFER (obj))
2569 if (NILP (best_window)
2570 || (XINT (XWINDOW (best_window)->use_time)
2571 < XINT (p->use_time)))
2577 case DELETE_OTHER_WINDOWS:
2579 /* Don't delete the last window on a frame; this can
2580 happen when the minibuffer is selected, and would
2581 cause the frame to be deleted. */
2582 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
2583 Fdelete_window (w, Qnil);
2587 case DELETE_BUFFER_WINDOWS:
2589 if (EQ (p->buffer, obj))
2591 struct frame *f = XFRAME (WINDOW_FRAME (p));
2593 /* If this window is dedicated, and in a frame
2594 of its own, kill the frame. */
2595 if (EQ (w, FRAME_ROOT_WINDOW (f))
2596 && !NILP (p->dedicated)
2597 && other_visible_frames (f))
2599 /* Skip the other windows on this frame.
2600 There might be one, the minibuffer! */
2601 if (! EQ (w, last_window))
2602 while (f == XFRAME (WINDOW_FRAME
2603 (XWINDOW (next_window))))
2605 /* As we go, check for the end of the
2606 loop. We mustn't start going
2607 around a second time. */
2608 if (EQ (next_window, last_window))
2613 next_window = Fnext_window (next_window,
2617 /* Now we can safely delete the frame. */
2618 Fdelete_frame (WINDOW_FRAME (p), Qnil);
2621 /* If we're deleting the buffer displayed in
2622 the only window on the frame, find a new
2623 buffer to display there. */
2624 if (NILP (p->parent))
2626 Lisp_Object new_buffer;
2627 new_buffer = Fother_buffer (obj, Qnil, Qnil);
2628 if (NILP (new_buffer))
2629 new_buffer = Fget_buffer_create (QSscratch);
2630 Fset_window_buffer (w, new_buffer, Qnil);
2631 if (EQ (w, Fselected_window (Qnil)))
2632 Fset_buffer (p->buffer);
2635 Fdelete_window (w, Qnil);
2640 case GET_LARGEST_WINDOW:
2642 /* Ignore dedicated windows and minibuffers. */
2643 if (MINI_WINDOW_P (p)
2644 || (dedicated_too ? 0 : !NILP (p->dedicated)))
2647 /* write the check as follows to avoid tripping
2648 error_check_window() --ben */
2649 struct window *b = NILP (best_window) ? 0 :
2650 XWINDOW (best_window);
2651 if (NILP (best_window)
2652 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
2653 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
2661 if (EQ (p->buffer, obj))
2663 /* Find another buffer to show in this window. */
2664 Lisp_Object another_buffer =
2665 Fother_buffer (obj, Qnil, Qnil);
2666 if (NILP (another_buffer))
2668 = Fget_buffer_create (QSscratch);
2669 /* If this window is dedicated, and in a frame
2670 of its own, kill the frame. */
2671 if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
2672 && !NILP (p->dedicated)
2673 && other_visible_frames (w_frame))
2675 /* Skip the other windows on this frame.
2676 There might be one, the minibuffer! */
2677 if (! EQ (w, last_window))
2678 while (w_frame == XFRAME (WINDOW_FRAME
2679 (XWINDOW (next_window))))
2681 /* As we go, check for the end of the
2682 loop. We mustn't start going
2683 around a second time. */
2684 if (EQ (next_window, last_window))
2689 next_window = Fnext_window (next_window,
2693 /* Now we can safely delete the frame. */
2694 delete_frame_internal (XFRAME (WINDOW_FRAME (p)),
2699 /* Otherwise show a different buffer in the
2701 p->dedicated = Qnil;
2702 Fset_window_buffer (w, another_buffer, Qnil);
2703 if (EQ (w, Fselected_window (Qnil)))
2704 Fset_buffer (p->buffer);
2714 if (EQ (w, last_window))
2721 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window;
2724 #if 0 /* not currently used */
2727 buffer_window_count (struct buffer *b, struct frame *f)
2729 Lisp_Object buffer, frame;
2731 XSETFRAME (frame, f);
2732 XSETBUFFER (buffer, b);
2734 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1,
2739 buffer_window_mru (struct window *w)
2741 Lisp_Object window =
2742 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil);
2746 else if (XWINDOW (window) == w)
2755 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /*
2756 Return the window least recently selected or used for display.
2757 If optional argument FRAME is `visible', search all visible frames.
2758 If FRAME is 0, search all visible and iconified frames.
2759 If FRAME is t, search all frames.
2760 If FRAME is nil, search only the selected frame.
2761 If FRAME is a frame, search only that frame.
2763 Optional second argument CONSOLE controls which consoles or devices the
2764 returned window may be on. If CONSOLE is a console, return windows only
2765 on that console. If CONSOLE is a device, return windows only on that
2766 device. If CONSOLE is a console type, return windows only on consoles
2767 of that type. If CONSOLE is 'window-system, return any windows on any
2768 window-system consoles. If CONSOLE is nil or omitted, return windows only
2769 on FRAME'S console, or on the selected console if FRAME is not a frame.
2770 Otherwise, all windows are considered.
2775 /* First try for a non-dedicated window that is full-width */
2776 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0, console);
2777 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2780 /* Then try for any non-dedicated window */
2781 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0, console);
2782 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2786 /* FSFmacs never returns a dedicated window here. If we do,
2787 it makes `display-buffer' not work right. #### All of this
2788 shit is so disgusting and awful that it needs to be rethought
2790 /* then try for a dedicated window that is full-width */
2791 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1, console);
2792 if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
2795 /* If none of them, then all windows, dedicated or not. */
2796 w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1, console);
2798 /* At this point we damn well better have found something. */
2799 if (NILP (w)) abort ();
2805 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /*
2806 Return the window largest in area.
2807 If optional argument FRAME is `visible', search all visible frames.
2808 If 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 second 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.
2824 /* Don't search dedicated windows because FSFmacs doesn't.
2825 This stuff is all black magic so don't try to apply common
2827 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 0, console);
2830 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /*
2831 Return a window currently displaying BUFFER, or nil if none.
2832 If optional argument FRAME is `visible', search all visible frames.
2833 If optional argument FRAME is 0, search all visible and iconified frames.
2834 If FRAME is t, search all frames.
2835 If FRAME is nil, search only the selected frame.
2836 If FRAME is a frame, search only that frame.
2838 Optional third argument CONSOLE controls which consoles or devices the
2839 returned window may be on. If CONSOLE is a console, return windows only
2840 on that console. If CONSOLE is a device, return windows only on that
2841 device. If CONSOLE is a console type, return windows only on consoles
2842 of that type. If CONSOLE is 'window-system, return any windows on any
2843 window-system consoles. If CONSOLE is nil or omitted, return windows only
2844 on FRAME'S console, or on the selected console if FRAME is not a frame.
2845 Otherwise, all windows are considered.
2847 (buffer, frame, console))
2849 buffer = Fget_buffer (buffer);
2850 if (BUFFERP (buffer))
2851 /* Search dedicated windows too. (Doesn't matter here anyway.) */
2852 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1, console);
2857 /* These functions used to be `buffer-left-margin-pixel-width', etc.
2858 but there is no sensible way to implement those functions, since
2859 you can't in general derive a window from a buffer. */
2861 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
2863 Return the width in pixels of the left outside margin of window WINDOW.
2864 If WINDOW is nil, the selected window is assumed.
2868 return make_int (window_left_margin_width (decode_window (window)));
2871 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
2873 Return the width in pixels of the right outside margin of window WINDOW.
2874 If WINDOW is nil, the selected window is assumed.
2878 return make_int (window_right_margin_width (decode_window (window)));
2881 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /*
2882 Make WINDOW (or the selected window) fill its frame.
2883 Only the frame WINDOW is on is affected.
2884 This function tries to reduce display jumps
2885 by keeping the text previously visible in WINDOW
2886 in the same place on the frame. Doing this depends on
2887 the value of (window-start WINDOW), so if calling this function
2888 in a program gives strange scrolling, make sure the window-start
2889 value is reasonable when this function is called.
2893 struct window *w = decode_window (window);
2894 struct buffer *b = XBUFFER (w->buffer);
2896 int old_top = WINDOW_TOP (w);
2898 XSETWINDOW (window, w);
2900 if (MINI_WINDOW_P (w) && old_top > 0)
2901 error ("Can't expand minibuffer to full frame");
2903 /* Ignore dedicated windows. */
2904 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil);
2906 start_pos = marker_position (w->start[CURRENT_DISP]);
2908 /* Try to minimize scrolling, by setting the window start to the
2909 point which will cause the text at the old window start to be at
2910 the same place on the frame. But don't try to do this if the
2911 window start is outside the visible portion (as might happen when
2912 the display is not current, due to typeahead). */
2913 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
2914 && !MINI_WINDOW_P (w))
2916 Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
2918 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
2920 Fset_marker (w->start[CURRENT_DISP], make_int (new_start),
2922 w->start_at_line_beg = beginning_of_line_p (b, new_start);
2924 /* We need to do this, so that the window-scroll-functions
2932 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3,
2933 "bDelete windows on (buffer): ", /*
2934 Delete all windows showing BUFFER.
2935 Optional second argument FRAME controls which frames are affected.
2936 If nil or omitted, delete all windows showing BUFFER in any frame.
2937 If t, delete only windows showing BUFFER in the selected frame.
2938 If `visible', delete all windows showing BUFFER in any visible frame.
2939 If a frame, delete only windows showing BUFFER in that frame.
2941 Optional third argument CONSOLE controls which consoles or devices the
2942 returned window may be on. If CONSOLE is a console, return windows only
2943 on that console. If CONSOLE is a device, return windows only on that
2944 device. If CONSOLE is a console type, return windows only on consoles
2945 of that type. If CONSOLE is 'window-system, return any windows on any
2946 window-system consoles. If CONSOLE is nil or omitted, return windows only
2947 on FRAME'S console, or on the selected console if FRAME is not a frame.
2948 Otherwise, all windows are considered.
2950 (buffer, frame, console))
2952 /* This function can GC */
2953 /* FRAME uses t and nil to mean the opposite of what window_loop
2955 if (!FRAMEP (frame))
2956 frame = NILP (frame) ? Qt : Qnil;
2960 buffer = Fget_buffer (buffer);
2961 CHECK_BUFFER (buffer);
2962 /* Ignore dedicated windows. */
2963 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0, console);
2968 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 1,
2969 "bReplace buffer in windows: ", /*
2970 Replace BUFFER with some other buffer in all windows showing it.
2974 /* This function can GC */
2977 buffer = Fget_buffer (buffer);
2978 CHECK_BUFFER (buffer);
2979 /* Ignore dedicated windows. */
2980 window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0, Qnil);
2985 /* The smallest acceptable dimensions for a window. Anything smaller
2986 might crash Emacs. */
2987 #define MIN_SAFE_WINDOW_WIDTH (2)
2988 #define MIN_SAFE_WINDOW_HEIGHT (2)
2990 /* Make sure that window_min_height and window_min_width are
2991 not too small; if they are, set them to safe minima. */
2994 check_min_window_sizes (void)
2996 /* Smaller values might permit a crash. */
2997 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2998 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2999 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
3000 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
3004 frame_min_height (struct frame *frame)
3006 /* For height, we have to see whether the frame has a minibuffer, and
3007 whether it wants a modeline. */
3008 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
3009 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
3010 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
3013 /* Return non-zero if both frame sizes are less than or equal to
3014 minimal allowed values. ROWS and COLS are in characters */
3016 frame_size_valid_p (struct frame *frame, int rows, int cols)
3018 return (rows >= frame_min_height (frame)
3019 && cols >= MIN_SAFE_WINDOW_WIDTH);
3022 /* Return non-zero if both frame sizes are less than or equal to
3023 minimal allowed values. WIDTH and HEIGHT are in pixels */
3025 frame_pixsize_valid_p (struct frame *frame, int width, int height)
3028 pixel_to_real_char_size (frame, width, height, &cols, &rows);
3029 return frame_size_valid_p (frame, rows, cols);
3032 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3033 minimum allowable size. */
3035 check_frame_size (struct frame *frame, int *rows, int *cols)
3037 int min_height = frame_min_height (frame);
3039 if (*rows < min_height)
3041 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3042 *cols = MIN_SAFE_WINDOW_WIDTH;
3045 /* Normally the window is deleted if it gets too small.
3046 nodelete nonzero means do not do this.
3047 (The caller should check later and do so if appropriate) */
3049 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
3052 struct window *w = XWINDOW (window);
3053 struct frame *f = XFRAME (w->frame);
3055 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
3056 Lisp_Object child, minor_kid, major_kid;
3059 int defheight, defwidth;
3061 /* #### This is very likely incorrect and instead the char_to_pixel_
3062 functions should be called. */
3063 default_face_height_and_width (window, &defheight, &defwidth);
3064 line_size = (set_height ? defheight : defwidth);
3066 check_min_window_sizes ();
3068 minsize = (set_height ? window_min_height : window_min_width);
3069 minsize *= line_size;
3072 && !TOP_LEVEL_WINDOW_P (w)
3073 && new_pixsize < minsize)
3075 Fdelete_window (window, Qnil);
3079 SET_LAST_MODIFIED (w, 0);
3080 SET_LAST_FACECHANGE (w);
3081 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
3084 WINDOW_HEIGHT (w) = new_pixsize;
3085 major_kid = w->vchild;
3086 minor_kid = w->hchild;
3090 WINDOW_WIDTH (w) = new_pixsize;
3091 major_kid = w->hchild;
3092 minor_kid = w->vchild;
3095 if (!NILP (minor_kid))
3097 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
3100 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
3102 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
3104 set_window_pixsize (child, new_pixsize, nodelete, set_height);
3107 else if (!NILP (major_kid))
3109 int last_pos, last_old_pos, pos, old_pos, first;
3110 int pixel_adj_left = new_pixsize - old_pixsize;
3111 int div_val = old_pixsize << 1;
3114 * Previously we bailed out here if there was no size change.
3115 * (pixel_adj_left == 0) But this broke toolbar updates. If a
3116 * toolbar appears or disappears, windows may not change size,
3117 * but their top and left coordinates need to be updated.
3119 * So we don't bail until after the loop below.
3122 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
3125 for (child = major_kid; !NILP (child); child = c->next)
3127 c = XWINDOW (child);
3131 old_pos = last_old_pos + WINDOW_HEIGHT (c);
3132 WINDOW_TOP (c) = last_pos;
3136 old_pos = last_old_pos + WINDOW_WIDTH (c);
3137 WINDOW_LEFT (c) = last_pos;
3140 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
3141 /* All but the last window should have a height which is
3142 a multiple of the default line height. */
3143 if (!NILP (c->next))
3144 pos = (pos / line_size) * line_size;
3146 /* Avoid confusion: don't delete child if it becomes too small */
3147 set_window_pixsize (child, pos + first - last_pos, 1, set_height);
3149 last_pos = pos + first;
3150 last_old_pos = old_pos;
3153 /* Sometimes we may get called with our old size. In that case
3154 we don't need to do anything else. */
3155 if (!pixel_adj_left)
3158 /* Now delete any children that became too small. */
3160 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
3163 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
3165 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
3170 /* Set the height of WINDOW and all its inferiors. */
3172 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
3174 set_window_pixsize (window, new_pixheight, nodelete, 1);
3177 /* Recursively set width of WINDOW and its inferiors. */
3179 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
3181 set_window_pixsize (window, new_pixwidth, nodelete, 0);
3185 static int window_select_count;
3187 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
3188 Make WINDOW display BUFFER as its contents.
3189 BUFFER can be a buffer or buffer name.
3191 With non-nil optional argument `norecord', do not modify the
3192 global or per-frame buffer ordering.
3194 (window, buffer, norecord))
3197 struct window *w = decode_window (window);
3199 buffer = Fget_buffer (buffer);
3200 CHECK_BUFFER (buffer);
3202 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3203 error ("Attempt to display deleted buffer");
3207 error ("Window is deleted");
3209 /* While this seems like a logical thing to do, it causes problems
3210 because of saved window configurations. It is possible for a
3211 buffer to get restored into a window in which it is already being
3212 displayed, but start and point are actually at completely
3213 different locations. So we let this function complete fully and
3214 it will then make sure redisplay correctly updates things.
3216 #### This is a kludge. The correct approach is not to do this
3217 but to fix set-window-configuration. */
3219 else if (EQ (tem, buffer))
3222 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3223 is first being set up. */
3225 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3226 error ("Window is dedicated to buffer %s",
3227 XSTRING_DATA (XBUFFER (tem)->name));
3233 w->window_end_pos[CURRENT_DISP] = 0;
3235 w->modeline_hscroll = 0;
3236 Fset_marker (w->pointm[CURRENT_DISP],
3237 make_int (BUF_PT (XBUFFER (buffer))),
3239 set_marker_restricted (w->start[CURRENT_DISP],
3240 make_int (XBUFFER (buffer)->last_window_start),
3242 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
3243 /* set start_at_line_beg correctly. GE */
3244 w->start_at_line_beg = beginning_of_line_p (XBUFFER (buffer),
3245 marker_position (w->start[CURRENT_DISP]));
3246 w->force_start = 0; /* Lucid fix */
3247 SET_LAST_MODIFIED (w, 1);
3248 SET_LAST_FACECHANGE (w);
3249 MARK_WINDOWS_CHANGED (w);
3250 recompute_all_cached_specifiers_in_window (w);
3251 if (EQ (window, Fselected_window (Qnil)))
3253 if (NILP (norecord))
3254 Frecord_buffer (buffer);
3256 Fset_buffer (buffer);
3261 DEFUN ("select-window", Fselect_window, 1, 2, 0, /*
3262 Select WINDOW. Most editing will apply to WINDOW's buffer.
3263 The main editor command loop selects the buffer of the selected window
3264 before each command.
3266 With non-nil optional argument `norecord', do not modify the
3267 global or per-frame buffer ordering.
3272 Lisp_Object old_selected_window = Fselected_window (Qnil);
3274 CHECK_LIVE_WINDOW (window);
3275 w = XWINDOW (window);
3277 /* we have already caught dead-window errors */
3278 if (!NILP (w->hchild) || !NILP (w->vchild))
3279 error ("Trying to select non-leaf window");
3281 w->use_time = make_int (++window_select_count);
3282 if (EQ (window, old_selected_window))
3285 /* deselect the old window, if it exists (it might not exist if
3286 the selected device has no frames, which occurs at startup) */
3287 if (!NILP (old_selected_window))
3289 struct window *ow = XWINDOW (old_selected_window);
3291 Fset_marker (ow->pointm[CURRENT_DISP],
3292 make_int (BUF_PT (XBUFFER (ow->buffer))),
3295 MARK_WINDOWS_CHANGED (ow);
3298 /* now select the window's frame */
3299 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window);
3301 select_frame_1 (WINDOW_FRAME (w));
3303 /* also select the window's buffer */
3304 if (NILP (norecord))
3305 Frecord_buffer (w->buffer);
3306 Fset_buffer (w->buffer);
3308 /* Go to the point recorded in the window.
3309 This is important when the buffer is in more
3310 than one window. It also matters when
3311 redisplay_window has altered point after scrolling,
3312 because it makes the change only in the window. */
3314 Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
3315 if (new_point < BUF_BEGV (current_buffer))
3316 new_point = BUF_BEGV (current_buffer);
3317 else if (new_point > BUF_ZV (current_buffer))
3318 new_point = BUF_ZV (current_buffer);
3320 BUF_SET_PT (current_buffer, new_point);
3323 MARK_WINDOWS_CHANGED (w);
3329 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p,
3330 Lisp_Object override_frame)
3332 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3336 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
3338 /* This function can GC */
3341 struct buffer *b = XBUFFER (buf);
3343 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b);
3344 widen_buffer (b, 0);
3345 BUF_SET_PT (b, BUF_BEG (b));
3347 if (!NILP (Vtemp_buffer_show_function))
3348 call1 (Vtemp_buffer_show_function, buf);
3351 window = display_buffer (buf, Qnil, same_frame);
3353 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
3354 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3356 Vminibuffer_scroll_window = window;
3357 w = XWINDOW (window);
3359 w->modeline_hscroll = 0;
3360 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf);
3361 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf);
3362 set_marker_restricted (w->sb_point, make_int (1), buf);
3364 /* Run temp-buffer-show-hook, with the chosen window selected. */
3365 if (!preparing_for_armageddon)
3368 tem = Fboundp (Qtemp_buffer_show_hook);
3371 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3374 int count = specpdl_depth ();
3376 /* Select the window that was chosen, for running
3378 record_unwind_protect (save_window_excursion_unwind,
3379 Fcurrent_window_configuration (Qnil));
3381 Fselect_window (window, Qnil);
3382 run_hook (Qtemp_buffer_show_hook);
3383 unbind_to (count, Qnil);
3391 make_dummy_parent (Lisp_Object window)
3394 struct window *o = XWINDOW (window);
3395 struct window *p = alloc_lcrecord_type (struct window, &lrecord_window);
3397 XSETWINDOW (new, p);
3398 copy_lcrecord (p, o);
3400 /* Don't copy the pointers to the line start cache or the face
3402 p->line_start_cache = Dynarr_new (line_start_cache);
3403 p->face_cachels = Dynarr_new (face_cachel);
3404 p->glyph_cachels = Dynarr_new (glyph_cachel);
3406 /* Put new into window structure in place of window */
3407 replace_window (window, new);
3415 p->start[CURRENT_DISP] = Qnil;
3416 p->start[DESIRED_DISP] = Qnil;
3417 p->start[CMOTION_DISP] = Qnil;
3418 p->pointm[CURRENT_DISP] = Qnil;
3419 p->pointm[DESIRED_DISP] = Qnil;
3420 p->pointm[CMOTION_DISP] = Qnil;
3425 DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
3426 Split WINDOW, putting SIZE lines in the first of the pair.
3427 WINDOW defaults to selected one and SIZE to half its size.
3428 If optional third arg HOR-FLAG is non-nil, split side by side
3429 and put SIZE columns in the first of the pair.
3431 (window, chsize, horflag))
3434 struct window *o, *p;
3440 window = Fselected_window (Qnil);
3442 CHECK_LIVE_WINDOW (window);
3444 o = XWINDOW (window);
3445 f = XFRAME (WINDOW_FRAME (o));
3449 if (!NILP (horflag))
3450 /* In the new scheme, we are symmetric with respect to separators
3451 so there is no need to do weird things here. */
3453 psize = WINDOW_WIDTH (o) >> 1;
3454 size = window_pixel_width_to_char_width (o, psize, 0);
3458 psize = WINDOW_HEIGHT (o) >> 1;
3459 size = window_pixel_height_to_char_height (o, psize, 1);
3465 size = XINT (chsize);
3466 if (!NILP (horflag))
3467 psize = window_char_width_to_pixel_width (o, size, 0);
3469 psize = window_char_height_to_pixel_height (o, size, 1);
3472 if (MINI_WINDOW_P (o))
3473 error ("Attempt to split minibuffer window");
3474 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
3475 error ("Attempt to split unsplittable frame");
3477 check_min_window_sizes ();
3481 if (size < window_min_height)
3482 error ("Window height %d too small (after splitting)", size);
3483 if (size + window_min_height > window_char_height (o, 1))
3484 error ("Window height %d too small (after splitting)",
3485 window_char_height (o, 1) - size);
3486 if (NILP (o->parent)
3487 || NILP (XWINDOW (o->parent)->vchild))
3489 make_dummy_parent (window);
3490 reset_face_cachels (XWINDOW (window));
3492 XWINDOW (new)->vchild = window;
3493 XFRAME (o->frame)->mirror_dirty = 1;
3498 if (size < window_min_width)
3499 error ("Window width %d too small (after splitting)", size);
3500 if (size + window_min_width > window_char_width (o, 0))
3501 error ("Window width %d too small (after splitting)",
3502 window_char_width (o, 0) - size);
3503 if (NILP (o->parent)
3504 || NILP (XWINDOW (o->parent)->hchild))
3506 make_dummy_parent (window);
3507 reset_face_cachels (XWINDOW (window));
3509 XWINDOW (new)->hchild = window;
3510 XFRAME (o->frame)->mirror_dirty = 1;
3514 /* Now we know that window's parent is a vertical combination
3515 if we are dividing vertically, or a horizontal combination
3516 if we are making side-by-side windows */
3518 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
3519 new = allocate_window ();
3522 p->frame = o->frame;
3524 if (!NILP (p->next))
3525 XWINDOW (p->next)->prev = new;
3528 p->parent = o->parent;
3531 reset_face_cachels (p);
3532 reset_glyph_cachels (p);
3535 /* Apportion the available frame space among the two new windows */
3537 if (!NILP (horflag))
3539 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
3540 WINDOW_TOP (p) = WINDOW_TOP (o);
3541 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
3542 WINDOW_WIDTH (o) = psize;
3543 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
3547 WINDOW_LEFT (p) = WINDOW_LEFT (o);
3548 WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
3549 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
3550 WINDOW_HEIGHT (o) = psize;
3551 WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
3554 XFRAME (p->frame)->mirror_dirty = 1;
3555 /* do this last (after the window is completely initialized and
3556 the mirror-dirty flag is set) so that specifier recomputation
3557 caused as a result of this will work properly and not abort. */
3558 Fset_window_buffer (new, o->buffer, Qt);
3563 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /*
3564 Make the selected window N lines bigger.
3565 From program, optional second arg SIDE non-nil means grow sideways N columns,
3566 and optional third arg WINDOW specifies the window to change instead of the
3571 struct window *w = decode_window (window);
3573 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 0);
3577 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /*
3578 Make the selected window N pixels bigger.
3579 From program, optional second arg SIDE non-nil means grow sideways N pixels,
3580 and optional third arg WINDOW specifies the window to change instead of the
3585 struct window *w = decode_window (window);
3587 change_window_height (w, XINT (n), !NILP (side), /* inpixels */ 1);
3591 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /*
3592 Make the selected window N lines smaller.
3593 From program, optional second arg SIDE non-nil means shrink sideways N columns,
3594 and optional third arg WINDOW specifies the window to change instead of the
3600 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3605 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /*
3606 Make the selected window N pixels smaller.
3607 From program, optional second arg SIDE non-nil means shrink sideways N pixels,
3608 and optional third arg WINDOW specifies the window to change instead of the
3614 change_window_height (decode_window (window), -XINT (n), !NILP (side),
3620 window_pixel_height (Lisp_Object window)
3622 return WINDOW_HEIGHT (XWINDOW (window));
3626 window_pixel_height_to_char_height (struct window *w, int pixel_height,
3627 int include_gutters_p)
3630 int defheight, defwidth;
3634 XSETWINDOW (window, w);
3636 avail_height = (pixel_height -
3637 (include_gutters_p ? 0 :
3638 window_top_gutter_height (w) +
3639 window_bottom_gutter_height (w)));
3641 default_face_height_and_width (window, &defheight, &defwidth);
3643 char_height = avail_height / defheight;
3645 /* It's the calling function's responsibility to check these values
3646 and make sure they're not out of range.
3648 #### We need to go through the calling functions and actually
3650 return max (0, char_height);
3654 window_char_height_to_pixel_height (struct window *w, int char_height,
3655 int include_gutters_p)
3658 int defheight, defwidth;
3663 XSETWINDOW (window, w);
3665 default_face_height_and_width (window, &defheight, &defwidth);
3667 avail_height = char_height * defheight;
3668 pixel_height = (avail_height +
3669 (include_gutters_p ? 0 :
3670 window_top_gutter_height (w) +
3671 window_bottom_gutter_height (w)));
3673 /* It's the calling function's responsibility to check these values
3674 and make sure they're not out of range.
3676 #### We need to go through the calling functions and actually
3678 return max (0, pixel_height);
3681 /* Return number of default lines of text can fit in the window W.
3682 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
3683 horizontal scrollbar) in the space that is used for the calculation.
3686 window_char_height (struct window *w, int include_gutters_p)
3688 return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
3693 * Return number of lines currently displayed in window w. If
3694 * end-of-buffer is displayed then the area below end-of-buffer is assume
3695 * to be blank lines of default height.
3696 * Does not include the modeline.
3699 window_displayed_height (struct window *w)
3701 struct buffer *b = XBUFFER (w->buffer);
3702 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
3704 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
3706 : w->window_end_pos[CURRENT_DISP]);
3708 if (!Dynarr_length (dla))
3709 return window_char_height (w, 0);
3711 num_lines = Dynarr_length (dla);
3713 /* #### Document and assert somewhere that w->window_end_pos == -1
3714 indicates that end-of-buffer is being displayed. */
3717 struct display_line *dl = Dynarr_atp (dla, 0);
3718 int ypos1 = dl->ypos + dl->descent;
3719 int ypos2 = WINDOW_TEXT_BOTTOM (w);
3721 int defheight, defwidth;
3723 XSETWINDOW (window, w);
3729 if (Dynarr_length (dla) == 1)
3730 ypos1 = WINDOW_TEXT_TOP (w);
3733 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
3734 /* If this line is clipped then we know that there is no
3735 blank room between eob and the modeline. If we are
3736 scrolling on clipped lines just know off the clipped
3738 if (scroll_on_clipped_lines && dl->clip)
3739 return num_lines - 1;
3740 ypos1 = dl->ypos + dl->descent - dl->clip;
3744 default_face_height_and_width (window, &defheight, &defwidth);
3745 /* #### This probably needs to know about the clipping area once a
3746 final definition is decided on. */
3747 num_lines += ((ypos2 - ypos1) / defheight);
3751 if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
3754 if (scroll_on_clipped_lines
3755 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
3763 window_pixel_width (Lisp_Object window)
3765 return WINDOW_WIDTH (XWINDOW (window));
3769 window_pixel_width_to_char_width (struct window *w, int pixel_width,
3770 int include_margins_p)
3774 int defheight, defwidth;
3777 XSETWINDOW (window, w);
3779 avail_width = (pixel_width -
3780 window_left_gutter_width (w, 0) -
3781 window_right_gutter_width (w, 0) -
3782 (include_margins_p ? 0 : window_left_margin_width (w)) -
3783 (include_margins_p ? 0 : window_right_margin_width (w)));
3785 default_face_height_and_width (window, &defheight, &defwidth);
3787 char_width = (avail_width / defwidth);
3789 /* It's the calling function's responsibility to check these values
3790 and make sure they're not out of range.
3792 #### We need to go through the calling functions and actually
3794 return max (0, char_width);
3798 window_char_width_to_pixel_width (struct window *w, int char_width,
3799 int include_margins_p)
3803 int defheight, defwidth;
3806 XSETWINDOW (window, w);
3808 default_face_height_and_width (window, &defheight, &defwidth);
3810 avail_width = char_width * defwidth;
3811 pixel_width = (avail_width +
3812 window_left_gutter_width (w, 0) +
3813 window_right_gutter_width (w, 0) +
3814 (include_margins_p ? 0 : window_left_margin_width (w)) +
3815 (include_margins_p ? 0 : window_right_margin_width (w)));
3817 /* It's the calling function's responsibility to check these values
3818 and make sure they're not out of range.
3820 #### We need to go through the calling functions and actually
3822 return max (0, pixel_width);
3825 /* This returns the usable space which doesn't include space needed by
3826 scrollbars or divider lines. */
3828 window_char_width (struct window *w, int include_margins_p)
3830 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
3834 #define MINSIZE(w) \
3836 ? window_min_width * defwidth \
3837 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
3840 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
3842 #define CURSIZE(w) \
3843 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
3845 #define CURCHARSIZE(w) \
3846 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
3848 #define MINCHARSIZE(window) \
3849 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
3850 ? 1 : window_min_height)
3852 /* Unlike set_window_pixheight, this function
3853 also changes the heights of the siblings so as to
3854 keep everything consistent. */
3857 change_window_height (struct window *win, int delta, int widthflag,
3865 int (*sizefun) (Lisp_Object) = (widthflag
3866 ? window_pixel_width
3867 : window_pixel_height);
3868 void (*setsizefun) (Lisp_Object, int, int) = (widthflag
3869 ? set_window_pixwidth
3870 : set_window_pixheight);
3872 int defheight, defwidth;
3877 check_min_window_sizes ();
3879 XSETWINDOW (window, win);
3880 f = XFRAME (win->frame);
3881 if (EQ (window, FRAME_ROOT_WINDOW (f)))
3882 error ("Won't change only window");
3884 /* #### This is very likely incorrect and instead the char_to_pixel_
3885 functions should be called. */
3886 default_face_height_and_width (window, &defheight, &defwidth);
3890 w = XWINDOW (window);
3895 error ("No other window to side of this one");
3899 ? !NILP (XWINDOW (parent)->hchild)
3900 : !NILP (XWINDOW (parent)->vchild))
3905 sizep = &CURSIZE (w);
3906 dim = CURCHARSIZE (w);
3908 if ((inpixels && (*sizep + delta) < MINSIZE (window)) ||
3909 (!inpixels && (dim + delta) < MINCHARSIZE (window)))
3911 if (MINI_WINDOW_P (XWINDOW (window)))
3913 else if (!NILP (parent))
3915 Fdelete_window (window, Qnil);
3921 delta *= (widthflag ? defwidth : defheight);
3926 maxdelta = ((!NILP (parent))
3927 ? (*sizefun) (parent) - *sizep
3928 : ((!NILP (w->next))
3929 ? (*sizefun) (w->next) - MINSIZE (w->next)
3930 : ((!NILP (w->prev))
3931 ? (*sizefun) (w->prev) - MINSIZE (w->prev)
3932 /* This is a frame with only one window,
3933 a minibuffer-only or a minibufferless frame. */
3936 if (delta > maxdelta)
3937 /* This case traps trying to make the minibuffer
3938 the full frame, or make the only window aside from the
3939 minibuffer the full frame. */
3946 /* #### Chuck: is this correct? */
3947 if (*sizep + delta < MINSIZE (window))
3949 Fdelete_window (window);
3955 if (!NILP (w->next) &&
3956 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
3958 CURBEG (XWINDOW (w->next)) += delta;
3959 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
3960 (*setsizefun) (window, *sizep + delta, 0);
3962 else if (!NILP (w->prev) &&
3963 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
3965 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
3966 CURBEG (w) -= delta;
3967 (*setsizefun) (window, *sizep + delta, 0);
3972 int opht = (*sizefun) (parent);
3974 /* If trying to grow this window to or beyond size of the parent,
3975 make delta1 so big that, on shrinking back down,
3976 all the siblings end up with less than one line and are deleted. */
3977 if (opht <= *sizep + delta)
3978 delta1 = opht * opht * 2;
3979 /* Otherwise, make delta1 just right so that if we add delta1
3980 lines to this window and to the parent, and then shrink
3981 the parent back to its original size, the new proportional
3982 size of this window will increase by delta. */
3984 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
3986 /* Add delta1 lines or columns to this window, and to the parent,
3987 keeping things consistent while not affecting siblings. */
3988 CURSIZE (XWINDOW (parent)) = opht + delta1;
3989 (*setsizefun) (window, *sizep + delta1, 0);
3991 /* Squeeze out delta1 lines or columns from our parent,
3992 shrinking this window and siblings proportionately.
3993 This brings parent back to correct size.
3994 Delta1 was calculated so this makes this window the desired size,
3995 taking it all out of the siblings. */
3996 (*setsizefun) (parent, opht, 0);
3999 SET_LAST_MODIFIED (w, 0);
4000 SET_LAST_FACECHANGE (w);
4001 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
4002 /* overkill maybe, but better to be correct */
4003 MARK_FRAME_GUTTERS_CHANGED (f);
4013 /* Scroll contents of window WINDOW up N lines. If N < (top line height /
4014 average line height) then we just adjust the top clip. */
4016 window_scroll (Lisp_Object window, Lisp_Object n, int direction,
4017 Error_behavior errb)
4019 struct window *w = XWINDOW (window);
4020 struct buffer *b = XBUFFER (w->buffer);
4021 int selected = EQ (window, Fselected_window (Qnil));
4023 Lisp_Object point, tem;
4024 display_line_dynarr *dla;
4025 int fheight, fwidth, modeline = 0;
4026 struct display_line* dl;
4029 point = make_int (BUF_PT (b));
4032 Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
4034 if (pos < BUF_BEGV (b))
4036 else if (pos > BUF_ZV (b))
4039 point = make_int (pos);
4042 /* Always set force_start so that redisplay_window will run
4043 the window-scroll-functions. */
4046 /* #### When the fuck does this happen? I'm so glad that history has
4047 completely documented the behavior of the scrolling functions under
4048 all circumstances. */
4049 tem = Fpos_visible_in_window_p (point, window);
4052 Fvertical_motion (make_int (-window_char_height (w, 0) / 2),
4054 Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
4055 w->start_at_line_beg = beginning_of_line_p (b, XINT (point));
4056 WINDOW_TEXT_TOP_CLIP (w) = 0;
4057 MARK_WINDOWS_CHANGED (w);
4066 n = Fprefix_numeric_value (n);
4067 value = XINT (n) * direction;
4070 return; /* someone just made a pointless call */
4074 /* If the user didn't specify how far to scroll then we have to figure it
4075 out by ourselves. */
4076 if (NILP (n) || EQ (n, Qminus))
4078 /* Going forwards is easy. If that is what we are doing then just
4079 set value and the section which handles the user specifying a
4080 positive value will work. */
4083 value = window_displayed_height (w) - next_screen_context_lines;
4084 value = (value < 1 ? 1 : value);
4087 /* Going backwards is hard. We can't use the same loop used if the
4088 user specified a negative value because we care about
4089 next_screen_context_lines. In a variable height world you don't
4090 know how many lines above you can actually be displayed and still
4091 have the context lines appear. So we leave value set to 0 and add
4092 a separate section to deal with this. */
4096 if (direction == 1 && !value)
4101 /* Determine parameters to test for partial line scrolling with. */
4102 dla = window_display_lines (w, CURRENT_DISP);
4104 if (INTP (Vwindow_pixel_scroll_increment))
4105 fheight = XINT (Vwindow_pixel_scroll_increment);
4106 else if (!NILP (Vwindow_pixel_scroll_increment))
4107 default_face_height_and_width (window, &fheight, &fwidth);
4109 if (Dynarr_length (dla) >= 1)
4110 modeline = Dynarr_atp (dla, 0)->modeline;
4112 dl = Dynarr_atp (dla, modeline);
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 > 0)
4125 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4126 MARK_WINDOWS_CHANGED (w);
4131 Bufpos startp, old_start;
4133 if (WINDOW_TEXT_TOP_CLIP (w))
4135 WINDOW_TEXT_TOP_CLIP (w) = 0;
4136 MARK_WINDOWS_CHANGED (w);
4139 old_start = marker_position (w->start[CURRENT_DISP]);
4140 startp = vmotion (w, old_start, value, &vtarget);
4142 if (vtarget < value &&
4143 (w->window_end_pos[CURRENT_DISP] == -1
4144 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
4146 maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb);
4151 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4154 w->start_at_line_beg = beginning_of_line_p (b, startp);
4155 MARK_WINDOWS_CHANGED (w);
4157 if (!point_would_be_visible (w, startp, XINT (point)))
4160 BUF_SET_PT (b, startp);
4162 set_marker_restricted (w->pointm[CURRENT_DISP],
4171 /* Go for partial display line scrolling. This just means bumping
4172 the clip by a reasonable amount and redisplaying, everything else
4173 remains unchanged. */
4174 if (!NILP (Vwindow_pixel_scroll_increment)
4176 Dynarr_length (dla) >= (1 + modeline)
4178 (dl->ascent - dl->top_clip) - fheight * value <
4179 (dl->ascent + dl->descent - dl->clip)
4181 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0)
4183 WINDOW_TEXT_TOP_CLIP (w) += value * fheight;
4184 MARK_WINDOWS_CHANGED (w);
4189 Bufpos startp, old_start;
4191 if (WINDOW_TEXT_TOP_CLIP (w))
4193 WINDOW_TEXT_TOP_CLIP (w) = 0;
4194 MARK_WINDOWS_CHANGED (w);
4197 old_start = marker_position (w->start[CURRENT_DISP]);
4198 startp = vmotion (w, old_start, value, &vtarget);
4201 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4203 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4208 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4211 w->start_at_line_beg = beginning_of_line_p (b, startp);
4212 MARK_WINDOWS_CHANGED (w);
4214 /* #### Scroll back by less than a line. This code was
4215 originally for scrolling over large pixmaps and it
4216 loses when a line being *exposed* at the top of the
4217 window is bigger than the current one. However, for
4218 pixel based scrolling in general we can guess that
4219 the line we are going to display is probably the same
4220 size as the one we are on. In that instance we can
4221 have a reasonable stab at a suitable top clip. Fixing
4222 this properly is hard (and probably slow) as we would
4223 have to call redisplay to figure out the exposed line
4225 if (!NILP (Vwindow_pixel_scroll_increment)
4226 && Dynarr_length (dla) >= (1 + modeline)
4227 && dl->ascent + fheight * value > 0)
4229 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
4232 if (!point_would_be_visible (w, startp, XINT (point)))
4236 if (MINI_WINDOW_P (w))
4239 new_point = start_of_last_line (w, startp);
4242 BUF_SET_PT (b, new_point);
4244 set_marker_restricted (w->pointm[CURRENT_DISP],
4245 make_int (new_point),
4251 else /* value == 0 && direction == -1 */
4253 if (WINDOW_TEXT_TOP_CLIP (w))
4255 WINDOW_TEXT_TOP_CLIP (w) = 0;
4256 MARK_WINDOWS_CHANGED (w);
4258 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
4260 maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb);
4266 int movement = next_screen_context_lines - 1;
4267 Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
4268 Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
4270 start_with_point_on_display_line (w, bottom,
4271 -1 - (movement - vtarget));
4273 if (startp >= old_startp)
4274 startp = vmotion (w, old_startp, -1, NULL);
4276 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp),
4279 w->start_at_line_beg = beginning_of_line_p (b, startp);
4280 MARK_WINDOWS_CHANGED (w);
4282 if (!point_would_be_visible (w, startp, XINT (point)))
4284 Bufpos new_point = start_of_last_line (w, startp);
4287 BUF_SET_PT (b, new_point);
4289 set_marker_restricted (w->pointm[CURRENT_DISP],
4290 make_int (new_point),
4297 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /*
4298 Scroll text of current window upward N lines; or near full screen if no arg.
4299 A near full screen is `next-screen-context-lines' less than a full screen.
4300 Negative N means scroll downward.
4301 When calling from a program, supply an integer as argument or nil.
4302 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4303 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4308 window_scroll (Fselected_window (Qnil), n, 1, ERROR_ME);
4312 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /*
4313 Scroll text of current window downward N lines; or near full screen if no arg.
4314 A near full screen is `next-screen-context-lines' less than a full screen.
4315 Negative N means scroll upward.
4316 When calling from a program, supply a number as argument or nil.
4317 On attempt to scroll past end of buffer, `end-of-buffer' is signaled.
4318 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is
4323 window_scroll (Fselected_window (Qnil), n, -1, ERROR_ME);
4327 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /*
4328 Return the other window for "other window scroll" commands.
4329 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4330 specifies the window.
4331 If `other-window-scroll-buffer' is non-nil, a window
4332 showing that buffer is used.
4337 Lisp_Object selected_window = Fselected_window (Qnil);
4339 if (MINI_WINDOW_P (XWINDOW (selected_window))
4340 && !NILP (Vminibuffer_scroll_window))
4341 window = Vminibuffer_scroll_window;
4342 /* If buffer is specified, scroll that buffer. */
4343 else if (!NILP (Vother_window_scroll_buffer))
4345 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
4347 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4351 /* Nothing specified; look for a neighboring window on the same
4353 window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
4355 if (EQ (window, selected_window))
4356 /* That didn't get us anywhere; look for a window on another
4359 window = Fnext_window (window, Qnil, Qt, Qnil);
4360 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4361 && ! EQ (window, selected_window));
4364 CHECK_LIVE_WINDOW (window);
4366 if (EQ (window, selected_window))
4367 error ("There is no other window");
4372 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /*
4373 Scroll next window upward N lines; or near full frame if no arg.
4374 The next window is the one below the current one; or the one at the top
4375 if the current one is at the bottom. Negative N means scroll downward.
4376 When calling from a program, supply a number as argument or nil.
4378 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4379 specifies the window to scroll.
4380 If `other-window-scroll-buffer' is non-nil, scroll the window
4381 showing that buffer, popping the buffer up if necessary.
4385 window_scroll (Fother_window_for_scrolling (), n, 1, ERROR_ME);
4389 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /*
4390 Scroll selected window display N columns left.
4391 Default for N is window width minus 2.
4395 Lisp_Object window = Fselected_window (Qnil);
4396 struct window *w = XWINDOW (window);
4397 int count = (NILP (n) ?
4398 window_char_width (w, 0) - 2 :
4399 XINT (Fprefix_numeric_value (n)));
4401 return Fset_window_hscroll (window, make_int (w->hscroll + count));
4404 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /*
4405 Scroll selected window display N columns right.
4406 Default for N is window width minus 2.
4410 Lisp_Object window = Fselected_window (Qnil);
4411 struct window *w = XWINDOW (window);
4412 int count = (NILP (n) ?
4413 window_char_width (w, 0) - 2 :
4414 XINT (Fprefix_numeric_value (n)));
4416 return Fset_window_hscroll (window, make_int (w->hscroll - count));
4419 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /*
4420 Center point in WINDOW. With N, put point on line N.
4421 The desired position of point is always relative to the window.
4422 If WINDOW is nil, the selected window is used.
4426 struct window *w = decode_window (window);
4427 struct buffer *b = XBUFFER (w->buffer);
4428 Bufpos opoint = BUF_PT (b);
4432 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
4435 n = Fprefix_numeric_value (n);
4437 startp = start_with_point_on_display_line (w, opoint, XINT (n));
4440 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer);
4442 w->start_at_line_beg = beginning_of_line_p (b, startp);
4444 MARK_WINDOWS_CHANGED (w);
4448 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /*
4449 Position point relative to WINDOW.
4450 With no argument, position text at center of window.
4451 An argument specifies window line; zero means top of window,
4452 negative means relative to bottom of window.
4453 If WINDOW is nil, the selected window is used.
4460 Bufpos start, new_point;
4463 /* Don't use decode_window() because we need the new value of
4466 window = Fselected_window (Qnil);
4468 CHECK_LIVE_WINDOW (window);
4469 w = XWINDOW (window);
4470 b = XBUFFER (w->buffer);
4472 height = window_displayed_height (w);
4473 selected = EQ (window, Fselected_window (w->frame));
4479 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
4480 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
4482 new_point = point_at_center (w, CURRENT_DISP, 0, 0);
4485 BUF_SET_PT (b, new_point);
4487 Fset_window_point (window, make_int (new_point));
4489 retval = line_at_center (w, CURRENT_DISP, 0, 0);
4493 start = marker_position (w->start[CURRENT_DISP]);
4494 if (start < BUF_BEGV (b))
4495 start = BUF_BEGV (b);
4496 else if (start > BUF_ZV (b))
4500 new_point = BUF_PT (b);
4502 new_point = marker_position (w->pointm[CURRENT_DISP]);
4504 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4507 BUF_SET_PT (b, new_point);
4509 Fset_window_point (window, make_int (new_point));
4511 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b));
4514 return make_int (retval);
4518 /* #### Is this going to work right when at eob? */
4519 arg = Fprefix_numeric_value (arg);
4521 XSETINT (arg, XINT (arg) + height);
4524 start = marker_position (w->start[CURRENT_DISP]);
4525 if (start < BUF_BEGV (b) || start > BUF_ZV (b))
4528 new_point = BUF_PT (b);
4530 new_point = marker_position (w->pointm[CURRENT_DISP]);
4532 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
4535 BUF_SET_PT (b, new_point);
4537 Fset_window_point (window, make_int (new_point));
4539 Fset_marker (w->start[CURRENT_DISP], make_int (new_point),
4541 w->start_at_line_beg = beginning_of_line_p (b, new_point);
4547 BUF_SET_PT (b, start);
4549 Fset_window_point (window, make_int (start));
4553 return Fvertical_motion (arg, window, Qnil);
4557 new_point = vmotion (XWINDOW (window),
4558 marker_position (w->pointm[CURRENT_DISP]),
4560 Fset_window_point (window, make_int (new_point));
4561 return make_int (vpos);
4567 map_windows_1 (Lisp_Object window,
4568 int (*mapfun) (struct window *w, void *closure),
4571 for (; !NILP (window); window = XWINDOW (window)->next)
4574 struct window *w = XWINDOW (window);
4576 if (!NILP (w->vchild))
4577 retval = map_windows_1 (w->vchild, mapfun, closure);
4578 else if (!NILP (w->hchild))
4579 retval = map_windows_1 (w->hchild, mapfun, closure);
4581 retval = (mapfun) (w, closure);
4590 /* Map MAPFUN over the windows in F. CLOSURE is passed to each
4591 invocation of MAPFUN. If any invocation of MAPFUN returns
4592 non-zero, the mapping is halted. Otherwise, map_windows() maps
4593 over all windows in F.
4595 If MAPFUN creates or deletes windows, the behavior is undefined. */
4598 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
4602 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
4605 Lisp_Object frmcons, devcons, concons;
4607 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
4609 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))),
4621 modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
4624 w->shadow_thickness_changed = 1;
4625 MARK_WINDOWS_CHANGED (w);
4629 vertical_divider_changed_in_window (Lisp_Object specifier,
4633 MARK_WINDOWS_CHANGED (w);
4634 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w)));
4637 /* also used in scrollbar.c */
4639 some_window_value_changed (Lisp_Object specifier, struct window *w,
4642 MARK_WINDOWS_CHANGED (w);
4645 #ifdef MEMORY_USAGE_STATS
4651 #ifdef HAVE_SCROLLBARS
4655 int other_redisplay;
4660 compute_window_mirror_usage (struct window_mirror *mir,
4661 struct window_stats *stats,
4662 struct overhead_stats *ovstats)
4666 stats->other += malloced_storage_size (mir, sizeof (struct window_mirror),
4668 #ifdef HAVE_SCROLLBARS
4670 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
4673 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
4676 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
4679 #endif /* HAVE_SCROLLBARS */
4680 stats->other_redisplay +=
4681 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
4682 stats->other_redisplay +=
4683 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
4687 compute_window_usage (struct window *w, struct window_stats *stats,
4688 struct overhead_stats *ovstats)
4691 stats->other += malloced_storage_size (w, sizeof (struct window), ovstats);
4692 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
4693 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
4694 stats->line_start +=
4695 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
4696 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
4699 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
4700 Return stats about the memory usage of window WINDOW.
4701 The values returned are in the form of an alist of usage types and byte
4702 counts. The byte counts attempt to encompass all the memory used
4703 by the window (separate from the memory logically associated with a
4704 buffer or frame), including internal structures and any malloc()
4705 overhead associated with them. In practice, the byte counts are
4706 underestimated because certain memory usage is very hard to determine
4707 \(e.g. the amount of memory used inside the Xt library or inside the
4708 X server) and because there is other stuff that might logically
4709 be associated with a window, buffer, or frame (e.g. window configurations,
4710 glyphs) but should not obviously be included in the usage counts.
4712 Multiple slices of the total memory usage may be returned, separated
4713 by a nil. Each slice represents a particular view of the memory, a
4714 particular way of partitioning it into groups. Within a slice, there
4715 is no overlap between the groups of memory, and each slice collectively
4716 represents all the memory concerned.
4720 struct window_stats stats;
4721 struct overhead_stats ovstats;
4722 Lisp_Object val = Qnil;
4724 CHECK_WINDOW (window); /* dead windows should be allowed, no? */
4726 compute_window_usage (XWINDOW (window), &stats, &ovstats);
4728 val = acons (Qface_cache, make_int (stats.face), val);
4729 val = acons (Qglyph_cache, make_int (stats.glyph), val);
4730 #ifdef HAVE_SCROLLBARS
4731 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val);
4733 val = acons (Qline_start_cache, make_int (stats.line_start), val);
4734 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val);
4735 val = acons (Qother, make_int (stats.other), val);
4736 val = Fcons (Qnil, val);
4737 val = acons (Qactually_requested, make_int (ovstats.was_requested), val);
4738 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val);
4739 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val);
4741 return Fnreverse (val);
4744 #endif /* MEMORY_USAGE_STATS */
4747 /************************************************************************/
4748 /* Window configurations */
4749 /************************************************************************/
4751 /* #### This window configuration stuff has had serious bugs lurking in it
4752 for years; it would be a -huge- win if this was reimplemented in lisp.
4755 /* If you add anything to this structure make sure saved_window_equal
4759 Lisp_Object window; /* window */
4760 Lisp_Object buffer; /* buffer */
4761 Lisp_Object start; /* copied marker */
4762 Lisp_Object pointm; /* copied marker */
4763 Lisp_Object sb_point; /* copied marker */
4764 Lisp_Object mark; /* copied marker */
4770 Charcount modeline_hscroll;
4771 int parent_index; /* index into saved_windows */
4772 int prev_index; /* index into saved_windows */
4773 char start_at_line_beg; /* boolean */
4775 #define WINDOW_SLOT_DECLARATION
4776 #define WINDOW_SLOT(slot, compare) Lisp_Object slot
4777 #include "winslots.h"
4780 /* If you add anything to this structure make sure window_config_equal
4782 struct window_config
4784 struct lcrecord_header header;
4785 /* int frame_width; No longer needed, JV
4786 int frame_height; */
4788 Lisp_Object selected_frame;
4790 Lisp_Object current_window;
4791 Lisp_Object current_buffer;
4792 Lisp_Object minibuffer_scroll_window;
4793 Lisp_Object root_window;
4794 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */
4795 /* Record the values of window-min-width and window-min-height
4796 so that window sizes remain consistent with them. */
4797 int min_width, min_height;
4798 int saved_windows_count;
4799 /* Zero-sized arrays aren't ANSI C */
4800 struct saved_window saved_windows[1];
4803 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
4804 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
4805 #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
4806 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
4807 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
4810 mark_window_config (Lisp_Object obj)
4812 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4814 mark_object (config->current_window);
4815 mark_object (config->current_buffer);
4816 mark_object (config->minibuffer_scroll_window);
4817 mark_object (config->root_window);
4819 for (i = 0; i < config->saved_windows_count; i++)
4821 struct saved_window *s = SAVED_WINDOW_N (config, i);
4822 mark_object (s->window);
4823 mark_object (s->buffer);
4824 mark_object (s->start);
4825 mark_object (s->pointm);
4826 mark_object (s->sb_point);
4827 mark_object (s->mark);
4829 /* #### This looked like this. I do not see why specifier cached
4830 values should not be marked, as such specifiers as toolbars
4831 might have GC-able instances. Freed configs are not marked,
4832 aren't they? -- kkm */
4833 mark_object (s->dedicated);
4835 #define WINDOW_SLOT(slot, compare) mark_object (s->slot)
4836 #include "winslots.h"
4843 sizeof_window_config_for_n_windows (int n)
4845 return (sizeof (struct window_config) +
4846 /* n - 1 because zero-sized arrays aren't ANSI C */
4847 (n - 1) *sizeof (struct saved_window));
4851 sizeof_window_config (const void *h)
4853 const struct window_config *c = (const struct window_config *) h;
4854 return sizeof_window_config_for_n_windows (c->saved_windows_count);
4858 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
4860 struct window_config *config = XWINDOW_CONFIGURATION (obj);
4863 error ("printing unreadable object #<window-configuration 0x%x>",
4864 config->header.uid);
4865 write_c_string ("#<window-configuration ", printcharfun);
4866 sprintf (buf, "0x%x>", config->header.uid);
4867 write_c_string (buf, printcharfun);
4870 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
4871 window_configuration,
4873 print_window_config,
4874 0, 0, 0, 0, sizeof_window_config,
4875 struct window_config);
4878 /* Returns a boolean indicating whether the two saved windows are
4881 saved_window_equal (struct saved_window *win1, struct saved_window *win2)
4883 #define WINDOW_SLOT(slot, compare) \
4884 if (!compare (win1->slot, win2->slot)) \
4886 #include "winslots.h"
4889 EQ (win1->window, win2->window) &&
4890 EQ (win1->buffer, win2->buffer) &&
4891 internal_equal (win1->start, win2->start, 0) &&
4892 internal_equal (win1->pointm, win2->pointm, 0) &&
4893 internal_equal (win1->sb_point, win2->sb_point, 0) &&
4894 internal_equal (win1->mark, win2->mark, 0) &&
4895 win1->pixel_left == win2->pixel_left &&
4896 win1->pixel_top == win2->pixel_top &&
4897 win1->pixel_width == win2->pixel_width &&
4898 win1->pixel_height == win2->pixel_height &&
4899 win1->hscroll == win2->hscroll &&
4900 win1->modeline_hscroll == win2->modeline_hscroll &&
4901 win1->parent_index == win2->parent_index &&
4902 win1->prev_index == win2->prev_index &&
4903 win1->start_at_line_beg == win2->start_at_line_beg;
4906 /* Returns a boolean indicating whether the two given configurations
4909 window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
4911 struct window_config *fig1, *fig2;
4914 /* First check if they are truly the same. */
4915 if (EQ (conf1, conf2))
4918 fig1 = XWINDOW_CONFIGURATION (conf1);
4919 fig2 = XWINDOW_CONFIGURATION (conf2);
4921 if (!((fig1->saved_windows_count == fig2->saved_windows_count) &&
4922 EQ (fig1->current_window, fig2->current_window) &&
4923 EQ (fig1->current_buffer, fig2->current_buffer) &&
4924 EQ (fig1->root_window, fig2->root_window) &&
4925 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window)))
4927 fig1->frame_width == fig2->frame_width &&
4928 fig1->frame_height == fig2->frame_height)) */
4931 for (i = 0; i < fig1->saved_windows_count; i++)
4933 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
4934 SAVED_WINDOW_N (fig2, i)))
4941 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /*
4942 Return t if OBJECT is a window-configuration object.
4946 return WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil;
4950 mark_windows_in_use_closure (struct window *w, void *closure)
4952 int mark = *(int *)closure;
4953 w->config_mark = mark;
4958 mark_windows_in_use (struct frame *f, int mark)
4960 map_windows (f, mark_windows_in_use_closure, &mark);
4963 /* Lisp_Object return value so it can be used in record_unwind_protect() */
4965 free_window_configuration (Lisp_Object window_config)
4968 struct window_config *config = XWINDOW_CONFIGURATION (window_config);
4970 /* Free all the markers. It's not completely necessary that
4971 we do this (window configs sitting in a free list aren't
4972 marked normally so the markers wouldn't be marked anyway)
4973 but it's more efficient. */
4974 for (i = 0; i < config->saved_windows_count; i++)
4976 struct saved_window *p = SAVED_WINDOW_N (config, i);
4978 if (!NILP (p->pointm))
4980 free_marker (XMARKER (p->pointm));
4983 if (!NILP (p->start))
4985 free_marker (XMARKER (p->start));
4988 if (!NILP (p->sb_point))
4990 free_marker (XMARKER (p->sb_point));
4993 if (!NILP (p->mark))
4995 free_marker (XMARKER (p->mark));
5000 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list))
5001 free_managed_lcrecord (Vwindow_configuration_free_list
5002 [config->saved_windows_count - 1],
5008 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /*
5009 Set the configuration of windows and buffers as specified by CONFIGURATION.
5010 CONFIGURATION must be a value previously returned
5011 by `current-window-configuration' (which see).
5016 struct window_config *config;
5017 struct saved_window *p;
5018 Lisp_Object new_current_buffer;
5022 struct gcpro gcpro1;
5023 Lisp_Object old_window_config;
5024 /* int previous_frame_height;
5025 int previous_frame_width;*/
5026 int previous_pixel_top;
5027 int previous_pixel_height;
5028 int previous_pixel_left;
5029 int previous_pixel_width;
5030 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
5031 int real_font_height;
5032 int converted_minibuf_height,target_minibuf_height;
5033 int specpdl_count = specpdl_depth ();
5035 GCPRO1 (configuration);
5037 CHECK_WINDOW_CONFIGURATION (configuration);
5038 config = XWINDOW_CONFIGURATION (configuration);
5040 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
5043 /* Do not signal an error here if the frame was deleted. There are
5044 reasonable cases where we could get here with a deleted frame and
5045 just want to do close to nothing instead. */
5047 if (FRAME_LIVE_P (f))
5049 /* restore the frame characteristics */
5051 new_current_buffer = config->current_buffer;
5052 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5053 new_current_buffer = Qnil;
5056 * Assumed precondition: w->config_mark = 0 for all w
5057 * This procedure should ensure this is true by the time it exits
5058 * to ensure the precondition for future calls.
5060 * We use w->config_mark to know whether we're modifying a
5061 * window that is currently visible on the frame (#### we
5062 * should just be able to check whether the window is dead
5063 * or not, but this way is safer?). As we process each
5064 * window, we set its config_mark to 0. At the end, we
5065 * go through all the windows that used to be on the frame,
5066 * set each one's config_mark to 0 (to maintain the
5067 * assumed precondition) and delete each one that's no
5070 * #### Using a window-configuration to keep track of
5071 * the current windows is wasteful. All we need is the
5072 * list of windows, so we could just use a dynarr.
5074 old_window_config = Fcurrent_window_configuration (frame);
5076 /* If the new configuration is already equal to the old, then stop
5077 right here. This saves the work below and it also saves
5078 triggering a full redisplay of this window. This is a huge win
5079 when using the mouse since the mode motion code uses
5080 save-window-excursion extensively but will rarely cause the
5081 configuration to actually change. */
5082 if (window_config_equal (configuration, old_window_config))
5084 free_window_configuration (old_window_config);
5089 /* We can't quit or even check for quit because that may cause
5090 investigation of the frame state, which may crash if the frame is
5091 in an inconsistent state. */
5092 begin_dont_check_for_quit ();
5093 record_unwind_protect (free_window_configuration, old_window_config);
5095 mark_windows_in_use (f, 1);
5098 /* JV: This is bogus,
5099 First of all, the units are inconsistent. The frame sizes are measured
5100 in characters but the window sizes are stored in pixels. So if a
5101 font size change happened between saving and restoring, the
5102 frame "sizes" maybe equal but the windows still should be
5103 resized. This is tickled alot by the new "character size
5104 stays constant" policy in 21.0. It leads to very wierd
5105 glitches (and possibly craches when asserts are tickled).
5107 Just changing the units doens't help because changing the
5108 toolbar configuration can also change the pixel positions.
5109 Luckily there is a much simpler way of doing this, see below.
5111 previous_frame_width = FRAME_WIDTH (f);
5112 previous_frame_height = FRAME_HEIGHT (f);
5113 /* If the frame has been resized since this window configuration was
5114 made, we change the frame to the size specified in the
5115 configuration, restore the configuration, and then resize it
5116 back. We keep track of the prevailing height in these variables. */
5117 if (config->frame_height != FRAME_HEIGHT (f)
5118 || config->frame_width != FRAME_WIDTH (f))
5119 change_frame_size (f, config->frame_height, config->frame_width, 0);
5122 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
5123 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
5124 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
5125 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width;
5127 /* remember some properties of the minibuffer */
5129 default_face_height_and_width (frame, &real_font_height, 0);
5130 assert(real_font_height > 0);
5132 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5134 previous_minibuf_height
5135 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5136 previous_minibuf_top
5137 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top;
5138 previous_minibuf_width
5139 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width;
5143 previous_minibuf_height = 0;
5144 previous_minibuf_top = 0;
5145 previous_minibuf_width = 0;
5147 converted_minibuf_height =
5148 (previous_minibuf_height % real_font_height) == 0 ?
5149 - (previous_minibuf_height / real_font_height ) : /* lines */
5150 previous_minibuf_height; /* pixels */
5152 /* Temporarily avoid any problems with windows that are smaller
5153 than they are supposed to be. */
5154 window_min_height = 1;
5155 window_min_width = 1;
5157 /* OK, now restore all the windows in the window config.
5158 This may involve "undeleting" windows, since the
5159 windows in the window config may be deleted.
5161 for (k = 0; k < config->saved_windows_count; k++)
5163 p = SAVED_WINDOW_N (config, k);
5164 w = XWINDOW (p->window);
5167 /* The window might be dead. In this case, its redisplay
5168 structures were freed, so we need to reallocate them. */
5169 if (!w->face_cachels)
5171 w->face_cachels = Dynarr_new (face_cachel);
5172 reset_face_cachels (w);
5174 if (!w->glyph_cachels)
5175 w->glyph_cachels = Dynarr_new (glyph_cachel);
5176 if (!w->line_start_cache)
5177 w->line_start_cache = Dynarr_new (line_start_cache);
5180 if (p->parent_index >= 0)
5181 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
5185 if (p->prev_index >= 0)
5187 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
5189 /* This is true for a minibuffer-only frame. */
5190 if (!NILP (w->mini_p) && EQ (w->prev, p->window))
5193 XWINDOW (w->prev)->next = p->window;
5198 if (!NILP (w->parent))
5200 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
5202 XWINDOW (w->parent)->vchild = p->window;
5203 XWINDOW (w->parent)->hchild = Qnil;
5207 XWINDOW (w->parent)->hchild = p->window;
5208 XWINDOW (w->parent)->vchild = Qnil;
5212 if (!w->config_mark)
5214 /* #### This should be equivalent to the window previously
5215 having been dead. If we're brave, we'll put in an
5216 assertion to this effect. */
5217 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
5219 else /* if (!EQ (w->buffer, p->buffer)) */
5221 /* With the new redisplay we let it know that a change has
5222 been made and it will take care of the rest. If we don't
5223 tell it something has possibly changed it could lead to
5224 incorrect display. */
5225 MARK_WINDOWS_CHANGED (w);
5228 WINDOW_LEFT (w) = WINDOW_LEFT (p);
5229 WINDOW_TOP (w) = WINDOW_TOP (p);
5230 WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
5231 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
5232 w->hscroll = p->hscroll;
5233 w->modeline_hscroll = p->modeline_hscroll;
5234 w->line_cache_last_updated = Qzero;
5235 SET_LAST_MODIFIED (w, 1);
5236 SET_LAST_FACECHANGE (w);
5239 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
5240 #include "winslots.h"
5242 /* Reinstall the saved buffer and pointers into it. */
5243 if (NILP (p->buffer))
5244 w->buffer = p->buffer;
5247 if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5248 /* If saved buffer is alive, install it. */
5250 w->buffer = p->buffer;
5251 w->start_at_line_beg = p->start_at_line_beg;
5252 set_marker_restricted (w->start[CURRENT_DISP],
5253 Fmarker_position (p->start),
5255 set_marker_restricted (w->pointm[CURRENT_DISP],
5256 Fmarker_position (p->pointm),
5258 set_marker_restricted (w->sb_point,
5259 Fmarker_position (p->sb_point),
5261 Fset_marker (XBUFFER (w->buffer)->mark,
5262 Fmarker_position (p->mark), w->buffer);
5264 /* As documented in Fcurrent_window_configuration, don't
5265 save the location of point in the buffer which was current
5266 when the window configuration was recorded. */
5267 if (!EQ (p->buffer, new_current_buffer) &&
5268 XBUFFER (p->buffer) == current_buffer)
5269 Fgoto_char (w->pointm[CURRENT_DISP], Qnil);
5271 else if (NILP (w->buffer) ||
5272 !BUFFER_LIVE_P (XBUFFER (w->buffer)))
5273 /* Else if window's old buffer is dead too, get a live one. */
5275 /* #### The following line makes me nervous... */
5276 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
5277 w->buffer = Fget_buffer_create (QSscratch);
5278 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
5279 /* This will set the markers to beginning of visible
5281 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
5282 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
5284 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5285 w->start_at_line_beg = 1;
5288 /* Keeping window's old buffer; make sure the markers
5291 /* Set window markers at start of visible range. */
5292 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
5293 set_marker_restricted (w->start[CURRENT_DISP], Qzero,
5295 if (XMARKER (w->sb_point)->buffer == 0)
5296 set_marker_restricted (w->sb_point, Qzero, w->buffer);
5297 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
5298 set_marker_restricted (w->pointm[CURRENT_DISP],
5300 (BUF_PT (XBUFFER (w->buffer))),
5302 w->start_at_line_beg = 1;
5307 FRAME_ROOT_WINDOW (f) = config->root_window;
5308 /* Note that FSFmacs unilaterally calls Fselect_window() here, and
5309 then calls do_switch_frame() below to select the frame that was
5310 recorded in the window config as being selected.
5312 Instead, we don't ever change the selected frame, and either
5313 call Fselect_window() below if the window config's frame is
5314 currently selected, or just set the selected window of the
5315 window config's frame. */
5318 /* Set the frame height to the value it had before this function. */
5319 if (previous_frame_height != FRAME_HEIGHT (f)
5320 || previous_frame_width != FRAME_WIDTH (f))
5321 change_frame_size (f, previous_frame_height, previous_frame_width, 0);
5323 /* We just reset the size and position of the minibuffer, to its old
5324 value, which needn't be valid. So we do some magic to see which value
5325 to actually take. Then we set it.
5328 We take the old value if is in the same units but differs from the
5331 #### Now we get more cases correct then ever before, but
5332 are we treating all? For instance what if the frames minibuf window
5333 is no longer the same one?
5335 target_minibuf_height = previous_minibuf_height;
5336 if (converted_minibuf_height &&
5337 (converted_minibuf_height * config->minibuf_height) > 0 &&
5338 (converted_minibuf_height != config->minibuf_height))
5340 target_minibuf_height = config->minibuf_height < 0 ?
5341 - (config->minibuf_height * real_font_height) :
5342 config->minibuf_height;
5343 target_minibuf_height =
5344 max(target_minibuf_height,real_font_height);
5346 if (previous_minibuf_height)
5348 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top
5349 = previous_minibuf_top -
5350 (target_minibuf_height - previous_minibuf_height);
5351 set_window_pixheight (FRAME_MINIBUF_WINDOW (f),
5352 target_minibuf_height, 0);
5353 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
5354 previous_minibuf_width, 0);
5357 /* This is a better way to deal with frame resizing, etc.
5358 What we _actually_ want is for the old (just restored)
5360 into the place of the new one. So we just do that. Simple! */
5361 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top;
5362 /* Note that this function also updates the subwindow
5364 set_window_pixheight (FRAME_ROOT_WINDOW (f),
5365 previous_pixel_height -
5366 (target_minibuf_height - previous_minibuf_height), 0);
5367 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left;
5368 /* Note that this function also updates the subwindow
5370 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
5372 /* If restoring in the current frame make the window current,
5373 otherwise just update the frame selected_window slot to be
5374 the restored current_window. */
5375 if (f == selected_frame ())
5377 /* When using `pop-window-configuration', often the minibuffer
5378 ends up as the selected window even though it's not active ...
5379 I really don't know the cause of this, but it should never
5380 happen. This kludge should fix it.
5382 #### Find out why this is really going wrong. */
5383 if (!minibuf_level &&
5384 MINI_WINDOW_P (XWINDOW (config->current_window)))
5385 Fselect_window (Fnext_window (config->current_window,
5389 Fselect_window (config->current_window, Qnil);
5390 if (!NILP (new_current_buffer))
5391 Fset_buffer (new_current_buffer);
5393 Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
5396 set_frame_selected_window (f, config->current_window);
5399 old_window_config = Qnil; /* Warning suppression */
5401 /* Restore the minimum heights recorded in the configuration. */
5402 window_min_height = config->min_height;
5403 window_min_width = config->min_width;
5406 /* see above comment */
5407 /* Fselect_window will have made f the selected frame, so we
5408 reselect the proper frame here. Fhandle_switch_frame will change the
5409 selected window too, but that doesn't make the call to
5410 Fselect_window above totally superfluous; it still sets f's
5412 if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
5413 do_switch_frame (config->selected_frame, Qnil, 0);
5416 Vminibuffer_scroll_window = config->minibuffer_scroll_window;
5418 if (FRAME_LIVE_P (f))
5420 /* Do this before calling recompute_all_cached_specifiers_in_window()
5421 so that things like redisplay_redraw_cursor() won't abort due
5422 to no window mirror present. */
5423 f->mirror_dirty = 1;
5425 config = XWINDOW_CONFIGURATION (old_window_config);
5426 for (k = 0; k < config->saved_windows_count; k++)
5428 p = SAVED_WINDOW_N (config, k);
5429 w = XWINDOW (p->window);
5430 /* Remember, we set w->config_mark on all currently visible
5431 windows, and reset it on all newly visible windows.
5432 Any windows still marked need to be deleted. */
5435 mark_window_as_deleted (w);
5440 /* We just potentially changed the window's buffer and
5441 potentially turned a dead window into a live one,
5442 so we need to recompute the cached specifier values. */
5443 recompute_all_cached_specifiers_in_window (w);
5448 /* Now restore things, when everything else if OK. */
5450 unbind_to (specpdl_count, Qnil);
5457 /* Mark all subwindows of a window as deleted. The argument
5458 W is actually the subwindow tree of the window in question. */
5461 delete_all_subwindows (struct window *w)
5463 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next));
5464 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild));
5465 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild));
5467 mark_window_as_deleted (w);
5472 count_windows (struct window *window)
5475 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) +
5476 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) +
5477 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0);
5481 saved_window_index (Lisp_Object window, struct window_config *config, int lim)
5484 for (j = 0; j < lim; j++)
5486 if (EQ (SAVED_WINDOW_N (config, j)->window, window))
5490 return 0; /* suppress compiler warning */
5494 save_window_save (Lisp_Object window, struct window_config *config, int i)
5498 for (; !NILP (window); window = w->next)
5500 struct saved_window *p = SAVED_WINDOW_N (config, i);
5502 w = XWINDOW (window);
5505 p->buffer = w->buffer;
5506 WINDOW_LEFT (p) = WINDOW_LEFT (w);
5507 WINDOW_TOP (p) = WINDOW_TOP (w);
5508 WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
5509 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
5510 p->hscroll = w->hscroll;
5511 p->modeline_hscroll = w->modeline_hscroll;
5513 #define WINDOW_SLOT(slot, compare) p->slot = w->slot
5514 #include "winslots.h"
5516 if (!NILP (w->buffer))
5518 /* Save w's value of point in the window configuration.
5519 If w is the selected window, then get the value of point
5520 from the buffer; pointm is garbage in the selected window. */
5521 if (EQ (window, Fselected_window (Qnil)))
5523 p->pointm = noseeum_make_marker ();
5524 Fset_marker (p->pointm,
5525 make_int (BUF_PT (XBUFFER (w->buffer))),
5529 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil);
5531 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil);
5532 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil);
5533 p->start_at_line_beg = w->start_at_line_beg;
5535 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil);
5543 p->start_at_line_beg = 0;
5546 if (NILP (w->parent))
5547 p->parent_index = -1;
5549 p->parent_index = saved_window_index (w->parent, config, i);
5553 p->prev_index = saved_window_index (w->prev, config, i);
5554 if (!NILP (w->vchild))
5555 i = save_window_save (w->vchild, config, i);
5556 if (!NILP (w->hchild))
5557 i = save_window_save (w->hchild, config, i);
5564 /* Added to doc string:
5566 This also records the currently selected frame, and FRAME's focus
5567 redirection (see `redirect-frame-focus').
5572 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /*
5573 Return an object representing the current window configuration of FRAME.
5574 If FRAME is nil or omitted, use the selected frame.
5575 This describes the number of windows, their sizes and current buffers,
5576 and for each displayed buffer, where display starts, and the positions of
5577 point and mark. An exception is made for point in the current buffer:
5578 its value is -not- saved.
5583 struct frame *f = decode_frame (frame);
5584 struct window_config *config;
5585 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5587 int real_font_height;
5589 if (n_windows <= countof (Vwindow_configuration_free_list))
5590 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord
5591 (Vwindow_configuration_free_list
5594 /* More than ten windows; just allocate directly */
5595 config = (struct window_config *)
5596 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows),
5597 &lrecord_window_configuration);
5598 XSETWINDOW_CONFIGURATION (result, config);
5600 config->frame_width = FRAME_WIDTH (f);
5601 config->frame_height = FRAME_HEIGHT (f); */
5602 config->current_window = FRAME_SELECTED_WINDOW (f);
5603 XSETBUFFER (config->current_buffer, current_buffer);
5604 config->minibuffer_scroll_window = Vminibuffer_scroll_window;
5605 config->root_window = FRAME_ROOT_WINDOW (f);
5606 config->min_height = window_min_height;
5607 config->min_width = window_min_width;
5608 config->saved_windows_count = n_windows;
5609 save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
5611 /* save the minibuffer height using the heuristics from
5612 change_frame_size_1 */
5614 XSETFRAME (frame, f); /* frame could have been nil ! */
5615 default_face_height_and_width (frame, &real_font_height, 0);
5616 assert(real_font_height > 0);
5618 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
5619 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
5622 config->minibuf_height = (minibuf_height % real_font_height) == 0 ?
5623 - (minibuf_height / real_font_height ) : /* lines */
5624 minibuf_height; /* pixels */
5630 save_window_excursion_unwind (Lisp_Object window_config)
5632 Lisp_Object val = Fset_window_configuration (window_config);
5633 free_window_configuration (window_config);
5637 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /*
5638 Execute body, preserving window sizes and contents.
5639 Restores which buffer appears in which window, where display starts,
5640 as well as the current buffer.
5641 Does not restore the value of point in current buffer.
5645 /* This function can GC */
5647 int speccount = specpdl_depth ();
5649 record_unwind_protect (save_window_excursion_unwind,
5650 Fcurrent_window_configuration (Qnil));
5651 val = Fprogn (args);
5652 return unbind_to (speccount, val);
5655 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /*
5656 Return the horizontal pixel position of POS in window.
5657 Beginning of line is column 0. This is calculated using the redisplay
5658 display tables. If WINDOW is nil, the current window is assumed.
5659 If POS is nil, point is assumed. Note that POS must be visible for
5660 a non-nil result to be returned.
5664 struct window* w = decode_window (window);
5665 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
5667 struct display_line *dl = 0;
5668 struct display_block *db = 0;
5669 struct rune* rb = 0;
5670 int y = w->last_point_y[CURRENT_DISP];
5671 int x = w->last_point_x[CURRENT_DISP];
5673 if (MINI_WINDOW_P (w))
5676 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos))
5682 pos = Fwindow_point (window);
5687 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5692 for (i = first_line; i < Dynarr_length (dla); i++)
5694 dl = Dynarr_atp (dla, i);
5695 /* find the vertical location first */
5696 if (point >= dl->bufpos && point <= dl->end_bufpos)
5698 db = get_display_block_from_line (dl, TEXT);
5699 for (i = 0; i < Dynarr_length (db->runes); i++)
5701 rb = Dynarr_atp (db->runes, i);
5702 if (point <= rb->bufpos)
5714 /* optimised case */
5715 dl = Dynarr_atp (dla, y);
5716 db = get_display_block_from_line (dl, TEXT);
5718 if (x >= Dynarr_length (db->runes))
5721 rb = Dynarr_atp (db->runes, x);
5724 return make_int (rb->xpos - WINDOW_LEFT (w));
5729 /* This is short and simple in elisp, but... it was written to debug
5730 problems purely on the C side. That is where we need to call it so
5733 debug_print_window (Lisp_Object window, int level)
5736 Lisp_Object child = Fwindow_first_vchild (window);
5739 child = Fwindow_first_hchild (window);
5741 for (i = level; i > 0; i--)
5742 putc ('\t', stderr);
5744 fputs ("#<window", stderr);
5746 Lisp_Object buffer = XWINDOW (window)->buffer;
5747 if (!NILP (buffer) && BUFFERP (buffer))
5748 fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
5750 fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
5752 while (!NILP (child))
5754 debug_print_window (child, level + 1);
5755 child = Fwindow_next_child (child);
5759 void debug_print_windows (struct frame *f);
5761 debug_print_windows (struct frame *f)
5763 debug_print_window (f->root_window, 0);
5764 putc ('\n', stderr);
5766 #endif /* DEBUG_XEMACS */
5769 /************************************************************************/
5770 /* initialization */
5771 /************************************************************************/
5774 syms_of_window (void)
5776 INIT_LRECORD_IMPLEMENTATION (window);
5777 INIT_LRECORD_IMPLEMENTATION (window_configuration);
5779 defsymbol (&Qwindowp, "windowp");
5780 defsymbol (&Qwindow_live_p, "window-live-p");
5781 defsymbol (&Qwindow_configurationp, "window-configuration-p");
5782 defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook");
5783 defsymbol (&Qdisplay_buffer, "display-buffer");
5785 #ifdef MEMORY_USAGE_STATS
5786 defsymbol (&Qface_cache, "face-cache");
5787 defsymbol (&Qglyph_cache, "glyph-cache");
5788 defsymbol (&Qline_start_cache, "line-start-cache");
5789 #ifdef HAVE_SCROLLBARS
5790 defsymbol (&Qscrollbar_instances, "scrollbar-instances");
5792 defsymbol (&Qother_redisplay, "other-redisplay");
5793 /* Qother in general.c */
5796 DEFSUBR (Fselected_window);
5797 DEFSUBR (Flast_nonminibuf_window);
5798 DEFSUBR (Fminibuffer_window);
5799 DEFSUBR (Fwindow_minibuffer_p);
5801 DEFSUBR (Fwindow_live_p);
5802 DEFSUBR (Fwindow_first_hchild);
5803 DEFSUBR (Fwindow_first_vchild);
5804 DEFSUBR (Fwindow_next_child);
5805 DEFSUBR (Fwindow_previous_child);
5806 DEFSUBR (Fwindow_parent);
5807 DEFSUBR (Fwindow_lowest_p);
5808 DEFSUBR (Fwindow_truncated_p);
5809 DEFSUBR (Fwindow_highest_p);
5810 DEFSUBR (Fwindow_leftmost_p);
5811 DEFSUBR (Fwindow_rightmost_p);
5812 DEFSUBR (Fpos_visible_in_window_p);
5813 DEFSUBR (Fwindow_buffer);
5814 DEFSUBR (Fwindow_frame);
5815 DEFSUBR (Fwindow_height);
5816 DEFSUBR (Fwindow_displayed_height);
5817 DEFSUBR (Fwindow_width);
5818 DEFSUBR (Fwindow_pixel_height);
5819 DEFSUBR (Fwindow_pixel_width);
5820 DEFSUBR (Fwindow_text_area_pixel_height);
5821 DEFSUBR (Fwindow_displayed_text_pixel_height);
5822 DEFSUBR (Fwindow_text_area_pixel_width);
5823 DEFSUBR (Fwindow_hscroll);
5824 DEFSUBR (Fset_window_hscroll);
5825 DEFSUBR (Fmodeline_hscroll);
5826 DEFSUBR (Fset_modeline_hscroll);
5827 #if 0 /* bogus FSF crock */
5828 DEFSUBR (Fwindow_redisplay_end_trigger);
5829 DEFSUBR (Fset_window_redisplay_end_trigger);
5831 DEFSUBR (Fwindow_pixel_edges);
5832 DEFSUBR (Fwindow_text_area_pixel_edges);
5833 DEFSUBR (Fwindow_point);
5834 DEFSUBR (Fwindow_start);
5835 DEFSUBR (Fwindow_end);
5836 DEFSUBR (Fwindow_last_line_visible_height);
5837 DEFSUBR (Fset_window_point);
5838 DEFSUBR (Fset_window_start);
5839 DEFSUBR (Fwindow_dedicated_p);
5840 DEFSUBR (Fset_window_dedicated_p);
5841 DEFSUBR (Fnext_window);
5842 DEFSUBR (Fprevious_window);
5843 DEFSUBR (Fnext_vertical_window);
5844 DEFSUBR (Fother_window);
5845 DEFSUBR (Fget_lru_window);
5846 DEFSUBR (Fget_largest_window);
5847 DEFSUBR (Fget_buffer_window);
5848 DEFSUBR (Fwindow_left_margin_pixel_width);
5849 DEFSUBR (Fwindow_right_margin_pixel_width);
5850 DEFSUBR (Fdelete_other_windows);
5851 DEFSUBR (Fdelete_windows_on);
5852 DEFSUBR (Freplace_buffer_in_windows);
5853 DEFSUBR (Fdelete_window);
5854 DEFSUBR (Fset_window_buffer);
5855 DEFSUBR (Fselect_window);
5856 DEFSUBR (Fsplit_window);
5857 DEFSUBR (Fenlarge_window);
5858 DEFSUBR (Fenlarge_window_pixels);
5859 DEFSUBR (Fshrink_window);
5860 DEFSUBR (Fshrink_window_pixels);
5861 DEFSUBR (Fscroll_up);
5862 DEFSUBR (Fscroll_down);
5863 DEFSUBR (Fscroll_left);
5864 DEFSUBR (Fscroll_right);
5865 DEFSUBR (Fother_window_for_scrolling);
5866 DEFSUBR (Fscroll_other_window);
5867 DEFSUBR (Fcenter_to_window_line);
5868 DEFSUBR (Fmove_to_window_line);
5869 #ifdef MEMORY_USAGE_STATS
5870 DEFSUBR (Fwindow_memory_usage);
5872 DEFSUBR (Fwindow_configuration_p);
5873 DEFSUBR (Fset_window_configuration);
5874 DEFSUBR (Fcurrent_window_configuration);
5875 DEFSUBR (Fsave_window_excursion);
5876 DEFSUBR (Fcurrent_pixel_column);
5880 reinit_vars_of_window (void)
5883 /* Make sure all windows get marked */
5884 minibuf_window = Qnil;
5885 staticpro_nodump (&minibuf_window);
5887 for (i = 0; i < countof (Vwindow_configuration_free_list); i++)
5889 Vwindow_configuration_free_list[i] =
5890 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1),
5891 &lrecord_window_configuration);
5892 staticpro_nodump (&Vwindow_configuration_free_list[i]);
5897 vars_of_window (void)
5899 reinit_vars_of_window ();
5901 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
5902 *Non-nil means to scroll if point lands on a line which is clipped.
5904 scroll_on_clipped_lines = 1;
5906 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /*
5907 See `temp-buffer-show-function'.
5909 Vtemp_buffer_show_hook = Qnil;
5911 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /*
5912 Non-nil means call as function to display a help buffer.
5913 The function is called with one argument, the buffer to be displayed.
5914 Used by `with-output-to-temp-buffer'.
5915 If this function is used, then it must do the entire job of showing
5916 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
5918 Vtemp_buffer_show_function = Qnil;
5920 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /*
5921 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.
5923 Vminibuffer_scroll_window = Qnil;
5925 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /*
5926 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.
5928 Vother_window_scroll_buffer = Qnil;
5930 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /*
5931 *Number of pixels to scroll by per requested line.
5932 If nil then normal line scrolling occurs regardless of line height.
5933 If t then scrolling is done in increments equal to the height of the default face.
5935 Vwindow_pixel_scroll_increment = Qt;
5937 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /*
5938 *Number of lines of continuity when scrolling by screenfuls.
5940 next_screen_context_lines = 2;
5942 DEFVAR_INT ("window-min-height", &window_min_height /*
5943 *Delete any window less than this tall (including its modeline).
5945 window_min_height = 4;
5947 DEFVAR_INT ("window-min-width", &window_min_width /*
5948 *Delete any window less than this wide.
5950 window_min_width = 10;
5954 specifier_vars_of_window (void)
5956 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /*
5957 *How thick to draw 3D shadows around modelines.
5958 If this is set to 0, modelines will be the traditional 2D. Sizes above
5959 10 will be accepted but the maximum thickness that will be drawn is 10.
5960 This is a specifier; use `set-specifier' to change it.
5962 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
5963 /* The initial value for modeline-shadow-thickness is 2, but if the
5964 user removes all specifications we provide a fallback value of 0,
5965 which is probably what was expected. */
5966 set_specifier_fallback (Vmodeline_shadow_thickness,
5967 list1 (Fcons (Qnil, Qzero)));
5968 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
5970 set_specifier_caching (Vmodeline_shadow_thickness,
5971 offsetof (struct window, modeline_shadow_thickness),
5972 modeline_shadow_thickness_changed,
5975 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /*
5976 *Whether the modeline should be displayed.
5977 This is a specifier; use `set-specifier' to change it.
5979 Vhas_modeline_p = Fmake_specifier (Qboolean);
5980 set_specifier_fallback (Vhas_modeline_p,
5981 list1 (Fcons (Qnil, Qt)));
5982 set_specifier_caching (Vhas_modeline_p,
5983 offsetof (struct window, has_modeline_p),
5984 /* #### It's strange that we need a special
5985 flag to indicate that the shadow-thickness
5986 has changed, but not one to indicate that
5987 the modeline has been turned off or on. */
5988 some_window_value_changed,
5991 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p",
5992 &Vvertical_divider_always_visible_p /*
5993 *Should XEmacs always display vertical dividers between windows.
5995 When this is non-nil, vertical dividers are always shown, and are
5996 draggable. When it is nil, vertical dividers are shown only when
5997 there are no scrollbars in between windows, and are not draggable.
5999 This is a specifier; use `set-specifier' to change it.
6001 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean);
6002 set_specifier_fallback (Vvertical_divider_always_visible_p,
6003 list1 (Fcons (Qnil, Qt)));
6004 set_specifier_caching (Vvertical_divider_always_visible_p,
6005 offsetof (struct window,
6006 vertical_divider_always_visible_p),
6007 vertical_divider_changed_in_window,
6010 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /*
6011 *How thick to draw 3D shadows around vertical dividers.
6012 This is a specifier; use `set-specifier' to change it.
6014 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger);
6015 set_specifier_fallback (Vvertical_divider_shadow_thickness,
6016 list1 (Fcons (Qnil, Qzero)));
6017 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
6019 set_specifier_caching (Vvertical_divider_shadow_thickness,
6020 offsetof (struct window,
6021 vertical_divider_shadow_thickness),
6022 vertical_divider_changed_in_window,
6024 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
6025 *The width of the vertical dividers, not including shadows.
6027 For TTY windows, divider line is always one character wide. When
6028 instance of this specifier is zero in a TTY window, no divider is
6029 drawn at all between windows. When non-zero, a one character wide
6030 divider is displayed.
6032 This is a specifier; use `set-specifier' to change it.
6035 Vvertical_divider_line_width = Fmake_specifier (Qnatnum);
6037 Lisp_Object fb = Qnil;
6039 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb);
6041 #ifdef HAVE_X_WINDOWS
6042 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb);
6044 #ifdef HAVE_MS_WINDOWS
6045 /* #### This should be made magic and made to obey system settings */
6046 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb);
6048 set_specifier_fallback (Vvertical_divider_line_width, fb);
6050 set_specifier_caching (Vvertical_divider_line_width,
6051 offsetof (struct window,
6052 vertical_divider_line_width),
6053 vertical_divider_changed_in_window,
6056 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /*
6057 *How much space to leave around the vertical dividers.
6059 In TTY windows, spacing is always zero, and the value of this
6060 specifier is ignored.
6062 This is a specifier; use `set-specifier' to change it.
6064 Vvertical_divider_spacing = Fmake_specifier (Qnatnum);
6066 Lisp_Object fb = Qnil;
6068 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
6070 #ifdef HAVE_X_WINDOWS
6071 /* #### 3D dividers look great on MS Windows with spacing = 0.
6072 Should not the same value be the fallback under X? - kkm */
6073 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb);
6075 #ifdef HAVE_MS_WINDOWS
6076 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb);
6078 set_specifier_fallback (Vvertical_divider_spacing, fb);
6080 set_specifier_caching (Vvertical_divider_spacing,
6081 offsetof (struct window, vertical_divider_spacing),
6082 vertical_divider_changed_in_window,