diff options
| author | Gregory Heytings | 2022-07-08 21:22:52 +0000 |
|---|---|---|
| committer | Gregory Heytings | 2022-07-08 23:36:58 +0200 |
| commit | 1792cbaddc33772c344e45fb9478bee85fee66e7 (patch) | |
| tree | 6bc87aa85e8c14091ef00433a52d28b99d9d0d32 | |
| parent | 60e51595c8a89ffc34dbe0d36c75d1c119a7d5c5 (diff) | |
| download | emacs-1792cbaddc33772c344e45fb9478bee85fee66e7.tar.gz emacs-1792cbaddc33772c344e45fb9478bee85fee66e7.zip | |
Actually fix the long lines display bug (bug#56393).
* src/dispextern.h (struct it): New 'narrowed_begv' field.
* src/dispextern.h (WITH_NARROWED_BEGV): New macro.
* src/xdisp.c (get_narrowed_begv): New function.
(init_iterator): Initilize the 'narrowed_begv' field.
(back_to_previous_line_start, get_visually_first_element,
move_it_vertically_backward): Use the new macro.
* src/dispextern.h: Prototype of 'get_narrowed_begv'.
* src/window.c (window_body_height): Make it externally visible.
* src/window.h: Prototype of 'window_body_height'.
* src/composite.c (find_automatic_composition): Optimize display in buffers
with very long lines with 'get_narrowed_begv'.
* lisp/obsolete/longlines.el: Reobsolete longlines-mode.
* etc/NEWS: Announce the new minor mode, and remove the unobsoletion
indication for 'longlines-mode'.
* doc/emacs/trouble.texi (Long Lines): Remove the section.
(Lossage): Remove the entry for the Long Lines section.
* doc/emacs/emacs.texi (Top): Remove the entry for the Long Lines section.
| -rw-r--r-- | doc/emacs/emacs.texi | 1 | ||||
| -rw-r--r-- | doc/emacs/trouble.texi | 59 | ||||
| -rw-r--r-- | etc/NEWS | 22 | ||||
| -rw-r--r-- | lisp/obsolete/longlines.el (renamed from lisp/longlines.el) | 1 | ||||
| -rw-r--r-- | src/composite.c | 6 | ||||
| -rw-r--r-- | src/dispextern.h | 17 | ||||
| -rw-r--r-- | src/window.c | 2 | ||||
| -rw-r--r-- | src/window.h | 1 | ||||
| -rw-r--r-- | src/xdisp.c | 31 |
9 files changed, 63 insertions, 77 deletions
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index 5e72699bbe8..b43c966f872 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi | |||
| @@ -1190,7 +1190,6 @@ Dealing with Emacs Trouble | |||
| 1190 | * Crashing:: What Emacs does when it crashes. | 1190 | * Crashing:: What Emacs does when it crashes. |
| 1191 | * After a Crash:: Recovering editing in an Emacs session that crashed. | 1191 | * After a Crash:: Recovering editing in an Emacs session that crashed. |
| 1192 | * Emergency Escape:: What to do if Emacs stops responding. | 1192 | * Emergency Escape:: What to do if Emacs stops responding. |
| 1193 | * Long Lines:: Mitigating slowness due to extremely long lines. | ||
| 1194 | * DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. | 1193 | * DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. |
| 1195 | 1194 | ||
| 1196 | Reporting Bugs | 1195 | Reporting Bugs |
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi index f06b93759d8..887e5c6170f 100644 --- a/doc/emacs/trouble.texi +++ b/doc/emacs/trouble.texi | |||
| @@ -158,7 +158,6 @@ Emacs. | |||
| 158 | * Crashing:: What Emacs does when it crashes. | 158 | * Crashing:: What Emacs does when it crashes. |
| 159 | * After a Crash:: Recovering editing in an Emacs session that crashed. | 159 | * After a Crash:: Recovering editing in an Emacs session that crashed. |
| 160 | * Emergency Escape:: What to do if Emacs stops responding. | 160 | * Emergency Escape:: What to do if Emacs stops responding. |
| 161 | * Long Lines:: Mitigating slowness due to extremely long lines. | ||
| 162 | * DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. | 161 | * DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. |
| 163 | @end menu | 162 | @end menu |
| 164 | 163 | ||
| @@ -433,64 +432,6 @@ program. | |||
| 433 | emergency escape---but there are cases where it won't work, when a | 432 | emergency escape---but there are cases where it won't work, when a |
| 434 | system call hangs or when Emacs is stuck in a tight loop in C code. | 433 | system call hangs or when Emacs is stuck in a tight loop in C code. |
| 435 | 434 | ||
| 436 | @node Long Lines | ||
| 437 | @subsection Long Lines | ||
| 438 | @cindex long lines | ||
| 439 | |||
| 440 | For a variety of reasons (some of which are fundamental to the Emacs | ||
| 441 | redisplay code and the complex range of possibilities it handles; | ||
| 442 | others of which are due to modes and features which do not scale well | ||
| 443 | in unusual circumstances), Emacs can perform poorly when extremely | ||
| 444 | long lines are present (where ``extremely long'' usually means at | ||
| 445 | least many thousands of characters). | ||
| 446 | |||
| 447 | @cindex @code{so-long} mode | ||
| 448 | @findex global-so-long-mode | ||
| 449 | @vindex so-long-action | ||
| 450 | A particular problem is that Emacs may ``hang'' for a long time at | ||
| 451 | the point of visiting a file with extremely long lines. This can be | ||
| 452 | mitigated by enabling the @file{so-long} library, which detects when a | ||
| 453 | visited file contains abnormally long lines, and takes steps to | ||
| 454 | disable features which are liable to cause slowness in that situation. | ||
| 455 | To enable this library, type @kbd{M-x global-so-long-mode @key{RET}}, | ||
| 456 | or turn on the @code{global-so-long-mode} in your init file | ||
| 457 | (@pxref{Init File}), or customize the @code{global-so-long-mode} | ||
| 458 | option. You can tailor this mode's operation by customizing the | ||
| 459 | variable @code{so-long-action}. | ||
| 460 | |||
| 461 | The @file{so-long} library can also significantly improve | ||
| 462 | performance when moving and editing in a buffer with long lines. | ||
| 463 | Performance is still likely to degrade as you get deeper into the long | ||
| 464 | lines, but the improvements from using this library can nevertheless | ||
| 465 | be substantial. | ||
| 466 | |||
| 467 | @findex so-long-commentary | ||
| 468 | Use @kbd{M-x so-long-commentary} to view the documentation for this | ||
| 469 | library and learn more about how to enable and configure it. | ||
| 470 | |||
| 471 | @vindex max-redisplay-ticks | ||
| 472 | If even @code{so-long-mode} doesn't help making Emacs responsive | ||
| 473 | enough, or if you'd rather not disable the display-related features | ||
| 474 | that @code{so-long-mode} turns off, you can instead customize the | ||
| 475 | variable @code{max-redisplay-ticks} to a non-zero value. Then Emacs | ||
| 476 | will abort redisplay of a window and commands, like @kbd{C-n} and | ||
| 477 | @kbd{M-v}, which use the display code to do their job, if processing a | ||
| 478 | window needs more low-level display operations than the value of this | ||
| 479 | variable. The display of the offending window will then remain | ||
| 480 | outdated, and possibly incomplete, on the screen, but Emacs should | ||
| 481 | otherwise be responsive, and you could then switch to another buffer, | ||
| 482 | or kill the problematic buffer, or turn on @code{so-long-mode} or | ||
| 483 | @code{so-long-minor-mode} in that buffer. When the display of a | ||
| 484 | window is aborted due to this reason, the buffer shown in that window | ||
| 485 | will not have any of its windows redisplayed until the buffer is | ||
| 486 | modified or until you type @kbd{C-l} (@pxref{Recentering}) in one of | ||
| 487 | that buffer's windows. | ||
| 488 | |||
| 489 | If you decide to customize this variable to a non-zero value, we | ||
| 490 | recommend to use a value between 100,000 and 1,000,000, depending on | ||
| 491 | your patience and the speed of your system. The default value is | ||
| 492 | zero, which disables this feature. | ||
| 493 | |||
| 494 | @node DEL Does Not Delete | 435 | @node DEL Does Not Delete |
| 495 | @subsection If @key{DEL} Fails to Delete | 436 | @subsection If @key{DEL} Fails to Delete |
| 496 | @cindex @key{DEL} vs @key{BACKSPACE} | 437 | @cindex @key{DEL} vs @key{BACKSPACE} |
| @@ -325,7 +325,14 @@ startup. Previously, these functions ignored | |||
| 325 | * Changes in Emacs 29.1 | 325 | * Changes in Emacs 29.1 |
| 326 | 326 | ||
| 327 | --- | 327 | --- |
| 328 | ** 'longlines-mode' is no longer obsolete. | 328 | ** Emacs is now capable of editing files with arbitarily long lines. |
| 329 | The display of long lines has been optimized, and Emacs no longer | ||
| 330 | chokes when a buffer on display contains long lines. If you still | ||
| 331 | experience slowdowns while editing files with long lines, this is | ||
| 332 | either due to font locking, which you can turn off with M-x | ||
| 333 | font-lock-mode, or to the current major mode or one of the enabled | ||
| 334 | minor modes, in which case you should open the the file with M-x | ||
| 335 | find-file-literally instead of C-x C-f. | ||
| 329 | 336 | ||
| 330 | +++ | 337 | +++ |
| 331 | ** New command to change the font size globally. | 338 | ** New command to change the font size globally. |
| @@ -347,10 +354,10 @@ Get the parent directory of a file. | |||
| 347 | This variable is used by some operations (mostly syntax-propertization | 354 | This variable is used by some operations (mostly syntax-propertization |
| 348 | and font-locking) to treat lines longer than this variable as if they | 355 | and font-locking) to treat lines longer than this variable as if they |
| 349 | were made up of various smaller lines. This can help reduce the | 356 | were made up of various smaller lines. This can help reduce the |
| 350 | pathological slowdowns seen in buffers made of a single long line, but | 357 | slowdowns seen in buffers made of a single long line, but can also |
| 351 | can also cause misbehavior in the presence of such long lines (tho | 358 | cause misbehavior in the presence of such long lines (tho most of that |
| 352 | most of that misbehavior should usually be limited to mis-highlighting). | 359 | misbehavior should usually be limited to mis-highlighting). You can |
| 353 | You can recover the previous behavior with: | 360 | recover the previous behavior with: |
| 354 | 361 | ||
| 355 | (setq syntax-wholeline-max most-positive-fixnum) | 362 | (setq syntax-wholeline-max most-positive-fixnum) |
| 356 | 363 | ||
| @@ -463,11 +470,6 @@ previous behavior). The default is nil, which inhibits recording of | |||
| 463 | passwords. | 470 | passwords. |
| 464 | 471 | ||
| 465 | +++ | 472 | +++ |
| 466 | ** New user option 'longlines-breakpoint-chars'. | ||
| 467 | This is a string containing chars that could be used as breakpoint in | ||
| 468 | longlines mode. | ||
| 469 | |||
| 470 | +++ | ||
| 471 | ** New function 'command-query'. | 473 | ** New function 'command-query'. |
| 472 | This function makes its argument command prompt the user for | 474 | This function makes its argument command prompt the user for |
| 473 | confirmation before executing. | 475 | confirmation before executing. |
diff --git a/lisp/longlines.el b/lisp/obsolete/longlines.el index a6cf93a0394..d44a634e2e0 100644 --- a/lisp/longlines.el +++ b/lisp/obsolete/longlines.el | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | ;; Alex Schroeder <alex@gnu.org> | 6 | ;; Alex Schroeder <alex@gnu.org> |
| 7 | ;; Chong Yidong <cyd@stupidchicken.com> | 7 | ;; Chong Yidong <cyd@stupidchicken.com> |
| 8 | ;; Maintainer: emacs-devel@gnu.org | 8 | ;; Maintainer: emacs-devel@gnu.org |
| 9 | ;; Obsolete-since: 24.4 | ||
| 9 | ;; Keywords: convenience, wp | 10 | ;; Keywords: convenience, wp |
| 10 | 11 | ||
| 11 | ;; This file is part of GNU Emacs. | 12 | ;; This file is part of GNU Emacs. |
diff --git a/src/composite.c b/src/composite.c index 4d69702171f..d8998b5a1f3 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -1576,6 +1576,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim, | |||
| 1576 | Lisp_Object window; | 1576 | Lisp_Object window; |
| 1577 | struct window *w; | 1577 | struct window *w; |
| 1578 | bool need_adjustment = 0; | 1578 | bool need_adjustment = 0; |
| 1579 | ptrdiff_t narrowed_begv; | ||
| 1579 | 1580 | ||
| 1580 | window = Fget_buffer_window (Fcurrent_buffer (), Qnil); | 1581 | window = Fget_buffer_window (Fcurrent_buffer (), Qnil); |
| 1581 | if (NILP (window)) | 1582 | if (NILP (window)) |
| @@ -1586,6 +1587,11 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim, | |||
| 1586 | if (NILP (string)) | 1587 | if (NILP (string)) |
| 1587 | { | 1588 | { |
| 1588 | head = backlim < 0 ? BEGV : backlim, tail = ZV, stop = GPT; | 1589 | head = backlim < 0 ? BEGV : backlim, tail = ZV, stop = GPT; |
| 1590 | /* In buffers with very long lines, this function becomes very | ||
| 1591 | slow. Pretend that the buffer is narrowed to make it fast. */ | ||
| 1592 | narrowed_begv = get_narrowed_begv (w); | ||
| 1593 | if (pos > narrowed_begv) | ||
| 1594 | head = narrowed_begv; | ||
| 1589 | cur.pos_byte = CHAR_TO_BYTE (cur.pos); | 1595 | cur.pos_byte = CHAR_TO_BYTE (cur.pos); |
| 1590 | cur.p = BYTE_POS_ADDR (cur.pos_byte); | 1596 | cur.p = BYTE_POS_ADDR (cur.pos_byte); |
| 1591 | } | 1597 | } |
diff --git a/src/dispextern.h b/src/dispextern.h index ca7834dec55..2edf4b73f81 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -2332,6 +2332,10 @@ struct it | |||
| 2332 | with which display_string was called. */ | 2332 | with which display_string was called. */ |
| 2333 | ptrdiff_t end_charpos; | 2333 | ptrdiff_t end_charpos; |
| 2334 | 2334 | ||
| 2335 | /* Alternate begin position of the buffer, which is used to optimize | ||
| 2336 | display (see the WITH_NARROWED_BEGV macro below). */ | ||
| 2337 | ptrdiff_t narrowed_begv; | ||
| 2338 | |||
| 2335 | /* C string to iterate over. Non-null means get characters from | 2339 | /* C string to iterate over. Non-null means get characters from |
| 2336 | this string, otherwise characters are read from current_buffer | 2340 | this string, otherwise characters are read from current_buffer |
| 2337 | or it->string. */ | 2341 | or it->string. */ |
| @@ -2813,6 +2817,18 @@ struct it | |||
| 2813 | reset_box_start_end_flags ((IT)); \ | 2817 | reset_box_start_end_flags ((IT)); \ |
| 2814 | } while (false) | 2818 | } while (false) |
| 2815 | 2819 | ||
| 2820 | /* Execute STATEMENT with a temporarily narrowed buffer. */ | ||
| 2821 | |||
| 2822 | #define WITH_NARROWED_BEGV(STATEMENT) \ | ||
| 2823 | do { \ | ||
| 2824 | ptrdiff_t obegv = BEGV; \ | ||
| 2825 | if (it->narrowed_begv) \ | ||
| 2826 | SET_BUF_BEGV (current_buffer, it->narrowed_begv); \ | ||
| 2827 | STATEMENT; \ | ||
| 2828 | if (it->narrowed_begv) \ | ||
| 2829 | SET_BUF_BEGV (current_buffer, obegv); \ | ||
| 2830 | } while (0) | ||
| 2831 | |||
| 2816 | /* Bit-flags indicating what operation move_it_to should perform. */ | 2832 | /* Bit-flags indicating what operation move_it_to should perform. */ |
| 2817 | 2833 | ||
| 2818 | enum move_operation_enum | 2834 | enum move_operation_enum |
| @@ -3396,6 +3412,7 @@ void mark_window_display_accurate (Lisp_Object, bool); | |||
| 3396 | void redisplay_preserve_echo_area (int); | 3412 | void redisplay_preserve_echo_area (int); |
| 3397 | void init_iterator (struct it *, struct window *, ptrdiff_t, | 3413 | void init_iterator (struct it *, struct window *, ptrdiff_t, |
| 3398 | ptrdiff_t, struct glyph_row *, enum face_id); | 3414 | ptrdiff_t, struct glyph_row *, enum face_id); |
| 3415 | ptrdiff_t get_narrowed_begv (struct window *w); | ||
| 3399 | void init_iterator_to_row_start (struct it *, struct window *, | 3416 | void init_iterator_to_row_start (struct it *, struct window *, |
| 3400 | struct glyph_row *); | 3417 | struct glyph_row *); |
| 3401 | void start_display (struct it *, struct window *, struct text_pos); | 3418 | void start_display (struct it *, struct window *, struct text_pos); |
diff --git a/src/window.c b/src/window.c index af463b90ce6..61ca9feb64d 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -1028,7 +1028,7 @@ window_body_unit_from_symbol (Lisp_Object unit) | |||
| 1028 | /* Return the number of lines/pixels of W's body. Don't count any mode | 1028 | /* Return the number of lines/pixels of W's body. Don't count any mode |
| 1029 | or header line or horizontal divider of W. Rounds down to nearest | 1029 | or header line or horizontal divider of W. Rounds down to nearest |
| 1030 | integer when not working pixelwise. */ | 1030 | integer when not working pixelwise. */ |
| 1031 | static int | 1031 | int |
| 1032 | window_body_height (struct window *w, enum window_body_unit pixelwise) | 1032 | window_body_height (struct window *w, enum window_body_unit pixelwise) |
| 1033 | { | 1033 | { |
| 1034 | int height = (w->pixel_height | 1034 | int height = (w->pixel_height |
diff --git a/src/window.h b/src/window.h index 298a80a5366..c63b1b24d4f 100644 --- a/src/window.h +++ b/src/window.h | |||
| @@ -1193,6 +1193,7 @@ enum window_body_unit | |||
| 1193 | WINDOW_BODY_IN_REMAPPED_CHARS | 1193 | WINDOW_BODY_IN_REMAPPED_CHARS |
| 1194 | }; | 1194 | }; |
| 1195 | extern int window_body_width (struct window *w, enum window_body_unit); | 1195 | extern int window_body_width (struct window *w, enum window_body_unit); |
| 1196 | extern int window_body_height (struct window *w, enum window_body_unit); | ||
| 1196 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; | 1197 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; |
| 1197 | extern int window_scroll_margin (struct window *, enum margin_unit); | 1198 | extern int window_scroll_margin (struct window *, enum margin_unit); |
| 1198 | extern void temp_output_buffer_show (Lisp_Object); | 1199 | extern void temp_output_buffer_show (Lisp_Object); |
diff --git a/src/xdisp.c b/src/xdisp.c index 4089525e10f..e130b23d9a1 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -3425,6 +3425,8 @@ init_iterator (struct it *it, struct window *w, | |||
| 3425 | } | 3425 | } |
| 3426 | } | 3426 | } |
| 3427 | 3427 | ||
| 3428 | it->narrowed_begv = get_narrowed_begv (w); | ||
| 3429 | |||
| 3428 | /* If a buffer position was specified, set the iterator there, | 3430 | /* If a buffer position was specified, set the iterator there, |
| 3429 | getting overlays and face properties from that position. */ | 3431 | getting overlays and face properties from that position. */ |
| 3430 | if (charpos >= BUF_BEG (current_buffer)) | 3432 | if (charpos >= BUF_BEG (current_buffer)) |
| @@ -3491,6 +3493,19 @@ init_iterator (struct it *it, struct window *w, | |||
| 3491 | CHECK_IT (it); | 3493 | CHECK_IT (it); |
| 3492 | } | 3494 | } |
| 3493 | 3495 | ||
| 3496 | /* Compute a suitable value for BEGV that can be used temporarily, to | ||
| 3497 | optimize display, for the buffer in window W. */ | ||
| 3498 | |||
| 3499 | ptrdiff_t | ||
| 3500 | get_narrowed_begv (struct window *w) | ||
| 3501 | { | ||
| 3502 | int len, begv; | ||
| 3503 | len = (1 + ((window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) * | ||
| 3504 | window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS)) / | ||
| 3505 | 10000)) * 10000; | ||
| 3506 | begv = max ((PT / len - 2) * len, BEGV); | ||
| 3507 | return begv == BEGV ? 0 : begv; | ||
| 3508 | } | ||
| 3494 | 3509 | ||
| 3495 | /* Initialize IT for the display of window W with window start POS. */ | 3510 | /* Initialize IT for the display of window W with window start POS. */ |
| 3496 | 3511 | ||
| @@ -6992,7 +7007,8 @@ back_to_previous_line_start (struct it *it) | |||
| 6992 | ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); | 7007 | ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); |
| 6993 | 7008 | ||
| 6994 | dec_both (&cp, &bp); | 7009 | dec_both (&cp, &bp); |
| 6995 | IT_CHARPOS (*it) = find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)); | 7010 | WITH_NARROWED_BEGV (IT_CHARPOS (*it) = |
| 7011 | find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it))); | ||
| 6996 | } | 7012 | } |
| 6997 | 7013 | ||
| 6998 | 7014 | ||
| @@ -8623,7 +8639,9 @@ get_visually_first_element (struct it *it) | |||
| 8623 | { | 8639 | { |
| 8624 | bool string_p = STRINGP (it->string) || it->s; | 8640 | bool string_p = STRINGP (it->string) || it->s; |
| 8625 | ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV); | 8641 | ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV); |
| 8626 | ptrdiff_t bob = (string_p ? 0 : BEGV); | 8642 | ptrdiff_t bob; |
| 8643 | |||
| 8644 | WITH_NARROWED_BEGV (bob = (string_p ? 0 : BEGV)); | ||
| 8627 | 8645 | ||
| 8628 | if (STRINGP (it->string)) | 8646 | if (STRINGP (it->string)) |
| 8629 | { | 8647 | { |
| @@ -8663,9 +8681,10 @@ get_visually_first_element (struct it *it) | |||
| 8663 | if (string_p) | 8681 | if (string_p) |
| 8664 | it->bidi_it.charpos = it->bidi_it.bytepos = 0; | 8682 | it->bidi_it.charpos = it->bidi_it.bytepos = 0; |
| 8665 | else | 8683 | else |
| 8666 | it->bidi_it.charpos = find_newline_no_quit (IT_CHARPOS (*it), | 8684 | WITH_NARROWED_BEGV (it->bidi_it.charpos = |
| 8667 | IT_BYTEPOS (*it), -1, | 8685 | find_newline_no_quit (IT_CHARPOS (*it), |
| 8668 | &it->bidi_it.bytepos); | 8686 | IT_BYTEPOS (*it), -1, |
| 8687 | &it->bidi_it.bytepos)); | ||
| 8669 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true); | 8688 | bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true); |
| 8670 | do | 8689 | do |
| 8671 | { | 8690 | { |
| @@ -10583,7 +10602,7 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 10583 | ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); | 10602 | ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); |
| 10584 | 10603 | ||
| 10585 | dec_both (&cp, &bp); | 10604 | dec_both (&cp, &bp); |
| 10586 | cp = find_newline_no_quit (cp, bp, -1, NULL); | 10605 | WITH_NARROWED_BEGV (cp = find_newline_no_quit (cp, bp, -1, NULL)); |
| 10587 | move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS); | 10606 | move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS); |
| 10588 | } | 10607 | } |
| 10589 | bidi_unshelve_cache (it3data, true); | 10608 | bidi_unshelve_cache (it3data, true); |