X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/022039da8ea1166498c507dda4944afd9c49c9fe..2fa611b72ba67066496866dd76688e9db5257ac6:/src/window.c diff --git a/src/window.c b/src/window.c index 875d777027..f9084e6c05 100644 --- a/src/window.c +++ b/src/window.c @@ -55,7 +55,8 @@ along with GNU Emacs. If not, see . */ Lisp_Object Qwindowp, Qwindow_live_p; static Lisp_Object Qwindow_valid_p; -static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer; +static Lisp_Object Qwindow_configuration_p; +static Lisp_Object Qrecord_window_buffer; static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer; static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window; static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically; @@ -65,14 +66,11 @@ static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of; static int displayed_window_lines (struct window *); static int count_windows (struct window *); static int get_leaf_windows (struct window *, struct window **, int); -static void window_scroll (Lisp_Object, EMACS_INT, int, int); -static void window_scroll_pixel_based (Lisp_Object, int, int, int); -static void window_scroll_line_based (Lisp_Object, int, int, int); -static int freeze_window_start (struct window *, void *); +static void window_scroll (Lisp_Object, EMACS_INT, bool, int); +static void window_scroll_pixel_based (Lisp_Object, int, bool, int); +static void window_scroll_line_based (Lisp_Object, int, bool, int); static Lisp_Object window_list (void); static int add_window_to_list (struct window *, void *); -static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object, - Lisp_Object); static Lisp_Object next_window (Lisp_Object, Lisp_Object, Lisp_Object, int); static void decode_next_window_args (Lisp_Object *, Lisp_Object *, @@ -130,6 +128,12 @@ static int window_scroll_pixel_based_preserve_y; static EMACS_INT window_scroll_preserve_hpos; static EMACS_INT window_scroll_preserve_vpos; +static void +CHECK_WINDOW_CONFIGURATION (Lisp_Object x) +{ + CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x); +} + /* These setters are used only in this file, so they can be private. */ static void wset_combination_limit (struct window *w, Lisp_Object val) @@ -147,21 +151,6 @@ wset_display_table (struct window *w, Lisp_Object val) w->display_table = val; } static void -wset_hchild (struct window *w, Lisp_Object val) -{ - w->hchild = val; -} -static void -wset_left_fringe_width (struct window *w, Lisp_Object val) -{ - w->left_fringe_width = val; -} -static void -wset_left_margin_cols (struct window *w, Lisp_Object val) -{ - w->left_margin_cols = val; -} -static void wset_new_normal (struct window *w, Lisp_Object val) { w->new_normal = val; @@ -192,16 +181,6 @@ wset_pointm (struct window *w, Lisp_Object val) w->pointm = val; } static void -wset_right_fringe_width (struct window *w, Lisp_Object val) -{ - w->right_fringe_width = val; -} -static void -wset_right_margin_cols (struct window *w, Lisp_Object val) -{ - w->right_margin_cols = val; -} -static void wset_scroll_bar_width (struct window *w, Lisp_Object val) { w->scroll_bar_width = val; @@ -217,11 +196,6 @@ wset_temslot (struct window *w, Lisp_Object val) w->temslot = val; } static void -wset_vchild (struct window *w, Lisp_Object val) -{ - w->vchild = val; -} -static void wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val) { w->vertical_scroll_bar_type = val; @@ -231,6 +205,29 @@ wset_window_parameters (struct window *w, Lisp_Object val) { w->window_parameters = val; } +static void +wset_combination (struct window *w, bool horflag, Lisp_Object val) +{ + /* Since leaf windows never becomes non-leaf, there should + be no buffer and markers in start and pointm fields of W. */ + eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm)); + w->contents = val; + /* When an internal window is deleted and VAL is nil, HORFLAG + is meaningless. */ + if (!NILP (val)) + w->horizontal = horflag; +} + +/* Nonzero if leaf window W doesn't reflect the actual state + of displayed buffer due to its text or overlays change. */ + +bool +window_outdated (struct window *w) +{ + struct buffer *b = XBUFFER (w->contents); + return (w->last_modified < BUF_MODIFF (b) + || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b)); +} struct window * decode_live_window (register Lisp_Object window) @@ -275,9 +272,9 @@ static void adjust_window_count (struct window *w, int arg) { eassert (eabs (arg) == 1); - if (BUFFERP (w->buffer)) + if (BUFFERP (w->contents)) { - struct buffer *b = XBUFFER (w->buffer); + struct buffer *b = XBUFFER (w->contents); if (b->base_buffer) b = b->base_buffer; @@ -296,7 +293,11 @@ void wset_buffer (struct window *w, Lisp_Object val) { adjust_window_count (w, -1); - w->buffer = val; + if (BUFFERP (val)) + /* Make sure that we do not assign the buffer + to an internal window. */ + eassert (MARKERP (w->start) && MARKERP (w->pointm)); + w->contents = val; adjust_window_count (w, 1); } @@ -394,15 +395,8 @@ the first window of that frame. */) window = XFRAME (frame_or_window)->root_window; } - while (NILP (XWINDOW (window)->buffer)) - { - if (! NILP (XWINDOW (window)->hchild)) - window = XWINDOW (window)->hchild; - else if (! NILP (XWINDOW (window)->vchild)) - window = XWINDOW (window)->vchild; - else - emacs_abort (); - } + while (WINDOWP (XWINDOW (window)->contents)) + window = XWINDOW (window)->contents; return window; } @@ -484,19 +478,15 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap) CHECK_LIVE_WINDOW (window); w = XWINDOW (window); - w->frozen_window_start_p = 0; - - if (NILP (norecord)) - { - w->use_time = ++window_select_count; - record_buffer (w->buffer); - } /* Make the selected window's buffer current. */ - Fset_buffer (w->buffer); + Fset_buffer (w->contents); if (EQ (window, selected_window) && !inhibit_point_swap) - return window; + /* `switch-to-buffer' uses (select-window (selected-window)) as a "clever" + way to call record_buffer from Elisp, so it's important that we call + record_buffer before returning here. */ + goto record_and_return; sf = SELECTED_FRAME (); if (XFRAME (WINDOW_FRAME (w)) != sf) @@ -515,9 +505,19 @@ select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap) fset_selected_window (sf, window); select_window_1 (window, inhibit_point_swap); - - bset_last_selected_window (XBUFFER (w->buffer), window); + bset_last_selected_window (XBUFFER (w->contents), window); windows_or_buffers_changed++; + + record_and_return: + /* record_buffer can run QUIT, so make sure it is run only after we have + re-established the invariant between selected_window and selected_frame, + otherwise the temporary broken invariant might "escape" (bug#14161). */ + if (NILP (norecord)) + { + w->use_time = ++window_select_count; + record_buffer (w->contents); + } + return window; } @@ -533,10 +533,10 @@ select_window_1 (Lisp_Object window, bool inhibit_point_swap) if (!inhibit_point_swap) { struct window *ow = XWINDOW (selected_window); - if (! NILP (ow->buffer)) - set_marker_both (ow->pointm, ow->buffer, - BUF_PT (XBUFFER (ow->buffer)), - BUF_PT_BYTE (XBUFFER (ow->buffer))); + if (BUFFERP (ow->contents)) + set_marker_both (ow->pointm, ow->contents, + BUF_PT (XBUFFER (ow->contents)), + BUF_PT_BYTE (XBUFFER (ow->contents))); } selected_window = window; @@ -581,7 +581,8 @@ If WINDOW is omitted or nil, it defaults to the selected window. Return nil for an internal window or a deleted window. */) (Lisp_Object window) { - return decode_any_window (window)->buffer; + struct window *w = decode_any_window (window); + return WINDOW_LEAF_P (w) ? w->contents : Qnil; } DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0, @@ -601,7 +602,8 @@ Return nil if WINDOW is an internal window whose children form a horizontal combination. */) (Lisp_Object window) { - return decode_valid_window (window)->vchild; + struct window *w = decode_valid_window (window); + return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil; } DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0, @@ -612,7 +614,8 @@ Return nil if WINDOW is an internal window whose children form a vertical combination. */) (Lisp_Object window) { - return decode_valid_window (window)->hchild; + struct window *w = decode_valid_window (window); + return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil; } DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0, @@ -645,9 +648,9 @@ WINDOW are never \(re-)combined with WINDOW's siblings. */) CHECK_VALID_WINDOW (window); w = XWINDOW (window); - if (!NILP (w->buffer)) + if (WINDOW_LEAF_P (w)) error ("Combination limit is meaningful for internal windows only"); - return XWINDOW (window)->combination_limit; + return w->combination_limit; } DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0, @@ -663,7 +666,7 @@ future use. */) CHECK_VALID_WINDOW (window); w = XWINDOW (window); - if (!NILP (w->buffer)) + if (WINDOW_LEAF_P (w)) error ("Combination limit is meaningful for internal windows only"); wset_combination_limit (w, limit); return limit; @@ -860,7 +863,7 @@ set_window_hscroll (struct window *w, EMACS_INT hscroll) /* Prevent redisplay shortcuts when changing the hscroll. */ if (w->hscroll != new_hscroll) - XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1; + XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1; w->hscroll = new_hscroll; return make_number (new_hscroll); @@ -1339,7 +1342,7 @@ struct check_window_data static int check_window_containing (struct window *w, void *user_data) { - struct check_window_data *cw = (struct check_window_data *) user_data; + struct check_window_data *cw = user_data; enum window_part found; int continue_p = 1; @@ -1441,7 +1444,7 @@ correct to return the top-level value of `point', outside of any register struct window *w = decode_live_window (window); if (w == XWINDOW (selected_window)) - return make_number (BUF_PT (XBUFFER (w->buffer))); + return make_number (BUF_PT (XBUFFER (w->contents))); else return Fmarker_position (w->pointm); } @@ -1483,12 +1486,16 @@ if it isn't already recorded. */) Lisp_Object buf; struct buffer *b; - buf = w->buffer; + buf = w->contents; CHECK_BUFFER (buf); b = XBUFFER (buf); if (! NILP (update) - && (windows_or_buffers_changed || !w->window_end_valid) + && (windows_or_buffers_changed + || !w->window_end_valid + || b->clip_changed + || b->prevent_redisplay_optimizations_p + || window_outdated (w)) && !noninteractive) { struct text_pos startp; @@ -1546,7 +1553,7 @@ Return POS. */) if (w == XWINDOW (selected_window)) { - if (XBUFFER (w->buffer) == current_buffer) + if (XBUFFER (w->contents) == current_buffer) Fgoto_char (pos); else { @@ -1554,14 +1561,14 @@ Return POS. */) /* ... but here we want to catch type error before buffer change. */ CHECK_NUMBER_COERCE_MARKER (pos); - set_buffer_internal (XBUFFER (w->buffer)); + set_buffer_internal (XBUFFER (w->contents)); Fgoto_char (pos); set_buffer_internal (old_buffer); } } else { - set_marker_restricted (w->pointm, pos, w->buffer); + set_marker_restricted (w->pointm, pos, w->contents); /* We have to make sure that redisplay updates the window to show the new value of point. */ ++windows_or_buffers_changed; @@ -1579,15 +1586,14 @@ overriding motion of point in order to display at this exact start. */) { register struct window *w = decode_live_window (window); - set_marker_restricted (w->start, pos, w->buffer); + set_marker_restricted (w->start, pos, w->contents); /* This is not right, but much easier than doing what is right. */ w->start_at_line_beg = 0; if (NILP (noforce)) w->force_start = 1; w->update_mode_line = 1; - w->last_modified = 0; - w->last_overlay_modified = 0; - if (!EQ (window, selected_window)) + if (w != XWINDOW (selected_window)) + /* Enforce full redisplay. FIXME: make it more selective. */ windows_or_buffers_changed++; return pos; @@ -1606,12 +1612,13 @@ specifies the position of the last visible glyph in WINDOW. POS defaults to point in WINDOW; WINDOW defaults to the selected window. If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil, -return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]), +the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]), where X and Y are the pixel coordinates relative to the top left corner of the window. The remaining elements are omitted if the character after POS is fully visible; otherwise, RTOP and RBOT are the number of pixels -off-window at the top and bottom of the row, ROWH is the height of the -display row, and VPOS is the row number (0-based) containing POS. */) +off-window at the top and bottom of the screen line ("row") containing +POS, ROWH is the visible height of that row, and VPOS is the row number +\(zero-based). */) (Lisp_Object pos, Lisp_Object window, Lisp_Object partially) { register struct window *w; @@ -1623,7 +1630,7 @@ display row, and VPOS is the row number (0-based) containing POS. */) int x, y; w = decode_live_window (window); - buf = XBUFFER (w->buffer); + buf = XBUFFER (w->contents); SET_TEXT_POS_FROM_MARKER (top, w->start); if (EQ (pos, Qt)) @@ -1692,15 +1699,15 @@ Return nil if window display is not up-to-date. In that case, use if (noninteractive || w->pseudo_window_p) return Qnil; - CHECK_BUFFER (w->buffer); - b = XBUFFER (w->buffer); + CHECK_BUFFER (w->contents); + b = XBUFFER (w->contents); /* Fail if current matrix is not up-to-date. */ if (!w->window_end_valid - || current_buffer->clip_changed - || current_buffer->prevent_redisplay_optimizations_p - || w->last_modified < BUF_MODIFF (b) - || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b)) + || windows_or_buffers_changed + || b->clip_changed + || b->prevent_redisplay_optimizations_p + || window_outdated (w)) return Qnil; if (NILP (line)) @@ -1919,9 +1926,9 @@ window_display_table (struct window *w) if (DISP_TABLE_P (w->display_table)) dp = XCHAR_TABLE (w->display_table); - else if (BUFFERP (w->buffer)) + else if (BUFFERP (w->contents)) { - struct buffer *b = XBUFFER (w->buffer); + struct buffer *b = XBUFFER (w->contents); if (DISP_TABLE_P (BVAR (b, display_table))) dp = XCHAR_TABLE (BVAR (b, display_table)); @@ -1946,17 +1953,14 @@ WINDOW must be a live window and defaults to the selected one. */) static void unshow_buffer (register struct window *w) { - Lisp_Object buf; - struct buffer *b; + Lisp_Object buf = w->contents; + struct buffer *b = XBUFFER (buf); - buf = w->buffer; - b = XBUFFER (buf); - if (b != XMARKER (w->pointm)->buffer) - emacs_abort (); + eassert (b == XMARKER (w->pointm)->buffer); #if 0 if (w == XWINDOW (selected_window) - || ! EQ (buf, XWINDOW (selected_window)->buffer)) + || ! EQ (buf, XWINDOW (selected_window)->contents)) /* Do this except when the selected window's buffer is being removed from some other window. */ #endif @@ -1972,14 +1976,14 @@ unshow_buffer (register struct window *w) /* Point in the selected window's buffer is actually stored in that buffer, and the window's pointm isn't used. So don't clobber point in that buffer. */ - if (! EQ (buf, XWINDOW (selected_window)->buffer) + if (! EQ (buf, XWINDOW (selected_window)->contents) /* Don't clobber point in current buffer either (this could be useful in connection with bug#12208). && XBUFFER (buf) != current_buffer */ /* This line helps to fix Horsley's testbug.el bug. */ && !(WINDOWP (BVAR (b, last_selected_window)) && w != XWINDOW (BVAR (b, last_selected_window)) - && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer))) + && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents))) temp_set_point_both (b, clip_to_bounds (BUF_BEGV (b), marker_position (w->pointm), @@ -2029,7 +2033,6 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag) wset_window_end_vpos (n, make_number (0)); wset_window_end_pos (n, make_number (0)); n->window_end_valid = 0; - n->frozen_window_start_p = 0; } tem = o->next; @@ -2044,13 +2047,8 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag) tem = o->parent; wset_parent (n, tem); - if (!NILP (tem)) - { - if (EQ (XWINDOW (tem)->vchild, old)) - wset_vchild (XWINDOW (tem), new); - if (EQ (XWINDOW (tem)->hchild, old)) - wset_hchild (XWINDOW (tem), new); - } + if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old)) + wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new); } /* If window WINDOW and its parent window are iso-combined, merge @@ -2069,22 +2067,19 @@ recombine_windows (Lisp_Object window) if (!NILP (parent) && NILP (w->combination_limit)) { p = XWINDOW (parent); - if (((!NILP (p->vchild) && !NILP (w->vchild)) - || (!NILP (p->hchild) && !NILP (w->hchild)))) + if (WINDOWP (p->contents) && WINDOWP (w->contents) + && p->horizontal == w->horizontal) /* WINDOW and PARENT are both either a vertical or a horizontal combination. */ { - horflag = NILP (w->vchild); - child = horflag ? w->hchild : w->vchild; + horflag = WINDOW_HORIZONTAL_COMBINATION_P (w); + child = w->contents; c = XWINDOW (child); /* Splice WINDOW's children into its parent's children and assign new normal sizes. */ if (NILP (w->prev)) - if (horflag) - wset_hchild (p, child); - else - wset_vchild (p, child); + wset_combination (p, horflag, child); else { wset_prev (c, w->prev); @@ -2122,8 +2117,7 @@ recombine_windows (Lisp_Object window) } /* WINDOW can be deleted now. */ - wset_vchild (w, Qnil); - wset_hchild (w, Qnil); + wset_combination (w, 0, Qnil); } } } @@ -2147,7 +2141,7 @@ delete_deletable_window (Lisp_Object window) static int add_window_to_list (struct window *w, void *user_data) { - Lisp_Object *list = (Lisp_Object *) user_data; + Lisp_Object *list = user_data; Lisp_Object window; XSETWINDOW (window, w); *list = Fcons (window, *list); @@ -2202,14 +2196,15 @@ window_list (void) a window means search the frame that window belongs to, a frame means consider windows on that frame, only. */ -static int -candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames) +static bool +candidate_window_p (Lisp_Object window, Lisp_Object owindow, + Lisp_Object minibuf, Lisp_Object all_frames) { struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); - int candidate_p = 1; + bool candidate_p = 1; - if (!BUFFERP (w->buffer)) + if (!BUFFERP (w->contents)) candidate_p = 0; else if (MINI_WINDOW_P (w) && (EQ (minibuf, Qlambda) @@ -2549,7 +2544,7 @@ enum window_loop GET_BUFFER_WINDOW, /* Arg is buffer */ REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */ REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */ - CHECK_ALL_WINDOWS + CHECK_ALL_WINDOWS /* Arg is ignored */ }; static Lisp_Object @@ -2613,7 +2608,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame switch (type) { case GET_BUFFER_WINDOW: - if (EQ (w->buffer, obj) + if (EQ (w->contents, obj) /* Don't find any minibuffer window except the one that is currently in use. */ && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1)) @@ -2637,25 +2632,25 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame case REPLACE_BUFFER_IN_WINDOWS_SAFELY: /* We could simply check whether the buffer shown by window is live, and show another buffer in case it isn't. */ - if (EQ (w->buffer, obj)) + if (EQ (w->contents, obj)) { /* Undedicate WINDOW. */ wset_dedicated (w, Qnil); /* Make WINDOW show the buffer returned by other_buffer_safely, don't run any hooks. */ set_window_buffer - (window, other_buffer_safely (w->buffer), 0, 0); + (window, other_buffer_safely (w->contents), 0, 0); /* If WINDOW is the selected window, make its buffer current. But do so only if the window shows the current buffer (Bug#6454). */ if (EQ (window, selected_window) - && XBUFFER (w->buffer) == current_buffer) - Fset_buffer (w->buffer); + && XBUFFER (w->contents) == current_buffer) + Fset_buffer (w->contents); } break; case REDISPLAY_BUFFER_WINDOWS: - if (EQ (w->buffer, obj)) + if (EQ (w->contents, obj)) { mark_window_display_accurate (window, 0); w->update_mode_line = 1; @@ -2665,11 +2660,20 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame } break; - /* Check for a window that has a killed buffer. */ + /* Check for a leaf window that has a killed buffer + or broken markers. */ case CHECK_ALL_WINDOWS: - if (! NILP (w->buffer) - && !BUFFER_LIVE_P (XBUFFER (w->buffer))) - emacs_abort (); + if (BUFFERP (w->contents)) + { + struct buffer *b = XBUFFER (w->contents); + + if (!BUFFER_LIVE_P (b)) + emacs_abort (); + if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b) + emacs_abort (); + if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b) + emacs_abort (); + } break; case WINDOW_LOOP_UNUSED: @@ -2786,7 +2790,7 @@ window-start value is reasonable when this function is called. */) else if (MINI_WINDOW_P (w)) /* && top > 0) */ error ("Can't expand minibuffer to full frame"); - if (!NILP (w->buffer)) + if (BUFFERP (w->contents)) { startpos = marker_position (w->start); startbyte = marker_byte_position (w->start); @@ -2858,7 +2862,7 @@ window-start value is reasonable when this function is called. */) FRAME_WINDOW_SIZES_CHANGED (f) = 1; resize_failed = 0; - if (NILP (w->buffer)) + if (!WINDOW_LEAF_P (w)) { /* Resize child windows vertically. */ XSETINT (delta, r->total_lines - w->total_lines); @@ -2917,28 +2921,21 @@ window-start value is reasonable when this function is called. */) sibling = w->next; s = XWINDOW (sibling); wset_prev (s, Qnil); - if (!NILP (XWINDOW (w->parent)->vchild)) - wset_vchild (XWINDOW (w->parent), sibling); - else - wset_hchild (XWINDOW (w->parent), sibling); + wset_combination (XWINDOW (w->parent), + XWINDOW (w->parent)->horizontal, sibling); } /* Delete ROOT and all child windows of ROOT. */ - if (!NILP (r->vchild)) - { - delete_all_child_windows (r->vchild); - wset_vchild (r, Qnil); - } - else if (!NILP (r->hchild)) + if (WINDOWP (r->contents)) { - delete_all_child_windows (r->hchild); - wset_hchild (r, Qnil); + delete_all_child_windows (r->contents); + wset_combination (r, 0, Qnil); } replace_window (root, window, 1); - /* This must become SWINDOW anyway ....... */ - if (!NILP (w->buffer) && !resize_failed) + /* This must become SWINDOW anyway ....... */ + if (BUFFERP (w->contents) && !resize_failed) { /* Try to minimize scrolling, by setting the window start to the point will cause the text at the old window start to be at the @@ -2947,18 +2944,18 @@ window-start value is reasonable when this function is called. */) when the display is not current, due to typeahead). */ new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))); if (new_top != top - && startpos >= BUF_BEGV (XBUFFER (w->buffer)) - && startpos <= BUF_ZV (XBUFFER (w->buffer))) + && startpos >= BUF_BEGV (XBUFFER (w->contents)) + && startpos <= BUF_ZV (XBUFFER (w->contents))) { struct position pos; struct buffer *obuf = current_buffer; - Fset_buffer (w->buffer); + Fset_buffer (w->contents); /* This computation used to temporarily move point, but that can have unwanted side effects due to text properties. */ pos = *vmotion (startpos, startbyte, -top, w); - set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos); + set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos); w->window_end_valid = 0; w->start_at_line_beg = (pos.bytepos == BEGV_BYTE || FETCH_BYTE (pos.bytepos - 1) == '\n'); @@ -3007,7 +3004,7 @@ replace_buffer_in_windows_safely (Lisp_Object buffer) minimum allowable size. */ void -check_frame_size (FRAME_PTR frame, int *rows, int *cols) +check_frame_size (struct frame *frame, int *rows, int *cols) { /* For height, we have to see: how many windows the frame has at minimum (one or two), @@ -3051,15 +3048,12 @@ adjust_window_margins (struct window *w) if (WINDOW_RIGHT_MARGIN_COLS (w) > 0) { if (WINDOW_LEFT_MARGIN_COLS (w) > 0) - { - wset_left_margin_cols (w, make_number (margin_cols / 2)); - wset_right_margin_cols (w, make_number (margin_cols / 2)); - } + w->left_margin_cols = w->right_margin_cols = margin_cols / 2; else - wset_right_margin_cols (w, make_number (margin_cols)); + w->right_margin_cols = margin_cols; } else - wset_left_margin_cols (w, make_number (margin_cols)); + w->left_margin_cols = margin_cols; return 1; } @@ -3073,18 +3067,18 @@ run_funs (Lisp_Object funs) call0 (XCAR (funs)); } -static Lisp_Object +static void select_window_norecord (Lisp_Object window) { - return WINDOW_LIVE_P (window) - ? Fselect_window (window, Qt) : selected_window; + if (WINDOW_LIVE_P (window)) + Fselect_window (window, Qt); } -static Lisp_Object +static void select_frame_norecord (Lisp_Object frame) { - return FRAME_LIVE_P (XFRAME (frame)) - ? Fselect_frame (frame, Qt) : selected_frame; + if (FRAME_LIVE_P (XFRAME (frame))) + Fselect_frame (frame, Qt); } void @@ -3107,7 +3101,7 @@ run_window_configuration_change_hook (struct frame *f) if (SELECTED_FRAME () != f) { - record_unwind_protect (select_frame_norecord, Fselected_frame ()); + record_unwind_protect (select_frame_norecord, selected_frame); select_frame_norecord (frame); } @@ -3122,7 +3116,7 @@ run_window_configuration_change_hook (struct frame *f) buffer))) { ptrdiff_t inner_count = SPECPDL_INDEX (); - record_unwind_protect (select_window_norecord, Fselected_window ()); + record_unwind_protect (select_window_norecord, selected_window); select_window_norecord (window); run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook, buffer)); @@ -3158,7 +3152,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, struct window *w = XWINDOW (window); struct buffer *b = XBUFFER (buffer); ptrdiff_t count = SPECPDL_INDEX (); - int samebuf = EQ (buffer, w->buffer); + int samebuf = EQ (buffer, w->contents); wset_buffer (w, buffer); @@ -3194,8 +3188,6 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, buffer); w->start_at_line_beg = 0; w->force_start = 0; - w->last_modified = 0; - w->last_overlay_modified = 0; } /* Maybe we could move this into the `if' but it's not obviously safe and I doubt it's worth the trouble. */ @@ -3218,11 +3210,11 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, /* This may call adjust_window_margins three times, so temporarily disable window margins. */ - Lisp_Object save_left = w->left_margin_cols; - Lisp_Object save_right = w->right_margin_cols; + int save_left = w->left_margin_cols; + int save_right = w->right_margin_cols; - wset_left_margin_cols (w, Qnil); - wset_right_margin_cols (w, Qnil); + w->left_margin_cols = 0; + w->right_margin_cols = 0; Fset_window_fringes (window, BVAR (b, left_fringe_width), BVAR (b, right_fringe_width), @@ -3232,8 +3224,8 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, BVAR (b, scroll_bar_width), BVAR (b, vertical_scroll_bar_type), Qnil); - wset_left_margin_cols (w, save_left); - wset_right_margin_cols (w, save_right); + w->left_margin_cols = save_left; + w->right_margin_cols = save_right; Fset_window_margins (window, BVAR (b, left_margin_cols), BVAR (b, right_margin_cols)); @@ -3277,7 +3269,7 @@ This function runs `window-scroll-functions' before running if (!BUFFER_LIVE_P (XBUFFER (buffer))) error ("Attempt to display deleted buffer"); - tem = w->buffer; + tem = w->contents; if (NILP (tem)) error ("Window is deleted"); else @@ -3330,8 +3322,8 @@ displaying that buffer. */) struct window *w = XWINDOW (object); mark_window_display_accurate (object, 0); w->update_mode_line = 1; - if (BUFFERP (w->buffer)) - XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1; + if (BUFFERP (w->contents)) + XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1; ++update_mode_lines; return Qt; } @@ -3397,10 +3389,10 @@ temp_output_buffer_show (register Lisp_Object buf) Note: Both Fselect_window and select_window_norecord may set-buffer to the buffer displayed in the window, so we need to save the current buffer. --stef */ - record_unwind_protect (Fset_buffer, prev_buffer); + record_unwind_protect (restore_buffer, prev_buffer); record_unwind_protect (select_window_norecord, prev_window); Fselect_window (window, Qt); - Fset_buffer (w->buffer); + Fset_buffer (w->contents); Frun_hooks (1, &Qtemp_buffer_show_hook); unbind_to (count, Qnil); } @@ -3421,7 +3413,7 @@ make_parent_window (Lisp_Object window, bool horflag) memcpy ((char *) p + sizeof (struct vectorlike_header), (char *) o + sizeof (struct vectorlike_header), word_size * VECSIZE (struct window)); - /* P's buffer slot may change from nil to a buffer. */ + /* P's buffer slot may change from nil to a buffer... */ adjust_window_count (p, 1); XSETWINDOW (parent, p); @@ -3430,12 +3422,11 @@ make_parent_window (Lisp_Object window, bool horflag) wset_next (o, Qnil); wset_prev (o, Qnil); wset_parent (o, parent); - - wset_hchild (p, horflag ? window : Qnil); - wset_vchild (p, horflag ? Qnil : window); + /* ...but now P becomes an internal window. */ wset_start (p, Qnil); wset_pointm (p, Qnil); wset_buffer (p, Qnil); + wset_combination (p, horflag, window); wset_combination_limit (p, Qnil); wset_window_parameters (p, Qnil); } @@ -3467,6 +3458,7 @@ make_window (void) /* Initialize non-Lisp data. Note that allocate_window zeroes out all non-Lisp data, so do it only for slots which should not be zero. */ w->nrows_scale_factor = w->ncols_scale_factor = 1; + w->left_fringe_width = w->right_fringe_width = -1; w->phys_cursor_type = -1; w->phys_cursor_width = -1; w->column_number_displayed = -1; @@ -3524,10 +3516,10 @@ window_resize_check (struct window *w, bool horflag) { struct window *c; - if (!NILP (w->vchild)) + if (WINDOW_VERTICAL_COMBINATION_P (w)) /* W is a vertical combination. */ { - c = XWINDOW (w->vchild); + c = XWINDOW (w->contents); if (horflag) /* All child windows of W must have the same width as W. */ { @@ -3555,10 +3547,10 @@ window_resize_check (struct window *w, bool horflag) return (sum_of_sizes == XINT (w->new_total)); } } - else if (!NILP (w->hchild)) + else if (WINDOW_HORIZONTAL_COMBINATION_P (w)) /* W is a horizontal combination. */ { - c = XWINDOW (w->hchild); + c = XWINDOW (w->contents); if (horflag) /* The sum of the widths of the child windows of W must equal W's width. */ @@ -3625,10 +3617,10 @@ window_resize_apply (struct window *w, bool horflag) pos = w->top_line; } - if (!NILP (w->vchild)) + if (WINDOW_VERTICAL_COMBINATION_P (w)) /* W is a vertical combination. */ { - c = XWINDOW (w->vchild); + c = XWINDOW (w->contents); while (c) { if (horflag) @@ -3641,10 +3633,10 @@ window_resize_apply (struct window *w, bool horflag) c = NILP (c->next) ? 0 : XWINDOW (c->next); } } - else if (!NILP (w->hchild)) + else if (WINDOW_HORIZONTAL_COMBINATION_P (w)) /* W is a horizontal combination. */ { - c = XWINDOW (w->hchild); + c = XWINDOW (w->contents); while (c) { if (horflag) @@ -3657,10 +3649,6 @@ window_resize_apply (struct window *w, bool horflag) c = NILP (c->next) ? 0 : XWINDOW (c->next); } } - - /* Clear out some redisplay caches. */ - w->last_modified = 0; - w->last_overlay_modified = 0; } @@ -3727,7 +3715,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag) ? 1 : 0))); r->top_line = FRAME_TOP_MARGIN (f); - if (NILP (r->vchild) && NILP (r->hchild)) + if (WINDOW_LEAF_P (r)) /* For a leaf root window just set the size. */ if (horflag) r->total_cols = new_size; @@ -3842,9 +3830,9 @@ set correctly. See the code of `split-window' for how this is done. */) combination_limit = EQ (Vwindow_combination_limit, Qt) || NILP (o->parent) - || NILP (horflag - ? (XWINDOW (o->parent)->hchild) - : (XWINDOW (o->parent)->vchild)); + || (horflag + ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent)) + : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))); /* We need a live reference window to initialize some parameters. */ if (WINDOW_LIVE_P (old)) @@ -3914,17 +3902,12 @@ set correctly. See the code of `split-window' for how this is done. */) n = XWINDOW (new); wset_frame (n, frame); wset_parent (n, o->parent); - wset_vchild (n, Qnil); - wset_hchild (n, Qnil); if (EQ (side, Qabove) || EQ (side, Qleft)) { wset_prev (n, o->prev); if (NILP (n->prev)) - if (horflag) - wset_hchild (p, new); - else - wset_vchild (p, new); + wset_combination (p, horflag, new); else wset_next (XWINDOW (n->prev), new); wset_next (n, old); @@ -3943,10 +3926,10 @@ set correctly. See the code of `split-window' for how this is done. */) memset (&n->last_cursor, 0, sizeof n->last_cursor); /* Get special geometry settings from reference window. */ - wset_left_margin_cols (n, r->left_margin_cols); - wset_right_margin_cols (n, r->right_margin_cols); - wset_left_fringe_width (n, r->left_fringe_width); - wset_right_fringe_width (n, r->right_fringe_width); + n->left_margin_cols = r->left_margin_cols; + n->right_margin_cols = r->right_margin_cols; + n->left_fringe_width = r->left_fringe_width; + n->right_fringe_width = r->right_fringe_width; n->fringes_outside_margins = r->fringes_outside_margins; wset_scroll_bar_width (n, r->scroll_bar_width); wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type); @@ -3973,7 +3956,7 @@ set correctly. See the code of `split-window' for how this is done. */) adjust_glyphs (f); /* Set buffer of NEW to buffer of reference window. Don't run any hooks. */ - set_window_buffer (new, r->buffer, 0, 1); + set_window_buffer (new, r->contents, 0, 1); unblock_input (); /* Maybe we should run the scroll functions in Elisp (which already @@ -3995,13 +3978,11 @@ Signal an error when WINDOW is the only window on its frame. */) register Lisp_Object parent, sibling, frame, root; struct window *w, *p, *s, *r; struct frame *f; - bool horflag; - int before_sibling = 0; + bool horflag, before_sibling = 0; w = decode_any_window (window); XSETWINDOW (window, w); - if (NILP (w->buffer) - && NILP (w->hchild) && NILP (w->vchild)) + if (NILP (w->contents)) /* It's a no-op to delete an already deleted window. */ return Qnil; @@ -4015,7 +3996,7 @@ Signal an error when WINDOW is the only window on its frame. */) error ("Attempt to delete sole window of parent"); p = XWINDOW (parent); - horflag = NILP (p->vchild); + horflag = WINDOW_HORIZONTAL_COMBINATION_P (p); frame = WINDOW_FRAME (w); f = XFRAME (frame); @@ -4033,10 +4014,7 @@ Signal an error when WINDOW is the only window on its frame. */) sibling = w->next; s = XWINDOW (sibling); wset_prev (s, Qnil); - if (horflag) - wset_hchild (p, sibling); - else - wset_vchild (p, sibling); + wset_combination (p, horflag, sibling); } else /* Get SIBLING above (on the left of) WINDOW. */ @@ -4075,17 +4053,12 @@ Signal an error when WINDOW is the only window on its frame. */) wset_next (w, Qnil); /* Don't delete w->next too. */ free_window_matrices (w); - if (!NILP (w->vchild)) + if (WINDOWP (w->contents)) { - delete_all_child_windows (w->vchild); - wset_vchild (w, Qnil); + delete_all_child_windows (w->contents); + wset_combination (w, 0, Qnil); } - else if (!NILP (w->hchild)) - { - delete_all_child_windows (w->hchild); - wset_hchild (w, Qnil); - } - else if (!NILP (w->buffer)) + else { unshow_buffer (w); unchain_marker (XMARKER (w->pointm)); @@ -4104,8 +4077,7 @@ Signal an error when WINDOW is the only window on its frame. */) wset_normal_cols (s, p->normal_cols); wset_normal_lines (s, p->normal_lines); /* Mark PARENT as deleted. */ - wset_vchild (p, Qnil); - wset_hchild (p, Qnil); + wset_combination (p, 0, Qnil); /* Try to merge SIBLING into its new parent. */ recombine_windows (sibling); } @@ -4153,10 +4125,7 @@ Signal an error when WINDOW is the only window on its frame. */) if (before_sibling) { wset_prev (s, window); - if (horflag) - wset_hchild (p, window); - else - wset_vchild (p, window); + wset_combination (p, horflag, window); } else { @@ -4198,9 +4167,7 @@ grow_mini_window (struct window *w, int delta) /* Grow the mini-window. */ w->top_line = r->top_line + r->total_lines; w->total_lines -= XINT (value); - w->last_modified = 0; - w->last_overlay_modified = 0; - + /* Enforce full redisplay. FIXME: make it more selective. */ windows_or_buffers_changed++; adjust_glyphs (f); unblock_input (); @@ -4234,10 +4201,7 @@ shrink_mini_window (struct window *w) /* Shrink the mini-window. */ w->top_line = r->top_line + r->total_lines; w->total_lines = 1; - - w->last_modified = 0; - w->last_overlay_modified = 0; - + /* Enforce full redisplay. FIXME: make it more selective. */ windows_or_buffers_changed++; adjust_glyphs (f); unblock_input (); @@ -4299,10 +4263,8 @@ mark_window_cursors_off (struct window *w) { while (w) { - if (!NILP (w->hchild)) - mark_window_cursors_off (XWINDOW (w->hchild)); - else if (!NILP (w->vchild)) - mark_window_cursors_off (XWINDOW (w->vchild)); + if (WINDOWP (w->contents)) + mark_window_cursors_off (XWINDOW (w->contents)); else w->phys_cursor_on_p = 0; @@ -4321,8 +4283,7 @@ window_internal_height (struct window *w) if (!MINI_WINDOW_P (w)) { if (!NILP (w->parent) - || !NILP (w->vchild) - || !NILP (w->hchild) + || WINDOWP (w->contents) || !NILP (w->next) || !NILP (w->prev) || WINDOW_WANTS_MODELINE_P (w)) @@ -4347,7 +4308,7 @@ window_internal_height (struct window *w) respectively. */ static void -window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror) +window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror) { immediate_quit = 1; n = clip_to_bounds (INT_MIN, n, INT_MAX); @@ -4368,7 +4329,7 @@ window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror) descriptions. */ static void -window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) +window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror) { struct it it; struct window *w = XWINDOW (window); @@ -4378,6 +4339,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) int vscrolled = 0; int x, y, rtop, rbot, rowh, vpos; void *itdata = NULL; + int window_total_lines; + int frame_line_height = default_line_pixel_height (w); SET_TEXT_POS_FROM_MARKER (start, w->start); /* Scrolling a minibuffer window via scroll bar when the echo area @@ -4421,7 +4384,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) if (rtop || rbot) /* partially visible */ { int px; - int dy = WINDOW_FRAME_LINE_HEIGHT (w); + int dy = frame_line_height; if (whole) dy = max ((window_box_height (w) - next_screen_context_lines * dy), @@ -4461,11 +4424,9 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) else spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV); set_marker_restricted (w->start, make_number (spos), - w->buffer); + w->contents); w->start_at_line_beg = 1; w->update_mode_line = 1; - w->last_modified = 0; - w->last_overlay_modified = 0; /* Set force_start so that redisplay_window will run the window-scroll-functions. */ w->force_start = 1; @@ -4507,7 +4468,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) if (whole) { ptrdiff_t start_pos = IT_CHARPOS (it); - int dy = WINDOW_FRAME_LINE_HEIGHT (w); + int dy = frame_line_height; dy = max ((window_box_height (w) - next_screen_context_lines * dy), dy) * n; @@ -4585,7 +4546,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) /* If control gets here, then we vscrolled. */ - XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1; + XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1; /* Don't try to change the window start below. */ vscrolled = 1; @@ -4605,13 +4566,11 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) } /* Set the window start, and set up the window for redisplay. */ - set_marker_restricted_both (w->start, w->buffer, IT_CHARPOS (it), + set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it), IT_BYTEPOS (it)); bytepos = marker_byte_position (w->start); w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n'); w->update_mode_line = 1; - w->last_modified = 0; - w->last_overlay_modified = 0; /* Set force_start so that redisplay_window will run the window-scroll-functions. */ w->force_start = 1; @@ -4624,10 +4583,12 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) /* Move PT out of scroll margins. This code wants current_y to be zero at the window start position even if there is a header line. */ + window_total_lines + = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height; this_scroll_margin = max (0, scroll_margin); this_scroll_margin - = min (this_scroll_margin, w->total_lines / 4); - this_scroll_margin *= FRAME_LINE_HEIGHT (it.f); + = min (this_scroll_margin, window_total_lines / 4); + this_scroll_margin *= frame_line_height; if (n > 0) { @@ -4732,7 +4693,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror) See the comment of window_scroll for parameter descriptions. */ static void -window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) +window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror) { register struct window *w = XWINDOW (window); /* Fvertical_motion enters redisplay, which can trigger @@ -4744,7 +4705,7 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) register ptrdiff_t pos, pos_byte; register int ht = window_internal_height (w); register Lisp_Object tem; - int lose; + bool lose; Lisp_Object bolp; ptrdiff_t startpos = marker_position (w->start); ptrdiff_t startbyte = marker_byte_position (w->start); @@ -4805,11 +4766,9 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) int this_scroll_margin = max (0, min (scroll_margin, w->total_lines / 4)); - set_marker_restricted_both (w->start, w->buffer, pos, pos_byte); + set_marker_restricted_both (w->start, w->contents, pos, pos_byte); w->start_at_line_beg = !NILP (bolp); w->update_mode_line = 1; - w->last_modified = 0; - w->last_overlay_modified = 0; /* Set force_start so that redisplay_window will run the window-scroll-functions. */ w->force_start = 1; @@ -4899,10 +4858,10 @@ scroll_command (Lisp_Object n, int direction) /* If selected window's buffer isn't current, make it current for the moment. But don't screw up if window_scroll gets an error. */ - if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer) + if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer) { record_unwind_protect (save_excursion_restore, save_excursion_save ()); - Fset_buffer (XWINDOW (selected_window)->buffer); + Fset_buffer (XWINDOW (selected_window)->contents); /* Make redisplay consider other windows than just selected_window. */ ++windows_or_buffers_changed; @@ -5017,7 +4976,7 @@ specifies the window to scroll. This takes precedence over record_unwind_protect (save_excursion_restore, save_excursion_save ()); ++windows_or_buffers_changed; - Fset_buffer (w->buffer); + Fset_buffer (w->contents); SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm)); if (NILP (arg)) @@ -5111,10 +5070,10 @@ displayed_window_lines (struct window *w) int bottom_y; void *itdata = NULL; - if (XBUFFER (w->buffer) != current_buffer) + if (XBUFFER (w->contents) != current_buffer) { old_buffer = current_buffer; - set_buffer_internal (XBUFFER (w->buffer)); + set_buffer_internal (XBUFFER (w->contents)); } else old_buffer = NULL; @@ -5176,9 +5135,9 @@ and redisplay normally--don't erase and redraw the frame. */) (register Lisp_Object arg) { struct window *w = XWINDOW (selected_window); - struct buffer *buf = XBUFFER (w->buffer); + struct buffer *buf = XBUFFER (w->contents); struct buffer *obuf = current_buffer; - int center_p = 0; + bool center_p = 0; ptrdiff_t charpos, bytepos; EMACS_INT iarg IF_LINT (= 0); int this_scroll_margin; @@ -5342,7 +5301,7 @@ and redisplay normally--don't erase and redraw the frame. */) } /* Set the new window start. */ - set_marker_both (w->start, w->buffer, charpos, bytepos); + set_marker_both (w->start, w->contents, charpos, bytepos); w->window_end_valid = 0; w->optional_new_start = 1; @@ -5386,9 +5345,8 @@ zero means top of window, negative means relative to bottom of window. */) int this_scroll_margin; #endif - if (!(BUFFERP (w->buffer) - && XBUFFER (w->buffer) == current_buffer)) - /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer + if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer)) + /* This test is needed to make sure PT/PT_BYTE make sense in w->contents when passed below to set_marker_both. */ error ("move-to-window-line called from unrelated buffer"); @@ -5398,7 +5356,7 @@ zero means top of window, negative means relative to bottom of window. */) { int height = window_internal_height (w); Fvertical_motion (make_number (- (height / 2)), window); - set_marker_both (w->start, w->buffer, PT, PT_BYTE); + set_marker_both (w->start, w->contents, PT, PT_BYTE); w->start_at_line_beg = !NILP (Fbolp ()); w->force_start = 1; } @@ -5524,7 +5482,7 @@ the return value is nil. Otherwise the value is t. */) struct Lisp_Vector *saved_windows; Lisp_Object new_current_buffer; Lisp_Object frame; - FRAME_PTR f; + struct frame *f; ptrdiff_t old_point = -1; CHECK_WINDOW_CONFIGURATION (configuration); @@ -5548,9 +5506,9 @@ the return value is nil. Otherwise the value is t. */) window-point of the final-selected-window to the window-point of the current-selected-window. So we have to be careful which point of the current-buffer we copy into old_point. */ - if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer) + if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer) && WINDOWP (selected_window) - && EQ (XWINDOW (selected_window)->buffer, new_current_buffer) + && EQ (XWINDOW (selected_window)->contents, new_current_buffer) && !EQ (selected_window, data->current_window)) old_point = marker_position (XWINDOW (data->current_window)->pointm); else @@ -5564,7 +5522,7 @@ the return value is nil. Otherwise the value is t. */) So if possible we want this arbitrary choice of "which point" to be the one from the to-be-selected-window so as to prevent this window's cursor from being copied from another window. */ - if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer) + if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer) /* If current_window = selected_window, its point is in BUF_PT. */ && !EQ (selected_window, data->current_window)) old_point = marker_position (XWINDOW (data->current_window)->pointm); @@ -5606,8 +5564,8 @@ the return value is nil. Otherwise the value is t. */) p = SAVED_WINDOW_N (saved_windows, k); window = p->window; w = XWINDOW (window); - if (!NILP (w->buffer) - && !EQ (w->buffer, p->buffer) + if (BUFFERP (w->contents) + && !EQ (w->contents, p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) /* If a window we restore gets another buffer, record the window's old buffer. */ @@ -5640,13 +5598,13 @@ the return value is nil. Otherwise the value is t. */) window holds garbage.) We do this now, before restoring the window contents, and prevent it from being done later on when we select a new window. */ - if (! NILP (XWINDOW (selected_window)->buffer)) + if (! NILP (XWINDOW (selected_window)->contents)) { w = XWINDOW (selected_window); set_marker_both (w->pointm, - w->buffer, - BUF_PT (XBUFFER (w->buffer)), - BUF_PT_BYTE (XBUFFER (w->buffer))); + w->contents, + BUF_PT (XBUFFER (w->contents)), + BUF_PT_BYTE (XBUFFER (w->contents))); } windows_or_buffers_changed++; @@ -5693,18 +5651,10 @@ the return value is nil. Otherwise the value is t. */) { wset_prev (w, Qnil); if (!NILP (w->parent)) - { - if (XINT (p->total_cols) == XWINDOW (w->parent)->total_cols) - { - wset_vchild (XWINDOW (w->parent), p->window); - wset_hchild (XWINDOW (w->parent), Qnil); - } - else - { - wset_hchild (XWINDOW (w->parent), p->window); - wset_vchild (XWINDOW (w->parent), Qnil); - } - } + wset_combination (XWINDOW (w->parent), + (XINT (p->total_cols) + != XWINDOW (w->parent)->total_cols), + p->window); } /* If we squirreled away the buffer, restore it now. */ @@ -5719,10 +5669,10 @@ the return value is nil. Otherwise the value is t. */) w->hscroll = XFASTINT (p->hscroll); w->min_hscroll = XFASTINT (p->min_hscroll); wset_display_table (w, p->display_table); - wset_left_margin_cols (w, p->left_margin_cols); - wset_right_margin_cols (w, p->right_margin_cols); - wset_left_fringe_width (w, p->left_fringe_width); - wset_right_fringe_width (w, p->right_fringe_width); + w->left_margin_cols = XINT (p->left_margin_cols); + w->right_margin_cols = XINT (p->right_margin_cols); + w->left_fringe_width = XINT (p->left_fringe_width); + w->right_fringe_width = XINT (p->right_fringe_width); w->fringes_outside_margins = !NILP (p->fringes_outside_margins); wset_scroll_bar_width (w, p->scroll_bar_width); wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type); @@ -5750,23 +5700,16 @@ the return value is nil. Otherwise the value is t. */) } } - w->last_modified = 0; - w->last_overlay_modified = 0; - - /* Reinstall the saved buffer and pointers into it. */ - if (NILP (p->buffer)) - /* An internal window. */ - wset_buffer (w, p->buffer); - else if (BUFFER_LIVE_P (XBUFFER (p->buffer))) + if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) /* If saved buffer is alive, install it. */ { wset_buffer (w, p->buffer); w->start_at_line_beg = !NILP (p->start_at_line_beg); - set_marker_restricted (w->start, p->start, w->buffer); + set_marker_restricted (w->start, p->start, w->contents); set_marker_restricted (w->pointm, p->pointm, - w->buffer); - Fset_marker (BVAR (XBUFFER (w->buffer), mark), - p->mark, w->buffer); + w->contents); + Fset_marker (BVAR (XBUFFER (w->contents), mark), + p->mark, w->contents); /* As documented in Fcurrent_window_configuration, don't restore the location of point in the buffer which was @@ -5775,23 +5718,21 @@ the return value is nil. Otherwise the value is t. */) && XBUFFER (p->buffer) == current_buffer) Fgoto_char (w->pointm); } - else if (!NILP (w->buffer) - && BUFFER_LIVE_P (XBUFFER (w->buffer))) - /* Keep window's old buffer; make sure the markers are - real. */ - { - /* Set window markers at start of visible range. */ - if (XMARKER (w->start)->buffer == 0) - set_marker_restricted_both (w->start, w->buffer, 0, 0); - if (XMARKER (w->pointm)->buffer == 0) - set_marker_restricted_both - (w->pointm, w->buffer, - BUF_PT (XBUFFER (w->buffer)), - BUF_PT_BYTE (XBUFFER (w->buffer))); - w->start_at_line_beg = 1; - } - else - /* Window has no live buffer, get one. */ + else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents))) + /* Keep window's old buffer; make sure the markers are real. */ + { + /* Set window markers at start of visible range. */ + if (XMARKER (w->start)->buffer == 0) + set_marker_restricted_both (w->start, w->contents, 0, 0); + if (XMARKER (w->pointm)->buffer == 0) + set_marker_restricted_both + (w->pointm, w->contents, + BUF_PT (XBUFFER (w->contents)), + BUF_PT_BYTE (XBUFFER (w->contents))); + w->start_at_line_beg = 1; + } + else if (!NILP (w->start)) + /* Leaf window has no live buffer, get one. */ { /* Get the buffer via other_buffer_safely in order to avoid showing an unimportant buffer and, if necessary, to @@ -5800,8 +5741,8 @@ the return value is nil. Otherwise the value is t. */) wset_buffer (w, other_buffer_safely (Fcurrent_buffer ())); /* This will set the markers to beginning of visible range. */ - set_marker_restricted_both (w->start, w->buffer, 0, 0); - set_marker_restricted_both (w->pointm, w->buffer, 0, 0); + set_marker_restricted_both (w->start, w->contents, 0, 0); + set_marker_restricted_both (w->pointm, w->contents, 0, 0); w->start_at_line_beg = 1; if (!NILP (w->dedicated)) /* Record this window as dead. */ @@ -5814,17 +5755,17 @@ the return value is nil. Otherwise the value is t. */) fset_root_window (f, data->root_window); /* Arrange *not* to restore point in the buffer that was current when the window configuration was saved. */ - if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)) + if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)) set_marker_restricted (XWINDOW (data->current_window)->pointm, make_number (old_point), - XWINDOW (data->current_window)->buffer); + XWINDOW (data->current_window)->contents); /* In the following call to `select-window', prevent "swapping out point" in the old selected window using the buffer that has been restored into it. We already swapped out that point from that window's old buffer. */ select_window (data->current_window, Qnil, 1); - BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window) + BVAR (XBUFFER (XWINDOW (selected_window)->contents), last_selected_window) = selected_window; if (NILP (data->focus_frame) @@ -5851,14 +5792,9 @@ the return value is nil. Otherwise the value is t. */) /* Now, free glyph matrices in windows that were not reused. */ for (i = n = 0; i < n_leaf_windows; ++i) { - if (NILP (leaf_windows[i]->buffer)) - { - /* Assert it's not reused as a combination. */ - eassert (NILP (leaf_windows[i]->hchild) - && NILP (leaf_windows[i]->vchild)); - free_window_matrices (leaf_windows[i]); - } - else if (EQ (leaf_windows[i]->buffer, new_current_buffer)) + if (NILP (leaf_windows[i]->contents)) + free_window_matrices (leaf_windows[i]); + else if (EQ (leaf_windows[i]->contents, new_current_buffer)) ++n; } @@ -5889,7 +5825,7 @@ the return value is nil. Otherwise the value is t. */) Fset_buffer (new_current_buffer); /* If the new current buffer doesn't appear in the selected window, go to its old point (see bug#12208). */ - if (!EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)) + if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer)) Fgoto_char (make_number (old_point)); } @@ -5899,9 +5835,17 @@ the return value is nil. Otherwise the value is t. */) return (FRAME_LIVE_P (f) ? Qt : Qnil); } +void +restore_window_configuration (Lisp_Object configuration) +{ + Fset_window_configuration (configuration); +} + + +/* If WINDOW is an internal window, recursively delete all child windows + reachable via the next and contents slots of WINDOW. Otherwise setup + WINDOW to not show any buffer. */ -/* Recursively delete all child windows reachable via the next, vchild, - and hchild slots of WINDOW. */ void delete_all_child_windows (Lisp_Object window) { @@ -5913,17 +5857,12 @@ delete_all_child_windows (Lisp_Object window) /* Delete WINDOW's siblings (we traverse postorderly). */ delete_all_child_windows (w->next); - if (!NILP (w->vchild)) - { - delete_all_child_windows (w->vchild); - wset_vchild (w, Qnil); - } - else if (!NILP (w->hchild)) + if (WINDOWP (w->contents)) { - delete_all_child_windows (w->hchild); - wset_hchild (w, Qnil); + delete_all_child_windows (w->contents); + wset_combination (w, 0, Qnil); } - else if (!NILP (w->buffer)) + else if (BUFFERP (w->contents)) { unshow_buffer (w); unchain_marker (XMARKER (w->pointm)); @@ -5931,7 +5870,7 @@ delete_all_child_windows (Lisp_Object window) /* Since combination limit makes sense for an internal windows only, we use this slot to save the buffer for the sake of possible resurrection in Fset_window_configuration. */ - wset_combination_limit (w, w->buffer); + wset_combination_limit (w, w->contents); wset_buffer (w, Qnil); } @@ -5944,10 +5883,8 @@ count_windows (register struct window *window) register int count = 1; if (!NILP (window->next)) count += count_windows (XWINDOW (window->next)); - if (!NILP (window->vchild)) - count += count_windows (XWINDOW (window->vchild)); - if (!NILP (window->hchild)) - count += count_windows (XWINDOW (window->hchild)); + if (WINDOWP (window->contents)) + count += count_windows (XWINDOW (window->contents)); return count; } @@ -5959,10 +5896,8 @@ get_leaf_windows (struct window *w, struct window **flat, int i) { while (w) { - if (!NILP (w->hchild)) - i = get_leaf_windows (XWINDOW (w->hchild), flat, i); - else if (!NILP (w->vchild)) - i = get_leaf_windows (XWINDOW (w->vchild), flat, i); + if (WINDOWP (w->contents)) + i = get_leaf_windows (XWINDOW (w->contents), flat, i); else flat[i++] = w; @@ -6002,8 +5937,7 @@ get_phys_cursor_glyph (struct window *w) hpos = row->used[TEXT_AREA] - 1; } - if (row->used[TEXT_AREA] > hpos - && 0 <= hpos) + if (0 <= hpos && hpos < row->used[TEXT_AREA]) glyph = row->glyphs[TEXT_AREA] + hpos; else glyph = NULL; @@ -6019,14 +5953,14 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) register struct window *w; register Lisp_Object tem, pers, par; - for (;!NILP (window); window = w->next) + for (; !NILP (window); window = w->next) { p = SAVED_WINDOW_N (vector, i); w = XWINDOW (window); wset_temslot (w, make_number (i)); i++; p->window = window; - p->buffer = w->buffer; + p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil); p->left_col = make_number (w->left_col); p->top_line = make_number (w->top_line); p->total_cols = make_number (w->total_cols); @@ -6036,10 +5970,10 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) XSETFASTINT (p->hscroll, w->hscroll); XSETFASTINT (p->min_hscroll, w->min_hscroll); p->display_table = w->display_table; - p->left_margin_cols = w->left_margin_cols; - p->right_margin_cols = w->right_margin_cols; - p->left_fringe_width = w->left_fringe_width; - p->right_fringe_width = w->right_fringe_width; + p->left_margin_cols = make_number (w->left_margin_cols); + p->right_margin_cols = make_number (w->right_margin_cols); + p->left_fringe_width = make_number (w->left_fringe_width); + p->right_fringe_width = make_number (w->right_fringe_width); p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil; p->scroll_bar_width = w->scroll_bar_width; p->vertical_scroll_bar_type = w->vertical_scroll_bar_type; @@ -6093,15 +6027,15 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) } } - if (!NILP (w->buffer)) + if (BUFFERP (w->contents)) { /* Save w's value of point in the window configuration. If w is the selected window, then get the value of point from the buffer; pointm is garbage in the selected window. */ if (EQ (window, selected_window)) - p->pointm = build_marker (XBUFFER (w->buffer), - BUF_PT (XBUFFER (w->buffer)), - BUF_PT_BYTE (XBUFFER (w->buffer))); + p->pointm = build_marker (XBUFFER (w->contents), + BUF_PT (XBUFFER (w->contents)), + BUF_PT_BYTE (XBUFFER (w->contents))); else p->pointm = Fcopy_marker (w->pointm, Qnil); XMARKER (p->pointm)->insertion_type @@ -6110,7 +6044,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) p->start = Fcopy_marker (w->start, Qnil); p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil; - tem = BVAR (XBUFFER (w->buffer), mark); + tem = BVAR (XBUFFER (w->contents), mark); p->mark = Fcopy_marker (tem, Qnil); } else @@ -6131,10 +6065,8 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) else p->prev = XWINDOW (w->prev)->temslot; - if (!NILP (w->vchild)) - i = save_window_save (w->vchild, vector, i); - if (!NILP (w->hchild)) - i = save_window_save (w->hchild, vector, i); + if (WINDOWP (w->contents)) + i = save_window_save (w->contents, vector, i); } return i; @@ -6197,38 +6129,31 @@ WINDOW must be a live window and defaults to the selected one. Second arg LEFT-WIDTH specifies the number of character cells to reserve for the left marginal area. Optional third arg RIGHT-WIDTH does the same for the right marginal area. A nil width parameter -means no margin. */) +means no margin. + +Return t if any margin was actually changed and nil otherwise. */) (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width) { struct window *w = decode_live_window (window); + int left, right; - /* Translate negative or zero widths to nil. - Margins that are too wide have to be checked elsewhere. */ + /* FIXME: what about margins that are too wide? */ - if (!NILP (left_width)) - { - CHECK_NUMBER (left_width); - if (XINT (left_width) <= 0) - left_width = Qnil; - } - - if (!NILP (right_width)) - { - CHECK_NUMBER (right_width); - if (XINT (right_width) <= 0) - right_width = Qnil; - } + left = (NILP (left_width) ? 0 + : (CHECK_NATNUM (left_width), XINT (left_width))); + right = (NILP (right_width) ? 0 + : (CHECK_NATNUM (right_width), XINT (right_width))); - if (!EQ (w->left_margin_cols, left_width) - || !EQ (w->right_margin_cols, right_width)) + if (w->left_margin_cols != left || w->right_margin_cols != right) { - wset_left_margin_cols (w, left_width); - wset_right_margin_cols (w, right_width); + w->left_margin_cols = left; + w->right_margin_cols = right; adjust_window_margins (w); ++windows_or_buffers_changed; adjust_glyphs (XFRAME (WINDOW_FRAME (w))); + return Qt; } return Qnil; @@ -6246,7 +6171,8 @@ as nil. */) (Lisp_Object window) { struct window *w = decode_live_window (window); - return Fcons (w->left_margin_cols, w->right_margin_cols); + return Fcons (w->left_margin_cols ? make_number (w->left_margin_cols) : Qnil, + w->right_margin_cols ? make_number (w->right_margin_cols) : Qnil); } @@ -6267,25 +6193,28 @@ frame's default fringe width. Default fringe widths can be set with the command `set-fringe-style'. If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes outside of the display margins. By default, fringes are drawn between -display marginal areas and the text area. */) - (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins) +display marginal areas and the text area. + +Return t if any fringe was actually changed and nil otherwise. */) + (Lisp_Object window, Lisp_Object left_width, + Lisp_Object right_width, Lisp_Object outside_margins) { struct window *w = decode_live_window (window); - int outside = !NILP (outside_margins); + int left, right, outside = !NILP (outside_margins); - if (!NILP (left_width)) - CHECK_NATNUM (left_width); - if (!NILP (right_width)) - CHECK_NATNUM (right_width); + left = (NILP (left_width) ? -1 + : (CHECK_NATNUM (left_width), XINT (left_width))); + right = (NILP (right_width) ? -1 + : (CHECK_NATNUM (right_width), XINT (right_width))); - /* Do nothing on a tty. */ + /* Do nothing on a tty or if nothing to actually change. */ if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) - && (!EQ (w->left_fringe_width, left_width) - || !EQ (w->right_fringe_width, right_width) + && (w->left_fringe_width != left + || w->right_fringe_width != right || w->fringes_outside_margins != outside)) { - wset_left_fringe_width (w, left_width); - wset_right_fringe_width (w, right_width); + w->left_fringe_width = left; + w->right_fringe_width = right; w->fringes_outside_margins = outside; adjust_window_margins (w); @@ -6295,6 +6224,7 @@ display marginal areas and the text area. */) ++windows_or_buffers_changed; adjust_glyphs (XFRAME (WINDOW_FRAME (w))); + return Qt; } return Qnil; @@ -6451,7 +6381,7 @@ If PIXELS-P is non-nil, the return value is VSCROLL. */) adjust_glyphs (f); /* Prevent redisplay shortcuts. */ - XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1; + XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1; } } @@ -6485,10 +6415,8 @@ foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *u for (cont = 1; w && cont;) { - if (!NILP (w->hchild)) - cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data); - else if (!NILP (w->vchild)) - cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data); + if (WINDOWP (w->contents)) + cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data); else cont = fn (w, user_data); @@ -6498,38 +6426,6 @@ foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *u return cont; } - -/* Freeze or unfreeze the window start of W unless it is a - mini-window or the selected window. FREEZE_P non-null means freeze - the window start. */ - -static int -freeze_window_start (struct window *w, void *freeze_p) -{ - if (MINI_WINDOW_P (w) - || (WINDOWP (selected_window) /* Can be nil in corner cases. */ - && (w == XWINDOW (selected_window) - || (MINI_WINDOW_P (XWINDOW (selected_window)) - && ! NILP (Vminibuf_scroll_window) - && w == XWINDOW (Vminibuf_scroll_window))))) - freeze_p = NULL; - - w->frozen_window_start_p = freeze_p != NULL; - return 1; -} - - -/* Freeze or unfreeze the window starts of all leaf windows on frame - F, except the selected window and a mini-window. FREEZE_P non-zero - means freeze the window start. */ - -void -freeze_window_starts (struct frame *f, bool freeze_p) -{ - foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0)); -} - - /*********************************************************************** Initialization ***********************************************************************/