aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2012-07-03 23:15:31 -0700
committerPaul Eggert2012-07-03 23:15:31 -0700
commit24a212eb232e081c12f6b52429757657f0528e66 (patch)
tree47ad3a7628ff477f5d7e957b82f0a05ecb5ef7ab /src
parentdea7f1e5a400cfa9a42eef08be86cdc0992660b5 (diff)
downloademacs-24a212eb232e081c12f6b52429757657f0528e66.tar.gz
emacs-24a212eb232e081c12f6b52429757657f0528e66.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog11
-rw-r--r--src/window.c50
2 files changed, 36 insertions, 25 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index fdcab515f4f..e335c8de8d4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,16 @@
12012-07-04 Paul Eggert <eggert@cs.ucla.edu> 12012-07-04 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Avoid weird behavior with large horizontal scrolls.
4 Without this change, for example, large hscroll values would
5 mess up Emacs's display on Fedora 15 x86, presumably due to
6 overflows in int calculations in the display code.
7 Also, if buffers had long lines, Emacs would freeze.
8 * window.c (HSCROLL_MAX): Reduce to 100000, and make it visible to GDB.
9 (set_window_hscroll): New function, containing the old guts of
10 Fset_window_hscroll. Return the clipped value.
11 (Fset_window_hscroll, Fscroll_left, Fscroll_right): Use it.
12 This avoids the need to check against PTRDIFF_MAX.
13
3 * buffer.c (Fgenerate_new_buffer_name): Fix sprintf format mismatch. 14 * buffer.c (Fgenerate_new_buffer_name): Fix sprintf format mismatch.
4 15
52012-07-04 Dmitry Antipov <dmantipov@yandex.ru> 162012-07-04 Dmitry Antipov <dmantipov@yandex.ru>
diff --git a/src/window.c b/src/window.c
index af4aa85a3b2..a4369655640 100644
--- a/src/window.c
+++ b/src/window.c
@@ -51,6 +51,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
51#include "nsterm.h" 51#include "nsterm.h"
52#endif 52#endif
53 53
54/* Horizontal scrolling has problems with large scroll amounts.
55 It's too slow with long lines, and even with small lines the
56 display can be messed up. Impose a reasonable maximum. */
57enum { HSCROLL_MAX = 100000 };
58
54Lisp_Object Qwindowp, Qwindow_live_p; 59Lisp_Object Qwindowp, Qwindow_live_p;
55static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer; 60static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
56static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer; 61static 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. */)
670 return make_number (decode_window (window)->hscroll); 675 return make_number (decode_window (window)->hscroll);
671} 676}
672 677
678/* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
679 range, returning the new amount as a fixnum. */
680static Lisp_Object
681set_window_hscroll (struct window *w, EMACS_INT hscroll)
682{
683 int new_hscroll = clip_to_bounds (0, hscroll, HSCROLL_MAX);
684
685 /* Prevent redisplay shortcuts when changing the hscroll. */
686 if (w->hscroll != new_hscroll)
687 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
688
689 w->hscroll = new_hscroll;
690 return make_number (new_hscroll);
691}
692
673DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0, 693DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
674 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL. 694 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
675If WINDOW is nil, the selected window is used. 695If WINDOW is nil, the selected window is used.
676Return NCOL. NCOL should be zero or positive. 696Clip the number to a reasonable value if out of range.
697Return the new number. NCOL should be zero or positive.
677 698
678Note that if `automatic-hscrolling' is non-nil, you cannot scroll the 699Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
679window so that the location of point moves off-window. */) 700window so that the location of point moves off-window. */)
680 (Lisp_Object window, Lisp_Object ncol) 701 (Lisp_Object window, Lisp_Object ncol)
681{ 702{
682 struct window *w = decode_window (window); 703 struct window *w = decode_window (window);
683 ptrdiff_t hscroll;
684 704
685 CHECK_NUMBER (ncol); 705 CHECK_NUMBER (ncol);
686 hscroll = clip_to_bounds (0, XINT (ncol), PTRDIFF_MAX); 706 return set_window_hscroll (w, XINT (ncol));
687
688 /* Prevent redisplay shortcuts when changing the hscroll. */
689 if (w->hscroll != hscroll)
690 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
691
692 w->hscroll = hscroll;
693 return ncol;
694} 707}
695 708
696DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger, 709DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
@@ -4850,9 +4863,6 @@ specifies the window to scroll. This takes precedence over
4850 return Qnil; 4863 return Qnil;
4851} 4864}
4852 4865
4853/* Scrolling amount must fit in both ptrdiff_t and Emacs fixnum. */
4854#define HSCROLL_MAX min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM)
4855
4856DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np", 4866DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
4857 doc: /* Scroll selected window display ARG columns left. 4867 doc: /* Scroll selected window display ARG columns left.
4858Default for ARG is window width minus 2. 4868Default for ARG is window width minus 2.
@@ -4864,16 +4874,11 @@ will not scroll a window to a column less than the value returned
4864by this function. This happens in an interactive call. */) 4874by this function. This happens in an interactive call. */)
4865 (register Lisp_Object arg, Lisp_Object set_minimum) 4875 (register Lisp_Object arg, Lisp_Object set_minimum)
4866{ 4876{
4867 Lisp_Object result;
4868 ptrdiff_t hscroll;
4869 struct window *w = XWINDOW (selected_window); 4877 struct window *w = XWINDOW (selected_window);
4870 EMACS_INT requested_arg = (NILP (arg) 4878 EMACS_INT requested_arg = (NILP (arg)
4871 ? window_body_cols (w) - 2 4879 ? window_body_cols (w) - 2
4872 : XINT (Fprefix_numeric_value (arg))); 4880 : XINT (Fprefix_numeric_value (arg)));
4873 ptrdiff_t clipped_arg = 4881 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
4874 clip_to_bounds (- w->hscroll, requested_arg, HSCROLL_MAX - w->hscroll);
4875 hscroll = w->hscroll + clipped_arg;
4876 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4877 4882
4878 if (!NILP (set_minimum)) 4883 if (!NILP (set_minimum))
4879 w->min_hscroll = w->hscroll; 4884 w->min_hscroll = w->hscroll;
@@ -4892,16 +4897,11 @@ will not scroll a window to a column less than the value returned
4892by this function. This happens in an interactive call. */) 4897by this function. This happens in an interactive call. */)
4893 (register Lisp_Object arg, Lisp_Object set_minimum) 4898 (register Lisp_Object arg, Lisp_Object set_minimum)
4894{ 4899{
4895 Lisp_Object result;
4896 ptrdiff_t hscroll;
4897 struct window *w = XWINDOW (selected_window); 4900 struct window *w = XWINDOW (selected_window);
4898 EMACS_INT requested_arg = (NILP (arg) 4901 EMACS_INT requested_arg = (NILP (arg)
4899 ? window_body_cols (w) - 2 4902 ? window_body_cols (w) - 2
4900 : XINT (Fprefix_numeric_value (arg))); 4903 : XINT (Fprefix_numeric_value (arg)));
4901 ptrdiff_t clipped_arg = 4904 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
4902 clip_to_bounds (w->hscroll - HSCROLL_MAX, requested_arg, w->hscroll);
4903 hscroll = w->hscroll - clipped_arg;
4904 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4905 4905
4906 if (!NILP (set_minimum)) 4906 if (!NILP (set_minimum))
4907 w->min_hscroll = w->hscroll; 4907 w->min_hscroll = w->hscroll;