Avoid weird behavior with large horizontal scrolls.

Without this change, for example, large hscroll values would
mess up Emacs's display on Fedora 15 x86, presumably due to
overflows in int calculations in the display code.
Also, if buffers had long lines, Emacs would freeze.
* window.c (HSCROLL_MAX): Reduce to 100000, and make it visible to GDB.
(set_window_hscroll): New function, containing the old guts of
Fset_window_hscroll.  Return the clipped value.
(Fset_window_hscroll, Fscroll_left, Fscroll_right): Use it.
This avoids the need to check against PTRDIFF_MAX.
This commit is contained in:
Paul Eggert 2012-07-03 23:15:31 -07:00
parent dea7f1e5a4
commit 24a212eb23
2 changed files with 36 additions and 25 deletions

View file

@ -1,5 +1,16 @@
2012-07-04 Paul Eggert <eggert@cs.ucla.edu>
Avoid weird behavior with large horizontal scrolls.
Without this change, for example, large hscroll values would
mess up Emacs's display on Fedora 15 x86, presumably due to
overflows in int calculations in the display code.
Also, if buffers had long lines, Emacs would freeze.
* window.c (HSCROLL_MAX): Reduce to 100000, and make it visible to GDB.
(set_window_hscroll): New function, containing the old guts of
Fset_window_hscroll. Return the clipped value.
(Fset_window_hscroll, Fscroll_left, Fscroll_right): Use it.
This avoids the need to check against PTRDIFF_MAX.
* buffer.c (Fgenerate_new_buffer_name): Fix sprintf format mismatch.
2012-07-04 Dmitry Antipov <dmantipov@yandex.ru>

View file

@ -51,6 +51,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "nsterm.h"
#endif
/* Horizontal scrolling has problems with large scroll amounts.
It's too slow with long lines, and even with small lines the
display can be messed up. Impose a reasonable maximum. */
enum { HSCROLL_MAX = 100000 };
Lisp_Object Qwindowp, Qwindow_live_p;
static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
@ -670,27 +675,35 @@ WINDOW must be a live window and defaults to the selected one. */)
return make_number (decode_window (window)->hscroll);
}
/* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
range, returning the new amount as a fixnum. */
static Lisp_Object
set_window_hscroll (struct window *w, EMACS_INT hscroll)
{
int new_hscroll = clip_to_bounds (0, hscroll, HSCROLL_MAX);
/* Prevent redisplay shortcuts when changing the hscroll. */
if (w->hscroll != new_hscroll)
XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
w->hscroll = new_hscroll;
return make_number (new_hscroll);
}
DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
If WINDOW is nil, the selected window is used.
Return NCOL. NCOL should be zero or positive.
Clip the number to a reasonable value if out of range.
Return the new number. NCOL should be zero or positive.
Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
window so that the location of point moves off-window. */)
(Lisp_Object window, Lisp_Object ncol)
{
struct window *w = decode_window (window);
ptrdiff_t hscroll;
CHECK_NUMBER (ncol);
hscroll = clip_to_bounds (0, XINT (ncol), PTRDIFF_MAX);
/* Prevent redisplay shortcuts when changing the hscroll. */
if (w->hscroll != hscroll)
XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
w->hscroll = hscroll;
return ncol;
return set_window_hscroll (w, XINT (ncol));
}
DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
@ -4850,9 +4863,6 @@ specifies the window to scroll. This takes precedence over
return Qnil;
}
/* Scrolling amount must fit in both ptrdiff_t and Emacs fixnum. */
#define HSCROLL_MAX min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM)
DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
doc: /* Scroll selected window display ARG columns left.
Default for ARG is window width minus 2.
@ -4864,16 +4874,11 @@ will not scroll a window to a column less than the value returned
by this function. This happens in an interactive call. */)
(register Lisp_Object arg, Lisp_Object set_minimum)
{
Lisp_Object result;
ptrdiff_t hscroll;
struct window *w = XWINDOW (selected_window);
EMACS_INT requested_arg = (NILP (arg)
? window_body_cols (w) - 2
: XINT (Fprefix_numeric_value (arg)));
ptrdiff_t clipped_arg =
clip_to_bounds (- w->hscroll, requested_arg, HSCROLL_MAX - w->hscroll);
hscroll = w->hscroll + clipped_arg;
result = Fset_window_hscroll (selected_window, make_number (hscroll));
Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
@ -4892,16 +4897,11 @@ will not scroll a window to a column less than the value returned
by this function. This happens in an interactive call. */)
(register Lisp_Object arg, Lisp_Object set_minimum)
{
Lisp_Object result;
ptrdiff_t hscroll;
struct window *w = XWINDOW (selected_window);
EMACS_INT requested_arg = (NILP (arg)
? window_body_cols (w) - 2
: XINT (Fprefix_numeric_value (arg)));
ptrdiff_t clipped_arg =
clip_to_bounds (w->hscroll - HSCROLL_MAX, requested_arg, w->hscroll);
hscroll = w->hscroll - clipped_arg;
result = Fset_window_hscroll (selected_window, make_number (hscroll));
Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;