Mercurial > vim
comparison src/ops.c @ 20583:d067be761cd7 v8.2.0845
patch 8.2.0845: text properties crossing lines not handled correctly
Commit: https://github.com/vim/vim/commit/87be9be1db6b6d8fb57ef14e05f23a84e5e8bea0
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat May 30 15:32:02 2020 +0200
patch 8.2.0845: text properties crossing lines not handled correctly
Problem: Text properties crossing lines not handled correctly.
Solution: When joining lines merge text properties if possible.
(Axel Forsman, closes #5839, closes #5683)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 30 May 2020 15:45:04 +0200 |
parents | 918245588b50 |
children | 9edb439adbea |
comparison
equal
deleted
inserted
replaced
20582:49d2f01322db | 20583:d067be761cd7 |
---|---|
1885 { | 1885 { |
1886 char_u *curr = NULL; | 1886 char_u *curr = NULL; |
1887 char_u *curr_start = NULL; | 1887 char_u *curr_start = NULL; |
1888 char_u *cend; | 1888 char_u *cend; |
1889 char_u *newp; | 1889 char_u *newp; |
1890 size_t newp_len; | |
1890 char_u *spaces; // number of spaces inserted before a line | 1891 char_u *spaces; // number of spaces inserted before a line |
1891 int endcurr1 = NUL; | 1892 int endcurr1 = NUL; |
1892 int endcurr2 = NUL; | 1893 int endcurr2 = NUL; |
1893 int currsize = 0; // size of the current line | 1894 int currsize = 0; // size of the current line |
1894 int sumsize = 0; // size of the long new line | 1895 int sumsize = 0; // size of the long new line |
1898 int *comments = NULL; | 1899 int *comments = NULL; |
1899 int remove_comments = (use_formatoptions == TRUE) | 1900 int remove_comments = (use_formatoptions == TRUE) |
1900 && has_format_option(FO_REMOVE_COMS); | 1901 && has_format_option(FO_REMOVE_COMS); |
1901 int prev_was_comment; | 1902 int prev_was_comment; |
1902 #ifdef FEAT_PROP_POPUP | 1903 #ifdef FEAT_PROP_POPUP |
1903 textprop_T **prop_lines = NULL; | 1904 int propcount = 0; // number of props over all joined lines |
1904 int *prop_lengths = NULL; | 1905 int props_remaining; |
1905 #endif | 1906 #endif |
1906 | 1907 |
1907 if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1), | 1908 if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1), |
1908 (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) | 1909 (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) |
1909 return FAIL; | 1910 return FAIL; |
1930 * This loops forward over the joined lines. | 1931 * This loops forward over the joined lines. |
1931 */ | 1932 */ |
1932 for (t = 0; t < count; ++t) | 1933 for (t = 0; t < count; ++t) |
1933 { | 1934 { |
1934 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); | 1935 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); |
1936 #ifdef FEAT_PROP_POPUP | |
1937 propcount += count_props((linenr_T) (curwin->w_cursor.lnum + t), t > 0); | |
1938 #endif | |
1935 if (t == 0 && setmark && !cmdmod.lockmarks) | 1939 if (t == 0 && setmark && !cmdmod.lockmarks) |
1936 { | 1940 { |
1937 // Set the '[ mark. | 1941 // Set the '[ mark. |
1938 curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum; | 1942 curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum; |
1939 curwin->w_buffer->b_op_start.col = (colnr_T)STRLEN(curr); | 1943 curwin->w_buffer->b_op_start.col = (colnr_T)STRLEN(curr); |
2012 | 2016 |
2013 // store the column position before last line | 2017 // store the column position before last line |
2014 col = sumsize - currsize - spaces[count - 1]; | 2018 col = sumsize - currsize - spaces[count - 1]; |
2015 | 2019 |
2016 // allocate the space for the new line | 2020 // allocate the space for the new line |
2017 newp = alloc(sumsize + 1); | 2021 newp_len = sumsize + 1; |
2022 #ifdef FEAT_PROP_POPUP | |
2023 newp_len += propcount * sizeof(textprop_T); | |
2024 #endif | |
2025 newp = alloc(newp_len); | |
2018 if (newp == NULL) | 2026 if (newp == NULL) |
2019 { | 2027 { |
2020 ret = FAIL; | 2028 ret = FAIL; |
2021 goto theend; | 2029 goto theend; |
2022 } | 2030 } |
2023 cend = newp + sumsize; | 2031 cend = newp + sumsize; |
2024 *cend = 0; | 2032 *cend = 0; |
2025 | |
2026 #ifdef FEAT_PROP_POPUP | |
2027 // We need to move properties of the lines that are going to be deleted to | |
2028 // the new long one. | |
2029 if (curbuf->b_has_textprop && !text_prop_frozen) | |
2030 { | |
2031 // Allocate an array to copy the text properties of joined lines into. | |
2032 // And another array to store the number of properties in each line. | |
2033 prop_lines = ALLOC_CLEAR_MULT(textprop_T *, count - 1); | |
2034 prop_lengths = ALLOC_CLEAR_MULT(int, count - 1); | |
2035 if (prop_lengths == NULL) | |
2036 VIM_CLEAR(prop_lines); | |
2037 } | |
2038 #endif | |
2039 | 2033 |
2040 /* | 2034 /* |
2041 * Move affected lines to the new long one. | 2035 * Move affected lines to the new long one. |
2042 * This loops backwards over the joined lines, including the original line. | 2036 * This loops backwards over the joined lines, including the original line. |
2043 * | 2037 * |
2044 * Move marks from each deleted line to the joined line, adjusting the | 2038 * Move marks from each deleted line to the joined line, adjusting the |
2045 * column. This is not Vi compatible, but Vi deletes the marks, thus that | 2039 * column. This is not Vi compatible, but Vi deletes the marks, thus that |
2046 * should not really be a problem. | 2040 * should not really be a problem. |
2047 */ | 2041 */ |
2042 #ifdef FEAT_PROP_POPUP | |
2043 props_remaining = propcount; | |
2044 #endif | |
2048 for (t = count - 1; ; --t) | 2045 for (t = count - 1; ; --t) |
2049 { | 2046 { |
2050 int spaces_removed; | 2047 int spaces_removed; |
2051 | 2048 |
2052 cend -= currsize; | 2049 cend -= currsize; |
2053 mch_memmove(cend, curr, (size_t)currsize); | 2050 mch_memmove(cend, curr, (size_t)currsize); |
2051 | |
2054 if (spaces[t] > 0) | 2052 if (spaces[t] > 0) |
2055 { | 2053 { |
2056 cend -= spaces[t]; | 2054 cend -= spaces[t]; |
2057 vim_memset(cend, ' ', (size_t)(spaces[t])); | 2055 vim_memset(cend, ' ', (size_t)(spaces[t])); |
2058 } | 2056 } |
2061 // what is added if it is inside these spaces. | 2059 // what is added if it is inside these spaces. |
2062 spaces_removed = (curr - curr_start) - spaces[t]; | 2060 spaces_removed = (curr - curr_start) - spaces[t]; |
2063 | 2061 |
2064 mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, | 2062 mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, |
2065 (long)(cend - newp - spaces_removed), spaces_removed); | 2063 (long)(cend - newp - spaces_removed), spaces_removed); |
2064 #ifdef FEAT_PROP_POPUP | |
2065 prepend_joined_props(newp + sumsize + 1, propcount, &props_remaining, | |
2066 curwin->w_cursor.lnum + t, t == count - 1, | |
2067 (long)(cend - newp), spaces_removed); | |
2068 #endif | |
2069 | |
2066 if (t == 0) | 2070 if (t == 0) |
2067 break; | 2071 break; |
2068 #ifdef FEAT_PROP_POPUP | |
2069 if (prop_lines != NULL) | |
2070 adjust_props_for_join(curwin->w_cursor.lnum + t, | |
2071 prop_lines + t - 1, prop_lengths + t - 1, | |
2072 (long)(cend - newp - spaces_removed), spaces_removed); | |
2073 #endif | |
2074 | |
2075 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); | 2072 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); |
2076 if (remove_comments) | 2073 if (remove_comments) |
2077 curr += comments[t - 1]; | 2074 curr += comments[t - 1]; |
2078 if (insert_space && t > 1) | 2075 if (insert_space && t > 1) |
2079 curr = skipwhite(curr); | 2076 curr = skipwhite(curr); |
2080 currsize = (int)STRLEN(curr); | 2077 currsize = (int)STRLEN(curr); |
2081 } | 2078 } |
2082 | 2079 |
2083 #ifdef FEAT_PROP_POPUP | 2080 ml_replace_len(curwin->w_cursor.lnum, newp, newp_len, TRUE, FALSE); |
2084 if (prop_lines != NULL) | |
2085 join_prop_lines(curwin->w_cursor.lnum, newp, | |
2086 prop_lines, prop_lengths, count); | |
2087 else | |
2088 #endif | |
2089 ml_replace(curwin->w_cursor.lnum, newp, FALSE); | |
2090 | 2081 |
2091 if (setmark && !cmdmod.lockmarks) | 2082 if (setmark && !cmdmod.lockmarks) |
2092 { | 2083 { |
2093 // Set the '] mark. | 2084 // Set the '] mark. |
2094 curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum; | 2085 curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum; |