Mercurial > vim
comparison src/charset.c @ 29678:fc0f93590fd4 v9.0.0179
patch 9.0.0179: cursor pos wrong with wrapping virtual text in empty line
Commit: https://github.com/vim/vim/commit/49a90792d950c51608d0459ef8699fe921070718
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Aug 9 18:25:23 2022 +0100
patch 9.0.0179: cursor pos wrong with wrapping virtual text in empty line
Problem: Cursor position wrong with wrapping virtual text in empty line.
Solution: Adjust handling of an empty line. (closes https://github.com/vim/vim/issues/10875)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 09 Aug 2022 19:30:03 +0200 |
parents | b4fea827c20a |
children | 538204fce2a4 |
comparison
equal
deleted
inserted
replaced
29677:d8ad7b1e9116 | 29678:fc0f93590fd4 |
---|---|
757 chartabsize_T cts; | 757 chartabsize_T cts; |
758 | 758 |
759 init_chartabsize_arg(&cts, curwin, 0, startcol, s, s); | 759 init_chartabsize_arg(&cts, curwin, 0, startcol, s, s); |
760 while (*cts.cts_ptr != NUL) | 760 while (*cts.cts_ptr != NUL) |
761 cts.cts_vcol += lbr_chartabsize_adv(&cts); | 761 cts.cts_vcol += lbr_chartabsize_adv(&cts); |
762 #ifdef FEAT_PROP_POPUP | |
763 if (cts.cts_has_prop_with_text && cts.cts_ptr == cts.cts_line) | |
764 { | |
765 // check for virtual text in an empty line | |
766 (void)lbr_chartabsize_adv(&cts); | |
767 cts.cts_vcol += cts.cts_cur_text_width; | |
768 } | |
769 #endif | |
762 clear_chartabsize_arg(&cts); | 770 clear_chartabsize_arg(&cts); |
763 return (int)cts.cts_vcol; | 771 return (int)cts.cts_vcol; |
764 } | 772 } |
765 | 773 |
766 /* | 774 /* |
770 win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len) | 778 win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len) |
771 { | 779 { |
772 chartabsize_T cts; | 780 chartabsize_T cts; |
773 | 781 |
774 init_chartabsize_arg(&cts, wp, lnum, 0, line, line); | 782 init_chartabsize_arg(&cts, wp, lnum, 0, line, line); |
775 #ifdef FEAT_PROP_POPUP | 783 win_linetabsize_cts(&cts, len); |
776 cts.cts_with_trailing = len == MAXCOL; | |
777 #endif | |
778 for ( ; *cts.cts_ptr != NUL && (len == MAXCOL || cts.cts_ptr < line + len); | |
779 MB_PTR_ADV(cts.cts_ptr)) | |
780 cts.cts_vcol += win_lbr_chartabsize(&cts, NULL); | |
781 clear_chartabsize_arg(&cts); | 784 clear_chartabsize_arg(&cts); |
782 return (int)cts.cts_vcol; | 785 return (int)cts.cts_vcol; |
786 } | |
787 | |
788 void | |
789 win_linetabsize_cts(chartabsize_T *cts, colnr_T len) | |
790 { | |
791 #ifdef FEAT_PROP_POPUP | |
792 cts->cts_with_trailing = len == MAXCOL; | |
793 #endif | |
794 for ( ; *cts->cts_ptr != NUL && (len == MAXCOL || cts->cts_ptr < cts->cts_line + len); | |
795 MB_PTR_ADV(cts->cts_ptr)) | |
796 cts->cts_vcol += win_lbr_chartabsize(cts, NULL); | |
797 #ifdef FEAT_PROP_POPUP | |
798 // check for a virtual text on an empty line | |
799 if (cts->cts_has_prop_with_text && *cts->cts_ptr == NUL | |
800 && cts->cts_ptr == cts->cts_line) | |
801 { | |
802 (void)win_lbr_chartabsize(cts, NULL); | |
803 cts->cts_vcol += cts->cts_cur_text_width; | |
804 } | |
805 #endif | |
783 } | 806 } |
784 | 807 |
785 /* | 808 /* |
786 * Return TRUE if 'c' is a normal identifier character: | 809 * Return TRUE if 'c' is a normal identifier character: |
787 * Letters and characters from the 'isident' option. | 810 * Letters and characters from the 'isident' option. |
1126 * First get the normal size, without 'linebreak' or text properties | 1149 * First get the normal size, without 'linebreak' or text properties |
1127 */ | 1150 */ |
1128 size = win_chartabsize(wp, s, vcol); | 1151 size = win_chartabsize(wp, s, vcol); |
1129 | 1152 |
1130 # ifdef FEAT_PROP_POPUP | 1153 # ifdef FEAT_PROP_POPUP |
1131 if (cts->cts_has_prop_with_text && *line != NUL) | 1154 if (cts->cts_has_prop_with_text) |
1132 { | 1155 { |
1133 int tab_size = size; | 1156 int tab_size = size; |
1134 int charlen = mb_ptr2len(s); | 1157 int charlen = *s == NUL ? 1 : mb_ptr2len(s); |
1135 int i; | 1158 int i; |
1136 int col = (int)(s - line); | 1159 int col = (int)(s - line); |
1137 garray_T *gap = &wp->w_buffer->b_textprop_text; | 1160 garray_T *gap = &wp->w_buffer->b_textprop_text; |
1138 | 1161 |
1139 for (i = 0; i < cts->cts_text_prop_count; ++i) | 1162 for (i = 0; i < cts->cts_text_prop_count; ++i) |
1410 int *vts = wp->w_buffer->b_p_vts_array; | 1433 int *vts = wp->w_buffer->b_p_vts_array; |
1411 #endif | 1434 #endif |
1412 int ts = wp->w_buffer->b_p_ts; | 1435 int ts = wp->w_buffer->b_p_ts; |
1413 int c; | 1436 int c; |
1414 chartabsize_T cts; | 1437 chartabsize_T cts; |
1438 #ifdef FEAT_PROP_POPUP | |
1439 int on_NUL = FALSE; | |
1440 #endif | |
1415 | 1441 |
1416 vcol = 0; | 1442 vcol = 0; |
1417 line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE); | 1443 line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE); |
1418 if (pos->col == MAXCOL) | 1444 if (pos->col == MAXCOL) |
1419 posptr = NULL; // continue until the NUL | 1445 posptr = NULL; // continue until the NUL |
1510 incr = win_lbr_chartabsize(&cts, &head); | 1536 incr = win_lbr_chartabsize(&cts, &head); |
1511 // make sure we don't go past the end of the line | 1537 // make sure we don't go past the end of the line |
1512 if (*cts.cts_ptr == NUL) | 1538 if (*cts.cts_ptr == NUL) |
1513 { | 1539 { |
1514 incr = 1; // NUL at end of line only takes one column | 1540 incr = 1; // NUL at end of line only takes one column |
1541 #ifdef FEAT_PROP_POPUP | |
1542 if (cts.cts_cur_text_width > 0) | |
1543 incr = cts.cts_cur_text_width; | |
1544 on_NUL = TRUE; | |
1545 #endif | |
1515 break; | 1546 break; |
1516 } | 1547 } |
1517 | 1548 |
1518 if (posptr != NULL && cts.cts_ptr >= posptr) | 1549 if (posptr != NULL && cts.cts_ptr >= posptr) |
1519 // character at pos->col | 1550 // character at pos->col |
1542 ) | 1573 ) |
1543 *cursor = vcol + incr - 1; // cursor at end | 1574 *cursor = vcol + incr - 1; // cursor at end |
1544 else | 1575 else |
1545 { | 1576 { |
1546 #ifdef FEAT_PROP_POPUP | 1577 #ifdef FEAT_PROP_POPUP |
1547 if ((State & MODE_INSERT) == 0) | 1578 if ((State & MODE_INSERT) == 0 && !on_NUL) |
1548 // cursor is after inserted text | 1579 // cursor is after inserted text, unless on the NUL |
1549 vcol += cts.cts_cur_text_width; | 1580 vcol += cts.cts_cur_text_width; |
1550 #endif | 1581 #endif |
1551 *cursor = vcol + head; // cursor at start | 1582 *cursor = vcol + head; // cursor at start |
1552 } | 1583 } |
1553 } | 1584 } |