From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.devel Subject: Re: The unwarranted scrolling assumption Date: Sun, 20 Jun 2010 21:17:10 +0300 Message-ID: <83aaqpfu1m.fsf@gnu.org> References: <87631jvpzg.fsf@gmail.com> <4C18211C.3070106@harpegolden.net> <87vd9j5neu.fsf@kfs-lx.rd.rdm> <83sk4misf2.fsf@gnu.org> <83iq5hiiin.fsf@gnu.org> <83fx0lihov.fsf@gnu.org> <838w6cixma.fsf@gnu.org> <83y6ech1oo.fsf@gnu.org> <83ocf8gx7e.fsf@gnu.org> <83fx0jgxk7.fsf@gnu.org> <83eig3gspa.fsf@gnu.org> <83bpb7gp2g.fsf@gnu.org> <837hlvglvh.fsf@gnu.org> <834ogzglaj.fsf@gnu.org> <8339wjgg8w.fsf@gnu.org> <83y6eagb7g.fsf@gnu.org> <83vd9eg9j1.fsf@gnu.org> <83r5k2g1qa.fsf@gnu.org> <83eig1g21p.fsf@gnu.org> Reply-To: Eli Zaretskii NNTP-Posting-Host: lo.gmane.org X-Trace: dough.gmane.org 1277058335 15452 80.91.229.12 (20 Jun 2010 18:25:35 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sun, 20 Jun 2010 18:25:35 +0000 (UTC) Cc: lennart.borgman@gmail.com, emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Jun 20 20:25:32 2010 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1OQPCy-0007wd-Nt for ged-emacs-devel@m.gmane.org; Sun, 20 Jun 2010 20:25:29 +0200 Original-Received: from localhost ([127.0.0.1]:41617 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OQPCx-0002No-Ht for ged-emacs-devel@m.gmane.org; Sun, 20 Jun 2010 14:25:27 -0400 Original-Received: from [140.186.70.92] (port=43206 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OQP7m-0000El-IN for emacs-devel@gnu.org; Sun, 20 Jun 2010 14:20:08 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OQP7P-0006IR-DU for emacs-devel@gnu.org; Sun, 20 Jun 2010 14:19:44 -0400 Original-Received: from mtaout22.012.net.il ([80.179.55.172]:59999) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OQP7M-0006Hi-9n; Sun, 20 Jun 2010 14:19:40 -0400 Original-Received: from conversion-daemon.a-mtaout22.012.net.il by a-mtaout22.012.net.il (HyperSendmail v2007.08) id <0L4B00700S7YY600@a-mtaout22.012.net.il>; Sun, 20 Jun 2010 21:19:12 +0300 (IDT) Original-Received: from HOME-C4E4A596F7 ([84.228.178.198]) by a-mtaout22.012.net.il (HyperSendmail v2007.08) with ESMTPA id <0L4B00LEJS7YRYM0@a-mtaout22.012.net.il>; Sun, 20 Jun 2010 21:19:12 +0300 (IDT) In-reply-to: <83eig1g21p.fsf@gnu.org> X-012-Sender: halo1@inter.net.il X-detected-operating-system: by eggs.gnu.org: Solaris 10 (beta) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:126274 Archived-At: > Date: Sun, 20 Jun 2010 18:24:18 +0300 > From: Eli Zaretskii > Cc: cyd@stupidchicken.com, monnier@iro.umontreal.ca, emacs-devel@gnu.org > > It's a bit silly to do that, when we have a dVCS, but here you go > anyway: Here's an updated version: ---------------------------------------------------------------------- static int try_scrolling (window, just_this_one_p, scroll_conservatively, scroll_step, temp_scroll_step, last_line_misfit) Lisp_Object window; int just_this_one_p; EMACS_INT scroll_conservatively, scroll_step; int temp_scroll_step; int last_line_misfit; { struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); struct text_pos pos, startp; struct it it; int this_scroll_margin, scroll_max, rc, height; int dy = 0, amount_to_scroll = 0, scroll_down_p = 0; int extra_scroll_margin_lines = last_line_misfit ? 1 : 0; Lisp_Object aggressive; int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f); #if GLYPH_DEBUG debug_method_add (w, "try_scrolling"); #endif SET_TEXT_POS_FROM_MARKER (startp, w->start); /* Compute scroll margin height in pixels. We scroll when point is within this distance from the top or bottom of the window. */ if (scroll_margin > 0) this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4) * FRAME_LINE_HEIGHT (f); else this_scroll_margin = 0; /* Force scroll_conservatively to have a reasonable value, to avoid overflow while computing how much to scroll. Note that the user can supply scroll-conservatively equal to `most-positive-fixnum', which can be larger than INT_MAX. */ if (scroll_conservatively > scroll_limit) { scroll_conservatively = scroll_limit; scroll_max = INT_MAX; } else if (scroll_step || scroll_conservatively || temp_scroll_step) /* Compute how much we should try to scroll maximally to bring point into view. */ scroll_max = (max (scroll_step, max (scroll_conservatively, temp_scroll_step)) * FRAME_LINE_HEIGHT (f)); else if (NUMBERP (current_buffer->scroll_down_aggressively) || NUMBERP (current_buffer->scroll_up_aggressively)) /* We're trying to scroll because of aggressive scrolling but no scroll_step is set. Choose an arbitrary one. */ scroll_max = 10 * FRAME_LINE_HEIGHT (f); else scroll_max = 0; too_near_end: /* Decide whether to scroll down. */ if (PT > CHARPOS (startp)) { int scroll_margin_y; /* Compute the pixel ypos of the scroll margin, then move it to either that ypos or PT, whichever comes first. */ start_display (&it, w, startp); scroll_margin_y = it.last_visible_y - this_scroll_margin - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines; move_it_to (&it, PT, -1, scroll_margin_y - 1, -1, (MOVE_TO_POS | MOVE_TO_Y)); if (PT > CHARPOS (it.current.pos)) { int y0 = line_bottom_y (&it); /* Compute how many pixels below window bottom to stop searching for PT. This avoids costly search for PT that is far away if the user limited scrolling by a small number of lines, but always finds PT if scroll_conservatively is set to a large number, such as most-positive-fixnum. */ int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)); int y_to_move = slack >= INT_MAX - it.last_visible_y ? INT_MAX : it.last_visible_y + slack; /* Compute the distance from the scroll margin to PT or to the scroll limit, whichever comes first. This should include the height of the cursor line, to make that line fully visible. */ move_it_to (&it, PT, -1, y_to_move, -1, MOVE_TO_POS | MOVE_TO_Y); dy = line_bottom_y (&it) - y0; if (dy > scroll_max) return SCROLLING_FAILED; scroll_down_p = 1; } } if (scroll_down_p) { /* Point is in or below the bottom scroll margin, so move the window start down. If scrolling conservatively, move it just enough down to make point visible. If scroll_step is set, move it down by scroll_step. */ if (scroll_conservatively) amount_to_scroll = min (max (dy, FRAME_LINE_HEIGHT (f)), FRAME_LINE_HEIGHT (f) * scroll_conservatively); else if (scroll_step || temp_scroll_step) amount_to_scroll = scroll_max; else { aggressive = current_buffer->scroll_up_aggressively; height = WINDOW_BOX_TEXT_HEIGHT (w); if (NUMBERP (aggressive)) { double float_amount = XFLOATINT (aggressive) * height; amount_to_scroll = float_amount; if (amount_to_scroll == 0 && float_amount > 0) amount_to_scroll = 1; } } if (amount_to_scroll <= 0) return SCROLLING_FAILED; start_display (&it, w, startp); if (scroll_max < INT_MAX) move_it_vertically (&it, amount_to_scroll); else { /* Extra precision for users who set scroll-conservatively to most-positive-fixnum: make sure the amount we scroll the window start is never less than amount_to_scroll, which was computed as distance from window bottom to point. This matters when lines at window top and lines below window bottom have different height. */ struct it it1 = it; /* We use a temporary it1 because line_bottom_y can modify its argument, if it moves one line down; see there. */ int start_y = line_bottom_y (&it1); do { move_it_by_lines (&it, 1, 1); it1 = it; } while (line_bottom_y (&it1) - start_y < amount_to_scroll); } /* If STARTP is unchanged, move it down another screen line. */ if (CHARPOS (it.current.pos) == CHARPOS (startp)) move_it_by_lines (&it, 1, 1); startp = it.current.pos; } else { struct text_pos scroll_margin_pos = startp; /* See if point is inside the scroll margin at the top of the window. */ if (this_scroll_margin) { start_display (&it, w, startp); move_it_vertically (&it, this_scroll_margin); scroll_margin_pos = it.current.pos; } if (PT < CHARPOS (scroll_margin_pos)) { /* Point is in the scroll margin at the top of the window or above what is displayed in the window. */ int y0; /* Compute the vertical distance from PT to the scroll margin position. Give up if distance is greater than scroll_max. */ SET_TEXT_POS (pos, PT, PT_BYTE); start_display (&it, w, pos); y0 = it.current_y; move_it_to (&it, CHARPOS (scroll_margin_pos), 0, it.last_visible_y, -1, MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); dy = it.current_y - y0; if (dy > scroll_max) return SCROLLING_FAILED; /* Compute new window start. */ start_display (&it, w, startp); if (scroll_conservatively) amount_to_scroll = max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step)); else if (scroll_step || temp_scroll_step) amount_to_scroll = scroll_max; else { aggressive = current_buffer->scroll_down_aggressively; height = WINDOW_BOX_TEXT_HEIGHT (w); if (NUMBERP (aggressive)) { double float_amount = XFLOATINT (aggressive) * height; amount_to_scroll = float_amount; if (amount_to_scroll == 0 && float_amount > 0) amount_to_scroll = 1; } } if (amount_to_scroll <= 0) return SCROLLING_FAILED; move_it_vertically_backward (&it, amount_to_scroll); startp = it.current.pos; } } /* Run window scroll functions. */ startp = run_window_scroll_functions (window, startp); /* Display the window. Give up if new fonts are loaded, or if point doesn't appear. */ if (!try_window (window, startp, 0)) rc = SCROLLING_NEED_LARGER_MATRICES; else if (w->cursor.vpos < 0) { clear_glyph_matrix (w->desired_matrix); rc = SCROLLING_FAILED; } else { /* Maybe forget recorded base line for line number display. */ if (!just_this_one_p || current_buffer->clip_changed || BEG_UNCHANGED < CHARPOS (startp)) w->base_line_number = Qnil; /* If cursor ends up on a partially visible line, treat that as being off the bottom of the screen. */ if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0)) { clear_glyph_matrix (w->desired_matrix); ++extra_scroll_margin_lines; goto too_near_end; } rc = SCROLLING_SUCCESS; } return rc; }