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>
#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;
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,
return Qnil;
}
\f
-/* 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.
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;
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;