X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/c3c45f65ba3d99aa53796cbfe47de73bcb7b949a..018ba359ab456f6a43f3acea0c15df616aa0ad02:/src/window.c diff --git a/src/window.c b/src/window.c index b02cc6b796..4c629113d9 100644 --- a/src/window.c +++ b/src/window.c @@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */ #include "lisp.h" #include "buffer.h" #include "keyboard.h" +#include "keymap.h" #include "frame.h" #include "window.h" #include "commands.h" @@ -69,6 +70,7 @@ Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; Lisp_Object Qwindow_size_fixed, Qleft_fringe, Qright_fringe; extern Lisp_Object Qheight, Qwidth; +static int displayed_window_lines P_ ((struct window *)); static struct window *decode_window P_ ((Lisp_Object)); static Lisp_Object select_window_1 P_ ((Lisp_Object, int)); static int count_windows P_ ((struct window *)); @@ -220,8 +222,6 @@ Lisp_Object Vscroll_preserve_screen_position; static int inhibit_frame_unsplittable; #endif /* 0 */ -#define min(a, b) ((a) < (b) ? (a) : (b)) - extern int scroll_margin; extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; @@ -1660,7 +1660,7 @@ argument ALL_FRAMES is non-nil, cycle through all frames.") window = Fnext_window (window, Qnil, all_frames); for (; i < 0; ++i) window = Fprevious_window (window, Qnil, all_frames); - + Fselect_window (window); return Qnil; } @@ -1854,8 +1854,6 @@ window_loop (type, obj, mini, frames) display there. */ Lisp_Object buffer; buffer = Fother_buffer (obj, Qnil, w->frame); - if (NILP (buffer)) - buffer = Fget_buffer_create (build_string ("*scratch*")); Fset_window_buffer (window, buffer); if (EQ (window, selected_window)) Fset_buffer (w->buffer); @@ -1891,8 +1889,6 @@ window_loop (type, obj, mini, frames) /* Find another buffer to show in this window. */ buffer = Fother_buffer (obj, Qnil, w->frame); - if (NILP (buffer)) - buffer = Fget_buffer_create (build_string ("*scratch*")); /* If this window is dedicated, and in a frame of its own, kill the frame. */ @@ -2733,9 +2729,7 @@ select_window_1 (window, recordflag) CHECK_LIVE_WINDOW (window, 0); w = XWINDOW (window); - - if (NILP (w->buffer)) - error ("Trying to select deleted window or non-leaf window"); + w->frozen_window_start_p = 0; XSETFASTINT (w->use_time, ++window_select_count); if (EQ (window, selected_window)) @@ -3855,7 +3849,7 @@ mark_window_cursors_off (w) } -/* Return number of lines of text (not counting mode line) in W. */ +/* Return number of lines of text (not counting mode lines) in W. */ int window_internal_height (w) @@ -3863,13 +3857,19 @@ window_internal_height (w) { int ht = XFASTINT (w->height); - if (MINI_WINDOW_P (w)) - return ht; - - if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild) - || !NILP (w->next) || !NILP (w->prev) - || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w)))) - return ht - 1; + if (!MINI_WINDOW_P (w)) + { + if (!NILP (w->parent) + || !NILP (w->vchild) + || !NILP (w->hchild) + || !NILP (w->next) + || !NILP (w->prev) + || WINDOW_WANTS_MODELINE_P (w)) + --ht; + + if (WINDOW_WANTS_HEADER_LINE_P (w)) + --ht; + } return ht; } @@ -3908,7 +3908,7 @@ window_internal_width (w) ***********************************************************************/ /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll - one screen-full, which is defined as the height of the window minus + N screen-fulls, which is defined as the height of the window minus next_screen_context_lines. If WHOLE is zero, scroll up N lines instead. Negative values of N mean scroll down. NOERROR non-zero means don't signal an error if we try to move over BEGV or ZV, @@ -3953,8 +3953,10 @@ window_scroll_pixel_based (window, n, whole, noerror) SET_TEXT_POS_FROM_MARKER (start, w->start); /* If PT is not visible in WINDOW, move back one half of - the screen. */ - tem = Fpos_visible_in_window_p (make_number (PT), window, Qnil); + the screen. Allow PT to be partially visible, otherwise + something like (scroll-down 1) with PT in the line before + the partially visible one would recenter. */ + tem = Fpos_visible_in_window_p (make_number (PT), window, Qt); if (NILP (tem)) { /* Move backward half the height of the window. Performance note: @@ -3962,7 +3964,7 @@ window_scroll_pixel_based (window, n, whole, noerror) results for variable height lines. */ init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); it.current_y = it.last_visible_y; - move_it_vertically (&it, -it.last_visible_y / 2); + move_it_vertically (&it, - window_box_height (w) / 2); /* The function move_iterator_vertically may move over more than the specified y-distance. If it->w is small, e.g. a @@ -3995,10 +3997,9 @@ window_scroll_pixel_based (window, n, whole, noerror) start_display (&it, w, start); if (whole) { - int screen_full = (it.last_visible_y + int screen_full = (window_box_height (w) - next_screen_context_lines * CANON_Y_UNIT (it.f)); - int direction = n < 0 ? -1 : 1; - int dy = direction * screen_full; + int dy = n * screen_full; /* Note that move_it_vertically always moves the iterator to the start of a line. So, if the last line doesn't have a newline, @@ -4142,6 +4143,11 @@ window_scroll_line_based (window, n, whole, noerror) struct position posit; int original_vpos; + /* If scrolling screen-fulls, compute the number of lines to + scroll from the window's height. */ + if (whole) + n *= max (1, ht - next_screen_context_lines); + startpos = marker_position (w->start); posit = *compute_motion (startpos, 0, 0, 0, @@ -4273,8 +4279,7 @@ scroll_command (n, direction) Lisp_Object n; int direction; { - register int defalt; - int count = specpdl_ptr - specpdl; + int count = BINDING_STACK_SIZE (); xassert (abs (direction) == 1); @@ -4289,14 +4294,10 @@ scroll_command (n, direction) ++windows_or_buffers_changed; } - defalt = (window_internal_height (XWINDOW (selected_window)) - - next_screen_context_lines); - defalt = direction * (defalt < 1 ? 1 : defalt); - if (NILP (n)) - window_scroll (selected_window, defalt, 1, 0); + window_scroll (selected_window, direction, 1, 0); else if (EQ (n, Qminus)) - window_scroll (selected_window, - defalt, 1, 0); + window_scroll (selected_window, -direction, 1, 0); else { n = Fprefix_numeric_value (n); @@ -4388,18 +4389,14 @@ specifies the window to scroll.\n\ If `other-window-scroll-buffer' is non-nil, scroll the window\n\ showing that buffer, popping the buffer up if necessary.") (arg) - register Lisp_Object arg; + Lisp_Object arg; { - register Lisp_Object window; - register int defalt; - register struct window *w; - register int count = specpdl_ptr - specpdl; + Lisp_Object window; + struct window *w; + int count = BINDING_STACK_SIZE (); window = Fother_window_for_scrolling (); - w = XWINDOW (window); - defalt = window_internal_height (w) - next_screen_context_lines; - if (defalt < 1) defalt = 1; /* Don't screw up if window_scroll gets an error. */ record_unwind_protect (save_excursion_restore, save_excursion_save ()); @@ -4409,9 +4406,9 @@ showing that buffer, popping the buffer up if necessary.") SET_PT (marker_position (w->pointm)); if (NILP (arg)) - window_scroll (window, defalt, 1, 1); + window_scroll (window, 1, 1, 1); else if (EQ (arg, Qminus)) - window_scroll (window, -defalt, 1, 1); + window_scroll (window, -1, 1, 1); else { if (CONSP (arg)) @@ -4495,7 +4492,16 @@ displayed_window_lines (w) else old_buffer = NULL; - SET_TEXT_POS_FROM_MARKER (start, w->start); + /* In case W->start is out of the accessible range, do something + reasonable. This happens in Info mode when Info-scroll-down + calls (recenter -1) while W->start is 1. */ + if (XMARKER (w->start)->charpos < BEGV) + SET_TEXT_POS (start, BEGV, BEGV_BYTE); + else if (XMARKER (w->start)->charpos > ZV) + SET_TEXT_POS (start, ZV, ZV_BYTE); + else + SET_TEXT_POS_FROM_MARKER (start, w->start); + start_display (&it, w, start); move_it_vertically (&it, height); bottom_y = line_bottom_y (&it); @@ -4555,34 +4561,70 @@ and redisplay normally--don't erase and redraw the frame.") set_buffer_internal (buf); - /* Handle centering on a gfaphical frame specially. Such frames can + /* 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. */ - if (center_p && FRAME_WINDOW_P (XFRAME (w->frame))) + if (FRAME_WINDOW_P (XFRAME (w->frame))) { - struct it it; - struct text_pos pt; - - SET_TEXT_POS (pt, PT, PT_BYTE); - start_display (&it, w, pt); - move_it_vertically (&it, - it.last_visible_y / 2); - charpos = IT_CHARPOS (it); - bytepos = IT_BYTEPOS (it); - } - else - { - struct position pos; - if (center_p) { - int ht = displayed_window_lines (w); - arg = make_number (ht / 2); + struct it it; + struct text_pos pt; + + SET_TEXT_POS (pt, PT, PT_BYTE); + start_display (&it, w, pt); + move_it_vertically (&it, - window_box_height (w) / 2); + charpos = IT_CHARPOS (it); + bytepos = IT_BYTEPOS (it); } else if (XINT (arg) < 0) { - int ht = displayed_window_lines (w); - XSETINT (arg, XINT (arg) + ht); + struct it it; + struct text_pos pt; + int y0, y1, h, nlines; + + SET_TEXT_POS (pt, PT, PT_BYTE); + start_display (&it, w, pt); + y0 = it.current_y; + + /* The amount of pixels we have to move back is the window + height minus what's displayed in the line containing PT, + and the lines below. */ + nlines = - XINT (arg) - 1; + move_it_by_lines (&it, nlines, 1); + + y1 = it.current_y - y0; + h = line_bottom_y (&it) - y1; + + /* If we can't move down NLINES lines because we hit + the end of the buffer, count in some empty lines. */ + if (it.vpos < nlines) + y1 += (nlines - it.vpos) * CANON_Y_UNIT (it.f); + + y0 = it.last_visible_y - y1 - h; + + start_display (&it, w, pt); + move_it_vertically (&it, - y0); + charpos = IT_CHARPOS (it); + bytepos = IT_BYTEPOS (it); + } + else + { + struct position pos; + pos = *vmotion (PT, - XINT (arg), w); + charpos = pos.bufpos; + bytepos = pos.bytepos; } + } + else + { + struct position pos; + 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); pos = *vmotion (PT, - XINT (arg), w); charpos = pos.bufpos; @@ -4970,7 +5012,7 @@ the return value is nil. Otherwise the value is t.") when the frame's old selected window has been deleted. */ if (f != selected_frame && FRAME_WINDOW_P (f)) do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), - Qnil, 0); + 0, 0); #endif /* Set the screen height to the value it had before this function. */ @@ -5018,7 +5060,7 @@ the return value is nil. Otherwise the value is t.") Fselect_window above totally superfluous; it still sets f's selected window. */ if (FRAME_LIVE_P (XFRAME (data->selected_frame))) - do_switch_frame (data->selected_frame, Qnil, 0); + do_switch_frame (data->selected_frame, 0, 0); if (! NILP (Vwindow_configuration_change_hook) && ! NILP (Vrun_hooks)) @@ -5460,7 +5502,7 @@ foreach_window_1 (w, fn, user_data) } -/* Freeze or unfreeze the window start of W if unless it is a +/* 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. */