diff options
| author | Jim Blandy | 1994-10-08 22:14:04 +0000 |
|---|---|---|
| committer | Jim Blandy | 1994-10-08 22:14:04 +0000 |
| commit | 0aa01123caabb74724a77580e388586808a77767 (patch) | |
| tree | 024b25b896014def6696d6ce283ce60772a61571 /src | |
| parent | ef5623efbd9b2579aaef52f18d307281dd6d0a0a (diff) | |
| download | emacs-0aa01123caabb74724a77580e388586808a77767.tar.gz emacs-0aa01123caabb74724a77580e388586808a77767.zip | |
* indent.c: #include "region-cache.h".
(character_width, disptab_matches_widthtab, recompute_width_table,
width_run_cache_on_off): New functions.
(compute_motion): Call width_run_cache_on_off. If this buffer's
width run cache is enabled, consult it to see if we need to
traverse a region character-by-character; store information in the
cache after doing so. Call find_before_next_newline instead of
writing out an equivalent loop explicitly, to take advantage of
the newline cache.
Doc fixes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/indent.c | 385 |
1 files changed, 308 insertions, 77 deletions
diff --git a/src/indent.c b/src/indent.c index 4dacd1eddff..5e369e8d976 100644 --- a/src/indent.c +++ b/src/indent.c | |||
| @@ -28,6 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 28 | #include "termopts.h" | 28 | #include "termopts.h" |
| 29 | #include "disptab.h" | 29 | #include "disptab.h" |
| 30 | #include "intervals.h" | 30 | #include "intervals.h" |
| 31 | #include "region-cache.h" | ||
| 31 | 32 | ||
| 32 | /* Indentation can insert tabs if this is non-zero; | 33 | /* Indentation can insert tabs if this is non-zero; |
| 33 | otherwise always uses spaces */ | 34 | otherwise always uses spaces */ |
| @@ -64,6 +65,112 @@ buffer_display_table () | |||
| 64 | return 0; | 65 | return 0; |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 68 | /* Width run cache considerations. */ | ||
| 69 | |||
| 70 | /* Return the width of character C under display table DP. */ | ||
| 71 | static int | ||
| 72 | character_width (c, dp) | ||
| 73 | int c; | ||
| 74 | struct Lisp_Vector *dp; | ||
| 75 | { | ||
| 76 | Lisp_Object elt; | ||
| 77 | |||
| 78 | /* These width computations were determined by examining the cases | ||
| 79 | in display_text_line. */ | ||
| 80 | |||
| 81 | /* Some characters are never handled by the display table. */ | ||
| 82 | if (c == '\n' || c == '\t' || c == '\015') | ||
| 83 | return 0; | ||
| 84 | |||
| 85 | /* Everything else might be handled by the display table, if it's | ||
| 86 | present and the element is right. */ | ||
| 87 | else if (dp && (elt = DISP_CHAR_VECTOR (dp, c), | ||
| 88 | VECTORP (elt))) | ||
| 89 | return XVECTOR (elt)->size; | ||
| 90 | |||
| 91 | /* In the absence of display table perversities, printing characters | ||
| 92 | have width 1. */ | ||
| 93 | else if (c >= 040 && c < 0177) | ||
| 94 | return 1; | ||
| 95 | |||
| 96 | /* Everybody else (control characters, metacharacters) has other | ||
| 97 | widths. We could return their actual widths here, but they | ||
| 98 | depend on things like ctl_arrow and crud like that, and they're | ||
| 99 | not very common at all. So we'll just claim we don't know their | ||
| 100 | widths. */ | ||
| 101 | else | ||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | /* Return true iff the display table DISPTAB specifies the same widths | ||
| 106 | for characters as WIDTHTAB. We use this to decide when to | ||
| 107 | invalidate the buffer's width_run_cache. */ | ||
| 108 | int | ||
| 109 | disptab_matches_widthtab (disptab, widthtab) | ||
| 110 | struct Lisp_Vector *disptab; | ||
| 111 | struct Lisp_Vector *widthtab; | ||
| 112 | { | ||
| 113 | int i; | ||
| 114 | |||
| 115 | if (widthtab->size != 256) | ||
| 116 | abort (); | ||
| 117 | |||
| 118 | for (i = 0; i < 256; i++) | ||
| 119 | if (character_width (i, disptab) | ||
| 120 | != XFASTINT (widthtab->contents[i])) | ||
| 121 | return 0; | ||
| 122 | |||
| 123 | return 1; | ||
| 124 | } | ||
| 125 | |||
| 126 | /* Recompute BUF's width table, using the display table DISPTAB. */ | ||
| 127 | void | ||
| 128 | recompute_width_table (buf, disptab) | ||
| 129 | struct buffer *buf; | ||
| 130 | struct Lisp_Vector *disptab; | ||
| 131 | { | ||
| 132 | int i; | ||
| 133 | struct Lisp_Vector *widthtab | ||
| 134 | = (VECTORP (buf->width_table) | ||
| 135 | ? XVECTOR (buf->width_table) | ||
| 136 | : XVECTOR (Fmake_vector (make_number (256), make_number (0)))); | ||
| 137 | |||
| 138 | if (widthtab->size != 256) | ||
| 139 | abort (); | ||
| 140 | |||
| 141 | for (i = 0; i < 256; i++) | ||
| 142 | widthtab->contents[i] = character_width (i, disptab); | ||
| 143 | } | ||
| 144 | |||
| 145 | /* Allocate or free the width run cache, as requested by the current | ||
| 146 | state of current_buffer's cache_long_line_scans variable. */ | ||
| 147 | static void | ||
| 148 | width_run_cache_on_off () | ||
| 149 | { | ||
| 150 | if (NILP (current_buffer->cache_long_line_scans)) | ||
| 151 | { | ||
| 152 | /* It should be off. */ | ||
| 153 | if (current_buffer->width_run_cache) | ||
| 154 | { | ||
| 155 | free_region_cache (current_buffer->width_run_cache); | ||
| 156 | current_buffer->width_run_cache = 0; | ||
| 157 | current_buffer->width_table = Qnil; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | else | ||
| 161 | { | ||
| 162 | /* It should be on. */ | ||
| 163 | if (current_buffer->width_run_cache == 0) | ||
| 164 | { | ||
| 165 | current_buffer->width_run_cache = new_region_cache (); | ||
| 166 | current_buffer->width_table = Fmake_vector (make_number (256), | ||
| 167 | make_number (0)); | ||
| 168 | recompute_width_table (current_buffer, buffer_display_table ()); | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | |||
| 67 | DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0, | 174 | DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0, |
| 68 | "Return the horizontal position of point. Beginning of line is column 0.\n\ | 175 | "Return the horizontal position of point. Beginning of line is column 0.\n\ |
| 69 | This is calculated by adding together the widths of all the displayed\n\ | 176 | This is calculated by adding together the widths of all the displayed\n\ |
| @@ -173,7 +280,6 @@ current_column () | |||
| 173 | return col; | 280 | return col; |
| 174 | } | 281 | } |
| 175 | 282 | ||
| 176 | |||
| 177 | DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ", | 283 | DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ", |
| 178 | "Indent from point with tabs and spaces until COLUMN is reached.\n\ | 284 | "Indent from point with tabs and spaces until COLUMN is reached.\n\ |
| 179 | Optional second argument MIN says always do at least MIN spaces\n\ | 285 | Optional second argument MIN says always do at least MIN spaces\n\ |
| @@ -221,6 +327,7 @@ even if that goes past COLUMN; by default, MIN is zero.") | |||
| 221 | XSETINT (col, mincol); | 327 | XSETINT (col, mincol); |
| 222 | return col; | 328 | return col; |
| 223 | } | 329 | } |
| 330 | |||
| 224 | 331 | ||
| 225 | DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation, | 332 | DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation, |
| 226 | 0, 0, 0, | 333 | 0, 0, 0, |
| @@ -282,6 +389,7 @@ indented_beyond_p (pos, column) | |||
| 282 | pos = find_next_newline_no_quit (pos - 1, -1); | 389 | pos = find_next_newline_no_quit (pos - 1, -1); |
| 283 | return (position_indentation (pos) >= column); | 390 | return (position_indentation (pos) >= column); |
| 284 | } | 391 | } |
| 392 | |||
| 285 | 393 | ||
| 286 | DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, 0, | 394 | DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, 0, |
| 287 | "Move point to column COLUMN in the current line.\n\ | 395 | "Move point to column COLUMN in the current line.\n\ |
| @@ -379,13 +487,18 @@ and if COLUMN is in the middle of a tab character, change it to spaces.") | |||
| 379 | XSETFASTINT (val, col); | 487 | XSETFASTINT (val, col); |
| 380 | return val; | 488 | return val; |
| 381 | } | 489 | } |
| 490 | |||
| 382 | 491 | ||
| 492 | /* compute_motion: compute buffer posn given screen posn and vice versa */ | ||
| 493 | |||
| 383 | struct position val_compute_motion; | 494 | struct position val_compute_motion; |
| 384 | 495 | ||
| 385 | /* Scan the current buffer forward from offset FROM, pretending that | 496 | /* Scan the current buffer forward from offset FROM, pretending that |
| 386 | this is at line FROMVPOS, column FROMHPOS, until reaching buffer | 497 | this is at line FROMVPOS, column FROMHPOS, until reaching buffer |
| 387 | offset TO or line TOVPOS, column TOHPOS (whichever comes first), | 498 | offset TO or line TOVPOS, column TOHPOS (whichever comes first), |
| 388 | and return the ending buffer position and screen location. | 499 | and return the ending buffer position and screen location. If we |
| 500 | can't hit the requested column exactly (because of a tab or other | ||
| 501 | multi-column character), overshoot. | ||
| 389 | 502 | ||
| 390 | WIDTH is the number of columns available to display text; | 503 | WIDTH is the number of columns available to display text; |
| 391 | compute_motion uses this to handle continuation lines and such. | 504 | compute_motion uses this to handle continuation lines and such. |
| @@ -397,8 +510,14 @@ struct position val_compute_motion; | |||
| 397 | 510 | ||
| 398 | compute_motion returns a pointer to a struct position. The bufpos | 511 | compute_motion returns a pointer to a struct position. The bufpos |
| 399 | member gives the buffer position at the end of the scan, and hpos | 512 | member gives the buffer position at the end of the scan, and hpos |
| 400 | and vpos give its cartesian location. I'm not clear on what the | 513 | and vpos give its cartesian location. prevhpos is the column at |
| 401 | other members are. | 514 | which the character before bufpos started, and contin is non-zero |
| 515 | if we reached the current line by continuing the previous. | ||
| 516 | |||
| 517 | Note that FROMHPOS and TOHPOS should be expressed in real screen | ||
| 518 | columns, taking HSCROLL and the truncation glyph at the left margin | ||
| 519 | into account. That is, beginning-of-line moves you to the hpos | ||
| 520 | -HSCROLL + (HSCROLL > 0). | ||
| 402 | 521 | ||
| 403 | Note that FROMHPOS and TOHPOS should be expressed in real screen | 522 | Note that FROMHPOS and TOHPOS should be expressed in real screen |
| 404 | columns, taking HSCROLL and the truncation glyph at the left margin | 523 | columns, taking HSCROLL and the truncation glyph at the left margin |
| @@ -452,7 +571,7 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta | |||
| 452 | = (INTEGERP (current_buffer->selective_display) | 571 | = (INTEGERP (current_buffer->selective_display) |
| 453 | ? XINT (current_buffer->selective_display) | 572 | ? XINT (current_buffer->selective_display) |
| 454 | : !NILP (current_buffer->selective_display) ? -1 : 0); | 573 | : !NILP (current_buffer->selective_display) ? -1 : 0); |
| 455 | int prev_vpos, prev_hpos = 0; | 574 | int prev_vpos = vpos, prev_hpos = 0; |
| 456 | int selective_rlen | 575 | int selective_rlen |
| 457 | = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp)) | 576 | = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp)) |
| 458 | ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0); | 577 | ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0); |
| @@ -462,8 +581,30 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta | |||
| 462 | Lisp_Object prop, position; | 581 | Lisp_Object prop, position; |
| 463 | #endif | 582 | #endif |
| 464 | 583 | ||
| 584 | /* For computing runs of characters with similar widths. | ||
| 585 | Invariant: width_run_width is zero, or all the characters | ||
| 586 | from width_run_start to width_run_end have a fixed width of | ||
| 587 | width_run_width. */ | ||
| 588 | int width_run_start = from; | ||
| 589 | int width_run_end = from; | ||
| 590 | int width_run_width = 0; | ||
| 591 | Lisp_Object *width_table; | ||
| 592 | |||
| 593 | /* The next buffer pos where we should consult the width run cache. */ | ||
| 594 | int next_width_run = from; | ||
| 595 | |||
| 596 | width_run_cache_on_off (); | ||
| 597 | if (dp == buffer_display_table ()) | ||
| 598 | width_table = (VECTORP (current_buffer->width_table) | ||
| 599 | ? XVECTOR (current_buffer->width_table)->contents | ||
| 600 | : 0); | ||
| 601 | else | ||
| 602 | /* If the window has its own display table, we can't use the width | ||
| 603 | run cache, because that's based on the buffer's display table. */ | ||
| 604 | width_table = 0; | ||
| 605 | |||
| 465 | if (tab_width <= 0 || tab_width > 1000) tab_width = 8; | 606 | if (tab_width <= 0 || tab_width > 1000) tab_width = 8; |
| 466 | for (pos = from; pos < to; pos++) | 607 | for (pos = from; pos < to; ) |
| 467 | { | 608 | { |
| 468 | /* Stop if past the target screen position. */ | 609 | /* Stop if past the target screen position. */ |
| 469 | if (vpos > tovpos | 610 | if (vpos > tovpos |
| @@ -504,74 +645,158 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta | |||
| 504 | if (pos >= to) | 645 | if (pos >= to) |
| 505 | break; | 646 | break; |
| 506 | #endif | 647 | #endif |
| 507 | c = FETCH_CHAR (pos); | 648 | |
| 508 | if (c >= 040 && c < 0177 | 649 | /* Consult the width run cache to see if we can avoid inspecting |
| 509 | && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c)))) | 650 | the text character-by-character. */ |
| 510 | hpos++; | 651 | if (current_buffer->width_run_cache && pos >= next_width_run) |
| 511 | else if (c == '\t') | 652 | { |
| 512 | { | 653 | int run_end; |
| 513 | hpos += tab_width - ((hpos + tab_offset + hscroll - (hscroll > 0) | 654 | int common_width |
| 514 | /* Add tab_width here to make sure positive. | 655 | = region_cache_forward (current_buffer, |
| 515 | hpos can be negative after continuation | 656 | current_buffer->width_run_cache, |
| 516 | but can't be less than -tab_width. */ | 657 | pos, &run_end); |
| 517 | + tab_width) | 658 | |
| 518 | % tab_width); | 659 | /* A width of zero means the character's width varies (like |
| 519 | } | 660 | a tab), is meaningless (like a newline), or we just don't |
| 520 | else if (c == '\n') | 661 | want to skip over it for some other reason. */ |
| 521 | { | 662 | if (common_width != 0) |
| 522 | if (selective > 0 && indented_beyond_p (pos + 1, selective)) | 663 | { |
| 523 | { | 664 | int run_end_hpos; |
| 524 | /* Skip any number of invisible lines all at once */ | 665 | |
| 525 | do | 666 | /* Don't go past the final buffer posn the user |
| 526 | { | 667 | requested. */ |
| 527 | while (++pos < to && FETCH_CHAR (pos) != '\n'); | 668 | if (run_end > to) |
| 528 | } | 669 | run_end = to; |
| 529 | while (pos < to && indented_beyond_p (pos + 1, selective)); | 670 | |
| 530 | pos--; /* Reread the newline on the next pass. */ | 671 | run_end_hpos = hpos + (run_end - pos) * common_width; |
| 531 | /* Allow for the " ..." that is displayed for them. */ | 672 | |
| 532 | if (selective_rlen) | 673 | /* Don't go past the final horizontal position the user |
| 533 | { | 674 | requested. */ |
| 534 | hpos += selective_rlen; | 675 | if (vpos == tovpos && run_end_hpos > tohpos) |
| 535 | if (hpos >= width) | 676 | { |
| 536 | hpos = width; | 677 | run_end = pos + (tohpos - hpos) / common_width; |
| 537 | } | 678 | run_end_hpos = hpos + (run_end - pos) * common_width; |
| 538 | /* We have skipped the invis text, but not the newline after. */ | 679 | } |
| 539 | } | 680 | |
| 540 | else | 681 | /* Don't go past the margin. */ |
| 541 | { | 682 | if (run_end_hpos >= width) |
| 542 | /* A visible line. */ | 683 | { |
| 543 | vpos++; | 684 | run_end = pos + (width - hpos) / common_width; |
| 544 | hpos = 0; | 685 | run_end_hpos = hpos + (run_end - pos) * common_width; |
| 545 | hpos -= hscroll; | 686 | } |
| 546 | if (hscroll > 0) hpos++; /* Truncation glyph on column 0 */ | 687 | |
| 547 | tab_offset = 0; | 688 | hpos = run_end_hpos; |
| 548 | } | 689 | if (run_end > pos) |
| 549 | } | 690 | prev_hpos = hpos - common_width; |
| 550 | else if (c == CR && selective < 0) | 691 | pos = run_end; |
| 551 | { | 692 | } |
| 552 | /* In selective display mode, | 693 | |
| 553 | everything from a ^M to the end of the line is invisible */ | 694 | next_width_run = run_end + 1; |
| 554 | while (pos < to && FETCH_CHAR (pos) != '\n') pos++; | 695 | } |
| 555 | /* Stop *before* the real newline. */ | 696 | |
| 556 | pos--; | 697 | /* We have to scan the text character-by-character. */ |
| 557 | /* Allow for the " ..." that is displayed for them. */ | ||
| 558 | if (selective_rlen) | ||
| 559 | { | ||
| 560 | hpos += selective_rlen; | ||
| 561 | if (hpos >= width) | ||
| 562 | hpos = width; | ||
| 563 | } | ||
| 564 | } | ||
| 565 | else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) | ||
| 566 | hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; | ||
| 567 | else | 698 | else |
| 568 | hpos += (ctl_arrow && c < 0200) ? 2 : 4; | 699 | { |
| 700 | c = FETCH_CHAR (pos); | ||
| 701 | pos++; | ||
| 702 | |||
| 703 | /* Perhaps add some info to the width_run_cache. */ | ||
| 704 | if (current_buffer->width_run_cache) | ||
| 705 | { | ||
| 706 | /* Is this character part of the current run? If so, extend | ||
| 707 | the run. */ | ||
| 708 | if (pos - 1 == width_run_end | ||
| 709 | && width_table[c] == width_run_width) | ||
| 710 | width_run_end = pos; | ||
| 711 | |||
| 712 | /* The previous run is over, since this is a character at a | ||
| 713 | different position, or a different width. */ | ||
| 714 | else | ||
| 715 | { | ||
| 716 | /* Have we accumulated a run to put in the cache? | ||
| 717 | (Currently, we only cache runs of width == 1. */ | ||
| 718 | if (width_run_start < width_run_end | ||
| 719 | && width_run_width == 1) | ||
| 720 | know_region_cache (current_buffer, | ||
| 721 | current_buffer->width_run_cache, | ||
| 722 | width_run_start, width_run_end); | ||
| 723 | |||
| 724 | /* Start recording a new width run. */ | ||
| 725 | width_run_width = width_table[c]; | ||
| 726 | width_run_start = pos - 1; | ||
| 727 | width_run_end = pos; | ||
| 728 | } | ||
| 729 | } | ||
| 730 | |||
| 731 | if (c >= 040 && c < 0177 | ||
| 732 | && (dp == 0 || ! VECTORP (DISP_CHAR_VECTOR (dp, c)))) | ||
| 733 | hpos++; | ||
| 734 | else if (c == '\t') | ||
| 735 | { | ||
| 736 | hpos += tab_width - ((hpos + tab_offset + hscroll - (hscroll > 0) | ||
| 737 | /* Add tab_width here to make sure | ||
| 738 | positive. hpos can be negative | ||
| 739 | after continuation but can't be | ||
| 740 | less than -tab_width. */ | ||
| 741 | + tab_width) | ||
| 742 | % tab_width); | ||
| 743 | } | ||
| 744 | else if (c == '\n') | ||
| 745 | { | ||
| 746 | if (selective > 0 && indented_beyond_p (pos, selective)) | ||
| 747 | { | ||
| 748 | /* Skip any number of invisible lines all at once */ | ||
| 749 | do | ||
| 750 | pos = find_before_next_newline (pos, to, 1); | ||
| 751 | while (pos < to | ||
| 752 | && indented_beyond_p (pos, selective)); | ||
| 753 | /* Allow for the " ..." that is displayed for them. */ | ||
| 754 | if (selective_rlen) | ||
| 755 | { | ||
| 756 | hpos += selective_rlen; | ||
| 757 | if (hpos >= width) | ||
| 758 | hpos = width; | ||
| 759 | } | ||
| 760 | /* We have skipped the invis text, but not the | ||
| 761 | newline after. */ | ||
| 762 | } | ||
| 763 | else | ||
| 764 | { | ||
| 765 | /* A visible line. */ | ||
| 766 | vpos++; | ||
| 767 | hpos = 0; | ||
| 768 | hpos -= hscroll; | ||
| 769 | /* Count the truncation glyph on column 0 */ | ||
| 770 | if (hscroll > 0) | ||
| 771 | hpos++; | ||
| 772 | tab_offset = 0; | ||
| 773 | } | ||
| 774 | } | ||
| 775 | else if (c == CR && selective < 0) | ||
| 776 | { | ||
| 777 | /* In selective display mode, | ||
| 778 | everything from a ^M to the end of the line is invisible. | ||
| 779 | Stop *before* the real newline. */ | ||
| 780 | pos = find_before_next_newline (pos, to, 1); | ||
| 781 | /* Allow for the " ..." that is displayed for them. */ | ||
| 782 | if (selective_rlen) | ||
| 783 | { | ||
| 784 | hpos += selective_rlen; | ||
| 785 | if (hpos >= width) | ||
| 786 | hpos = width; | ||
| 787 | } | ||
| 788 | } | ||
| 789 | else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) | ||
| 790 | hpos += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; | ||
| 791 | else | ||
| 792 | hpos += (ctl_arrow && c < 0200) ? 2 : 4; | ||
| 793 | } | ||
| 569 | 794 | ||
| 570 | /* Handle right margin. */ | 795 | /* Handle right margin. */ |
| 571 | if (hpos >= width | 796 | if (hpos >= width |
| 572 | && (hpos > width | 797 | && (hpos > width |
| 573 | || (pos < ZV - 1 | 798 | || (pos < ZV |
| 574 | && FETCH_CHAR (pos + 1) != '\n'))) | 799 | && FETCH_CHAR (pos) != '\n'))) |
| 575 | { | 800 | { |
| 576 | if (vpos > tovpos | 801 | if (vpos > tovpos |
| 577 | || (vpos == tovpos && hpos >= tohpos)) | 802 | || (vpos == tovpos && hpos >= tohpos)) |
| @@ -582,8 +807,7 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta | |||
| 582 | || !NILP (current_buffer->truncate_lines)) | 807 | || !NILP (current_buffer->truncate_lines)) |
| 583 | { | 808 | { |
| 584 | /* Truncating: skip to newline. */ | 809 | /* Truncating: skip to newline. */ |
| 585 | while (pos < to && FETCH_CHAR (pos) != '\n') pos++; | 810 | pos = find_before_next_newline (pos, to, 1); |
| 586 | pos--; | ||
| 587 | hpos = width; | 811 | hpos = width; |
| 588 | } | 812 | } |
| 589 | else | 813 | else |
| @@ -597,6 +821,13 @@ compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, ta | |||
| 597 | } | 821 | } |
| 598 | } | 822 | } |
| 599 | 823 | ||
| 824 | /* Remember any final width run in the cache. */ | ||
| 825 | if (current_buffer->width_run_cache | ||
| 826 | && width_run_width == 1 | ||
| 827 | && width_run_start < width_run_end) | ||
| 828 | know_region_cache (current_buffer, current_buffer->width_run_cache, | ||
| 829 | width_run_start, width_run_end); | ||
| 830 | |||
| 600 | val_compute_motion.bufpos = pos; | 831 | val_compute_motion.bufpos = pos; |
| 601 | val_compute_motion.hpos = hpos; | 832 | val_compute_motion.hpos = hpos; |
| 602 | val_compute_motion.vpos = vpos; | 833 | val_compute_motion.vpos = vpos; |
| @@ -710,8 +941,8 @@ DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0, | |||
| 710 | 941 | ||
| 711 | } | 942 | } |
| 712 | 943 | ||
| 713 | /* Return the column of position POS in window W's buffer, | 944 | /* Return the column of position POS in window W's buffer. |
| 714 | rounded down to a multiple of the internal width of W. | 945 | The result is rounded down to a multiple of the internal width of W. |
| 715 | This is the amount of indentation of position POS | 946 | This is the amount of indentation of position POS |
| 716 | that is not visible in its horizontal position in the window. */ | 947 | that is not visible in its horizontal position in the window. */ |
| 717 | 948 | ||
| @@ -732,10 +963,8 @@ pos_tab_offset (w, pos) | |||
| 732 | return col - (col % width); | 963 | return col - (col % width); |
| 733 | } | 964 | } |
| 734 | 965 | ||
| 735 | /* start_hpos is the hpos of the first character of the buffer: | 966 | |
| 736 | zero except for the minibuffer window, | 967 | /* Fvertical_motion and vmotion */ |
| 737 | where it is the width of the prompt. */ | ||
| 738 | |||
| 739 | struct position val_vmotion; | 968 | struct position val_vmotion; |
| 740 | 969 | ||
| 741 | struct position * | 970 | struct position * |
| @@ -884,6 +1113,8 @@ if beginning or end of buffer was reached.") | |||
| 884 | return make_number (pos.vpos); | 1113 | return make_number (pos.vpos); |
| 885 | } | 1114 | } |
| 886 | 1115 | ||
| 1116 | /* file's initialization. */ | ||
| 1117 | |||
| 887 | syms_of_indent () | 1118 | syms_of_indent () |
| 888 | { | 1119 | { |
| 889 | DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode, | 1120 | DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode, |