X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/5494d7bcdba82b2c33278b8d37fee6b0c9bd14e5..e58e5c503fb525017b04a11bfae8ccddf04f3df0:/src/window.c diff --git a/src/window.c b/src/window.c index 4839830b17..96cafc5820 100644 --- a/src/window.c +++ b/src/window.c @@ -1,7 +1,7 @@ /* Window creation, deletion and examination for GNU Emacs. Does not include redisplay. Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000, - 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -17,8 +17,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ #include #include "lisp.h" @@ -273,7 +273,6 @@ make_window () XSETWINDOW (val, p); XSETFASTINT (p->last_point, 0); p->frozen_window_start_p = 0; - p->height_fixed_p = 0; p->last_cursor_off_p = p->cursor_off_p = 0; p->left_margin_cols = Qnil; p->right_margin_cols = Qnil; @@ -683,7 +682,10 @@ coordinates_in_window (w, x, y) /* Outside any interesting column? */ if (*x < left_x || *x > right_x) - return ON_SCROLL_BAR; + { + *y -= top_y; + return ON_SCROLL_BAR; + } lmargin_width = window_box_width (w, LEFT_MARGIN_AREA); rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA); @@ -740,9 +742,9 @@ coordinates_in_window (w, x, y) ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w)) : (*x >= right_x - rmargin_width))) { - *x -= right_x; - if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)) - *x -= WINDOW_RIGHT_FRINGE_WIDTH (w); + *x -= right_x - rmargin_width; + if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)) + *x += WINDOW_RIGHT_FRINGE_WIDTH (w); *y -= top_y; return ON_RIGHT_MARGIN; } @@ -754,7 +756,7 @@ coordinates_in_window (w, x, y) } /* Everything special ruled out - must be on text area */ - *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w); + *x -= text_left; *y -= top_y; return ON_TEXT; } @@ -1030,7 +1032,8 @@ if it isn't already recorded. */) if (! NILP (update) && ! (! NILP (w->window_end_valid) - && XFASTINT (w->last_modified) >= MODIFF)) + && XFASTINT (w->last_modified) >= MODIFF) + && !noninteractive) { struct text_pos startp; struct it it; @@ -1472,7 +1475,7 @@ delete_window (window) /* Check if we have a v/hchild with a v/hchild. In that case remove one of them. */ - + if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild)) { p = XWINDOW (par->vchild); @@ -2438,27 +2441,22 @@ window_fixed_size_p (w, width_p, check_siblings_p) } else if (BUFFERP (w->buffer)) { - if (w->height_fixed_p && !width_p) - fixed_p = 1; - else - { - struct buffer *old = current_buffer; - Lisp_Object val; + struct buffer *old = current_buffer; + Lisp_Object val; - current_buffer = XBUFFER (w->buffer); - val = find_symbol_value (Qwindow_size_fixed); - current_buffer = old; + current_buffer = XBUFFER (w->buffer); + val = find_symbol_value (Qwindow_size_fixed); + current_buffer = old; - fixed_p = 0; - if (!EQ (val, Qunbound)) - { - fixed_p = !NILP (val); + fixed_p = 0; + if (!EQ (val, Qunbound)) + { + fixed_p = !NILP (val); - if (fixed_p - && ((EQ (val, Qheight) && width_p) - || (EQ (val, Qwidth) && !width_p))) - fixed_p = 0; - } + if (fixed_p + && ((EQ (val, Qheight) && width_p) + || (EQ (val, Qwidth) && !width_p))) + fixed_p = 0; } /* Can't tell if this one is resizable without looking at @@ -3234,7 +3232,7 @@ selects the buffer of the selected window before each command. */) so that FRAME_FOCUS_FRAME is moved appropriately as we move around in the state where a minibuffer in a separate frame is active. */ - Fselect_frame (WINDOW_FRAME (w), Qnil); + Fselect_frame (WINDOW_FRAME (w)); } else sf->selected_window = window; @@ -4180,7 +4178,7 @@ enlarge_window (window, delta, widthflag, preserve_before) The number of children n equals the number of resizable children of this window + 1 because we know window itself - is resizable (otherwise we would have signalled an error. */ + is resizable (otherwise we would have signalled an error). */ struct window *w = XWINDOW (window); Lisp_Object s; @@ -4783,7 +4781,9 @@ window_scroll_pixel_based (window, n, whole, noerror) /* We moved the window start towards ZV, so PT may be now in the scroll margin at the top. */ move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); - if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin) + if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin + && (NILP (Vscroll_preserve_screen_position) + || EQ (Vscroll_preserve_screen_position, Qt))) /* We found PT at a legitimate height. Leave it alone. */ ; else if (preserve_y >= 0) @@ -4820,7 +4820,9 @@ window_scroll_pixel_based (window, n, whole, noerror) /* We moved the window start towards BEGV, so PT may be now in the scroll margin at the bottom. */ move_it_to (&it, PT, -1, - it.last_visible_y - this_scroll_margin - 1, -1, + (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w) + - this_scroll_margin - 1), + -1, MOVE_TO_POS | MOVE_TO_Y); /* Save our position, in case it's correct. */ @@ -4836,7 +4838,9 @@ window_scroll_pixel_based (window, n, whole, noerror) partial_p = it.current_y > it.last_visible_y; } - if (charpos == PT && !partial_p) + if (charpos == PT && !partial_p + && (NILP (Vscroll_preserve_screen_position) + || EQ (Vscroll_preserve_screen_position, Qt))) /* We found PT before we found the display margin, so PT is ok. */ ; else if (preserve_y >= 0) @@ -4951,7 +4955,8 @@ window_scroll_line_based (window, n, whole, noerror) the window-scroll-functions. */ w->force_start = Qt; - if (whole && !NILP (Vscroll_preserve_screen_position)) + if (!NILP (Vscroll_preserve_screen_position) + && (whole || !EQ (Vscroll_preserve_screen_position, Qt))) { SET_PT_BOTH (pos, pos_byte); Fvertical_motion (make_number (original_vpos), window); @@ -5326,6 +5331,8 @@ and redisplay normally--don't erase and redraw the frame. */) struct buffer *obuf = current_buffer; int center_p = 0; int charpos, bytepos; + int iarg; + int this_scroll_margin; /* If redisplay is suppressed due to an error, try again. */ obuf->display_error_modiff = 0; @@ -5348,10 +5355,17 @@ and redisplay normally--don't erase and redraw the frame. */) { arg = Fprefix_numeric_value (arg); CHECK_NUMBER (arg); + iarg = XINT (arg); } set_buffer_internal (buf); + /* Do this after making BUF current + in case scroll_margin is buffer-local. */ + this_scroll_margin = max (0, scroll_margin); + this_scroll_margin = min (this_scroll_margin, + XFASTINT (w->total_lines) / 4); + /* Handle centering on a graphical frame specially. Such frames can have variable-height lines and centering point on the basis of line counts would lead to strange effects. */ @@ -5368,14 +5382,16 @@ and redisplay normally--don't erase and redraw the frame. */) charpos = IT_CHARPOS (it); bytepos = IT_BYTEPOS (it); } - else if (XINT (arg) < 0) + else if (iarg < 0) { struct it it; struct text_pos pt; - int nlines = - XINT (arg); + int nlines = -iarg; int extra_line_spacing; int h = window_box_height (w); + iarg = - max (-iarg, this_scroll_margin); + SET_TEXT_POS (pt, PT, PT_BYTE); start_display (&it, w, pt); @@ -5434,7 +5450,10 @@ and redisplay normally--don't erase and redraw the frame. */) else { struct position pos; - pos = *vmotion (PT, - XINT (arg), w); + + iarg = max (iarg, this_scroll_margin); + + pos = *vmotion (PT, -iarg, w); charpos = pos.bufpos; bytepos = pos.bytepos; } @@ -5445,11 +5464,15 @@ and redisplay normally--don't erase and redraw the frame. */) int ht = window_internal_height (w); if (center_p) - arg = make_number (ht / 2); - else if (XINT (arg) < 0) - arg = make_number (XINT (arg) + ht); + iarg = ht / 2; + else if (iarg < 0) + iarg += ht; + + /* Don't let it get into the margin at either top or bottom. */ + iarg = max (iarg, this_scroll_margin); + iarg = min (iarg, ht - this_scroll_margin - 1); - pos = *vmotion (PT, - XINT (arg), w); + pos = *vmotion (PT, - iarg, w); charpos = pos.bufpos; bytepos = pos.bytepos; } @@ -5498,6 +5521,9 @@ zero means top of window, negative means relative to bottom of window. */) struct window *w = XWINDOW (selected_window); int lines, start; Lisp_Object window; +#if 0 + int this_scroll_margin; +#endif window = selected_window; start = marker_position (w->start); @@ -5513,13 +5539,33 @@ zero means top of window, negative means relative to bottom of window. */) Fgoto_char (w->start); lines = displayed_window_lines (w); + +#if 0 + this_scroll_margin = max (0, scroll_margin); + this_scroll_margin = min (this_scroll_margin, lines / 4); +#endif + if (NILP (arg)) XSETFASTINT (arg, lines / 2); else { - arg = Fprefix_numeric_value (arg); - if (XINT (arg) < 0) - XSETINT (arg, XINT (arg) + lines); + int iarg = XINT (Fprefix_numeric_value (arg)); + + if (iarg < 0) + iarg = iarg + lines; + +#if 0 /* This code would prevent move-to-window-line from moving point + to a place inside the scroll margins (which would cause the + next redisplay to scroll). I wrote this code, but then concluded + it is probably better not to install it. However, it is here + inside #if 0 so as not to lose it. -- rms. */ + + /* Don't let it get into the margin at either top or bottom. */ + iarg = max (iarg, this_scroll_margin); + iarg = min (iarg, lines - this_scroll_margin - 1); +#endif + + arg = make_number (iarg); } /* Skip past a partially visible first line. */ @@ -5576,8 +5622,6 @@ struct saved_window Lisp_Object scroll_bar_width, vertical_scroll_bar_type; }; -#define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */ - #define SAVED_WINDOW_N(swv,n) \ ((struct saved_window *) (XVECTOR ((swv)->contents[(n)]))) @@ -6157,7 +6201,7 @@ redirection (see `redirect-frame-focus'). */) data->saved_windows = tem; for (i = 0; i < n_windows; i++) XVECTOR (tem)->contents[i] - = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil); + = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil); save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0); XSETWINDOW_CONFIGURATION (tem, data); return (tem); @@ -6185,6 +6229,84 @@ usage: (save-window-excursion BODY ...) */) return unbind_to (count, val); } + + +/*********************************************************************** + Window Split Tree + ***********************************************************************/ + +static Lisp_Object +window_tree (w) + struct window *w; +{ + Lisp_Object tail = Qnil; + Lisp_Object result = Qnil; + + while (w) + { + Lisp_Object wn; + + XSETWINDOW (wn, w); + if (!NILP (w->hchild)) + wn = Fcons (Qnil, Fcons (Fwindow_edges (wn), + window_tree (XWINDOW (w->hchild)))); + else if (!NILP (w->vchild)) + wn = Fcons (Qt, Fcons (Fwindow_edges (wn), + window_tree (XWINDOW (w->vchild)))); + + if (NILP (result)) + { + result = tail = Fcons (wn, Qnil); + } + else + { + XSETCDR (tail, Fcons (wn, Qnil)); + tail = XCDR (tail); + } + + w = NILP (w->next) ? 0 : XWINDOW (w->next); + } + + return result; +} + + + +DEFUN ("window-tree", Fwindow_tree, Swindow_tree, + 0, 1, 0, + doc: /* Return the window tree for frame FRAME. + +The return value is a list of the form (ROOT MINI), where ROOT +represents the window tree of the frame's root window, and MINI +is the frame's minibuffer window. + +If the root window is not split, ROOT is the root window itself. +Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a +horizontal split, and t for a vertical split, EDGES gives the combined +size and position of the subwindows in the split, and the rest of the +elements are the subwindows in the split. Each of the subwindows may +again be a window or a list representing a window split, and so on. +EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'. + +If FRAME is nil or omitted, return information on the currently +selected frame. */) + (frame) + Lisp_Object frame; +{ + FRAME_PTR f; + + if (NILP (frame)) + frame = selected_frame; + + CHECK_FRAME (frame); + f = XFRAME (frame); + + if (!FRAME_LIVE_P (f)) + return Qnil; + + return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f))); +} + /*********************************************************************** Marginal Areas @@ -6198,33 +6320,33 @@ 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. */) - (window, left, right) - Lisp_Object window, left, right; + (window, left_width, right_width) + Lisp_Object window, left_width, right_width; { struct window *w = decode_window (window); /* Translate negative or zero widths to nil. Margins that are too wide have to be checked elsewhere. */ - if (!NILP (left)) + if (!NILP (left_width)) { - CHECK_NUMBER (left); - if (XINT (left) <= 0) - left = Qnil; + CHECK_NUMBER (left_width); + if (XINT (left_width) <= 0) + left_width = Qnil; } - if (!NILP (right)) + if (!NILP (right_width)) { - CHECK_NUMBER (right); - if (XINT (right) <= 0) - right = Qnil; + CHECK_NUMBER (right_width); + if (XINT (right_width) <= 0) + right_width = Qnil; } - if (!EQ (w->left_margin_cols, left) - || !EQ (w->right_margin_cols, right)) + if (!EQ (w->left_margin_cols, left_width) + || !EQ (w->right_margin_cols, right_width)) { - w->left_margin_cols = left; - w->right_margin_cols = right; + w->left_margin_cols = left_width; + w->right_margin_cols = right_width; adjust_window_margins (w); @@ -6269,22 +6391,22 @@ 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. */) - (window, left, right, outside_margins) - Lisp_Object window, left, right, outside_margins; + (window, left_width, right_width, outside_margins) + Lisp_Object window, left_width, right_width, outside_margins; { struct window *w = decode_window (window); - if (!NILP (left)) - CHECK_NATNUM (left); - if (!NILP (right)) - CHECK_NATNUM (right); + if (!NILP (left_width)) + CHECK_NATNUM (left_width); + if (!NILP (right_width)) + CHECK_NATNUM (right_width); - if (!EQ (w->left_fringe_width, left) - || !EQ (w->right_fringe_width, right) + if (!EQ (w->left_fringe_width, left_width) + || !EQ (w->right_fringe_width, right_width) || !EQ (w->fringes_outside_margins, outside_margins)) { - w->left_fringe_width = left; - w->right_fringe_width = right; + w->left_fringe_width = left_width; + w->right_fringe_width = right_width; w->fringes_outside_margins = outside_margins; adjust_window_margins (w); @@ -6914,9 +7036,13 @@ If there is only one window, it is split regardless of this value. */); DEFVAR_LISP ("scroll-preserve-screen-position", &Vscroll_preserve_screen_position, - doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. -This is only when it is impossible to keep point fixed and still -scroll as specified. */); + doc: /* *Controls if scroll commands move point to keep its screen line unchanged. +A value of nil means point does not keep its screen position except +at the scroll margin or window boundary respectively. +A value of t means point keeps its screen position if the scroll +command moved it vertically out of the window, e.g. when scrolling +by full screens. +Any other value means point always keeps its screen position. */); Vscroll_preserve_screen_position = Qnil; DEFVAR_LISP ("window-configuration-change-hook", @@ -6987,6 +7113,7 @@ The selected frame is the one whose configuration has changed. */); defsubr (&Sset_window_configuration); defsubr (&Scurrent_window_configuration); defsubr (&Ssave_window_excursion); + defsubr (&Swindow_tree); defsubr (&Sset_window_margins); defsubr (&Swindow_margins); defsubr (&Sset_window_fringes);