From c54aa1668ec5c2626b3f9a84513b00d90dcf24c1 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 7 Mar 2013 08:42:59 +0400 Subject: [PATCH] Avoid character to byte conversions in motion subroutines. * indent.h (compute_motion, vmotion): Add byte position argument. * indent.c (compute_motion): Use it and avoid CHAR_TO_BYTE. Add eassert. (Fcompute_motion): Break long line. Adjust call to compute_motion. Use list5 for return value. (vmotion): Use byte position argument and avoid call to CHAR_TO_BYTE. Adjust comments, style and calls to compute_motion. (Fvertical_motion): Adjust call to vmotion. * window.c (Fdelete_other_windows_internal): Record window start byte position and adjust call to vmotion. (window_scroll_line_based): Likewise with call to compute_motion. Use SET_PT_BOTH. (Frecenter): Adjust calls to vmotion. --- src/ChangeLog | 17 ++++++++++++ src/indent.c | 75 ++++++++++++++++++++++----------------------------- src/indent.h | 12 ++++----- src/window.c | 23 ++++++++-------- 4 files changed, 66 insertions(+), 61 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index eee20d998d..bc106df0cb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2013-03-07 Dmitry Antipov + + Avoid character to byte conversions in motion subroutines. + * indent.h (compute_motion, vmotion): Add byte position argument. + * indent.c (compute_motion): Use it and avoid CHAR_TO_BYTE. + Add eassert. + (Fcompute_motion): Break long line. Adjust call to compute_motion. + Use list5 for return value. + (vmotion): Use byte position argument and avoid call to CHAR_TO_BYTE. + Adjust comments, style and calls to compute_motion. + (Fvertical_motion): Adjust call to vmotion. + * window.c (Fdelete_other_windows_internal): Record window start + byte position and adjust call to vmotion. + (window_scroll_line_based): Likewise with call to compute_motion. + Use SET_PT_BOTH. + (Frecenter): Adjust calls to vmotion. + 2013-03-07 Dmitry Antipov * lisp.h (list2i, list3i): New functions. diff --git a/src/indent.c b/src/indent.c index abb4e08ad0..fd692f0b14 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1102,8 +1102,8 @@ static struct position val_compute_motion; the scroll bars if they are turned on. */ struct position * -compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, - bool did_motion, ptrdiff_t to, +compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos, + EMACS_INT fromhpos, bool did_motion, ptrdiff_t to, EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width, ptrdiff_t hscroll, int tab_offset, struct window *win) { @@ -1186,8 +1186,11 @@ compute_motion (ptrdiff_t from, EMACS_INT fromvpos, EMACS_INT fromhpos, immediate_quit = 1; QUIT; + /* It's just impossible to be too paranoid here. */ + eassert (from == BYTE_TO_CHAR (frombyte) && frombyte == CHAR_TO_BYTE (from)); + pos = prev_pos = from; - pos_byte = prev_pos_byte = CHAR_TO_BYTE (from); + pos_byte = prev_pos_byte = frombyte; contin_hpos = 0; prev_tab_offset = tab_offset; memset (&cmp_it, 0, sizeof cmp_it); @@ -1724,7 +1727,8 @@ of a certain window, pass the window's starting location as FROM and the window's upper-left coordinates as FROMPOS. Pass the buffer's (point-max) as TO, to limit the scan to the end of the visible section of the buffer, and pass LINE and COL as TOPOS. */) - (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, Lisp_Object width, Lisp_Object offsets, Lisp_Object window) + (Lisp_Object from, Lisp_Object frompos, Lisp_Object to, Lisp_Object topos, + Lisp_Object width, Lisp_Object offsets, Lisp_Object window) { struct window *w; Lisp_Object bufpos, hpos, vpos, prevhpos; @@ -1767,7 +1771,8 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) if (XINT (to) < BEGV || XINT (to) > ZV) args_out_of_range_3 (to, make_number (BEGV), make_number (ZV)); - pos = compute_motion (XINT (from), XINT (XCDR (frompos)), + pos = compute_motion (XINT (from), CHAR_TO_BYTE (XINT (from)), + XINT (XCDR (frompos)), XINT (XCAR (frompos)), 0, XINT (to), (NILP (topos) @@ -1789,28 +1794,23 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) XSETINT (vpos, pos->vpos); XSETINT (prevhpos, pos->prevhpos); - return Fcons (bufpos, - Fcons (hpos, - Fcons (vpos, - Fcons (prevhpos, - Fcons (pos->contin ? Qt : Qnil, Qnil))))); - + return list5 (bufpos, hpos, vpos, prevhpos, pos->contin ? Qt : Qnil); } - -/* Fvertical_motion and vmotion */ + +/* Fvertical_motion and vmotion. */ static struct position val_vmotion; struct position * -vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) +vmotion (register ptrdiff_t from, register ptrdiff_t from_byte, + register EMACS_INT vtarget, struct window *w) { ptrdiff_t hscroll = w->hscroll; struct position pos; - /* vpos is cumulative vertical position, changed as from is changed */ + /* VPOS is cumulative vertical position, changed as from is changed. */ register EMACS_INT vpos = 0; ptrdiff_t prevline; register ptrdiff_t first; - ptrdiff_t from_byte; ptrdiff_t lmargin = hscroll > 0 ? 1 - hscroll : 0; ptrdiff_t selective = (INTEGERP (BVAR (current_buffer, selective_display)) @@ -1854,29 +1854,24 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) text_prop_object), TEXT_PROP_MEANS_INVISIBLE (propval)))) prevline = find_newline_no_quit (prevline - 1, -1, &bytepos); - pos = *compute_motion (prevline, 0, - lmargin, - 0, - from, + pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from, /* Don't care for VPOS... */ 1 << (BITS_PER_SHORT - 1), /* ... nor HPOS. */ 1 << (BITS_PER_SHORT - 1), - -1, hscroll, - 0, - w); + -1, hscroll, 0, w); vpos -= pos.vpos; first = 0; from = prevline; + from_byte = bytepos; } - /* If we made exactly the desired vertical distance, - or if we hit beginning of buffer, - return point found */ + /* If we made exactly the desired vertical distance, or + if we hit beginning of buffer, return point found. */ if (vpos >= vtarget) { val_vmotion.bufpos = from; - val_vmotion.bytepos = CHAR_TO_BYTE (from); + val_vmotion.bytepos = from_byte; val_vmotion.vpos = vpos; val_vmotion.hpos = lmargin; val_vmotion.contin = 0; @@ -1884,11 +1879,12 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) return &val_vmotion; } - /* Otherwise find the correct spot by moving down */ + /* Otherwise find the correct spot by moving down. */ } - /* Moving downward is simple, but must calculate from beg of line - to determine hpos of starting point */ - from_byte = CHAR_TO_BYTE (from); + + /* Moving downward is simple, but must calculate from + beg of line to determine hpos of starting point. */ + if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n') { ptrdiff_t bytepos; @@ -1905,17 +1901,12 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) text_prop_object), TEXT_PROP_MEANS_INVISIBLE (propval)))) prevline = find_newline_no_quit (prevline - 1, -1, &bytepos); - pos = *compute_motion (prevline, 0, - lmargin, - 0, - from, + pos = *compute_motion (prevline, bytepos, 0, lmargin, 0, from, /* Don't care for VPOS... */ 1 << (BITS_PER_SHORT - 1), /* ... nor HPOS. */ 1 << (BITS_PER_SHORT - 1), - -1, hscroll, - 0, - w); + -1, hscroll, 0, w); did_motion = 1; } else @@ -1924,11 +1915,9 @@ vmotion (register ptrdiff_t from, register EMACS_INT vtarget, struct window *w) pos.vpos = 0; did_motion = 0; } - return compute_motion (from, vpos, pos.hpos, did_motion, + return compute_motion (from, from_byte, vpos, pos.hpos, did_motion, ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)), - -1, hscroll, - 0, - w); + -1, hscroll, 0, w); } DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0, @@ -1995,7 +1984,7 @@ whether or not it is currently displayed in some window. */) if (noninteractive) { struct position pos; - pos = *vmotion (PT, XINT (lines), w); + pos = *vmotion (PT, PT_BYTE, XINT (lines), w); SET_PT_BOTH (pos.bufpos, pos.bytepos); } else diff --git a/src/indent.h b/src/indent.h index acfd952754..4eb3fed6a1 100644 --- a/src/indent.h +++ b/src/indent.h @@ -26,14 +26,14 @@ struct position int contin; }; -struct position *compute_motion (ptrdiff_t from, EMACS_INT fromvpos, - EMACS_INT fromhpos, bool did_motion, - ptrdiff_t to, EMACS_INT tovpos, - EMACS_INT tohpos, +struct position *compute_motion (ptrdiff_t from, ptrdiff_t frombyte, + EMACS_INT fromvpos, EMACS_INT fromhpos, + bool did_motion, ptrdiff_t to, + EMACS_INT tovpos, EMACS_INT tohpos, EMACS_INT width, ptrdiff_t hscroll, int tab_offset, struct window *); -struct position *vmotion (ptrdiff_t from, EMACS_INT vtarget, - struct window *); +struct position *vmotion (ptrdiff_t from, ptrdiff_t from_byte, + EMACS_INT vtarget, struct window *); ptrdiff_t skip_invisible (ptrdiff_t pos, ptrdiff_t *next_boundary_p, ptrdiff_t to, Lisp_Object window); diff --git a/src/window.c b/src/window.c index ed0c1283ab..7769613151 100644 --- a/src/window.c +++ b/src/window.c @@ -2743,7 +2743,7 @@ window-start value is reasonable when this function is called. */) struct window *w, *r, *s; struct frame *f; Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta; - ptrdiff_t startpos IF_LINT (= 0); + ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0); int top IF_LINT (= 0), new_top, resize_failed; w = decode_valid_window (window); @@ -2782,6 +2782,7 @@ window-start value is reasonable when this function is called. */) if (!NILP (w->buffer)) { startpos = marker_position (w->start); + startbyte = marker_byte_position (w->start); top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))); /* Make sure WINDOW is the frame's selected window. */ @@ -2951,7 +2952,7 @@ window-start value is reasonable when this function is called. */) Fset_buffer (w->buffer); /* This computation used to temporarily move point, but that can have unwanted side effects due to text properties. */ - pos = *vmotion (startpos, -top, w); + pos = *vmotion (startpos, startbyte, -top, w); set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos); w->window_end_valid = 0; @@ -4748,7 +4749,8 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) register Lisp_Object tem; int lose; Lisp_Object bolp; - ptrdiff_t startpos; + ptrdiff_t startpos = marker_position (w->start); + ptrdiff_t startbyte = marker_byte_position (w->start); Lisp_Object original_pos = Qnil; /* If scrolling screen-fulls, compute the number of lines to @@ -4756,8 +4758,6 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) if (whole) n *= max (1, ht - next_screen_context_lines); - startpos = marker_position (w->start); - if (!NILP (Vscroll_preserve_screen_position)) { if (window_scroll_preserve_vpos <= 0 @@ -4765,10 +4765,8 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command))) { struct position posit - = *compute_motion (startpos, 0, 0, 0, - PT, ht, 0, - -1, w->hscroll, - 0, w); + = *compute_motion (startpos, startbyte, 0, 0, 0, + PT, ht, 0, -1, w->hscroll, 0, w); window_scroll_preserve_vpos = posit.vpos; window_scroll_preserve_hpos = posit.hpos + w->hscroll; } @@ -4784,9 +4782,10 @@ window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror) { Fvertical_motion (make_number (- (ht / 2)), window); startpos = PT; + startbyte = PT_BYTE; } - SET_PT (startpos); + SET_PT_BOTH (startpos, startbyte); lose = n < 0 && PT == BEGV; Fvertical_motion (make_number (n), window); pos = PT; @@ -5321,7 +5320,7 @@ and redisplay normally--don't erase and redraw the frame. */) iarg = max (iarg, this_scroll_margin); - pos = *vmotion (PT, -iarg, w); + pos = *vmotion (PT, PT_BYTE, -iarg, w); charpos = pos.bufpos; bytepos = pos.bytepos; } @@ -5340,7 +5339,7 @@ and redisplay normally--don't erase and redraw the frame. */) iarg = clip_to_bounds (this_scroll_margin, iarg, ht - this_scroll_margin - 1); - pos = *vmotion (PT, - iarg, w); + pos = *vmotion (PT, PT_BYTE, - iarg, w); charpos = pos.bufpos; bytepos = pos.bytepos; } -- 2.20.1