| To: vim-dev@vim.org |
| Subject: Patch 7.2.137 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=ISO-8859-1 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Note: The special characters in the patch may cause problems. |
| |
| Patch 7.2.137 |
| Problem: When 'virtualedit' is set, a left shift of a blockwise selection |
| that starts and ends inside a tab shifts too much. (Helmut |
| Stiegler) |
| Solution: Redo the block left shift code. (Lech Lorens) |
| Files: src/ops.c, src/testdir/Makefile, src/testdir/test66.in, |
| src/testdir/test66.ok |
| |
| |
| |
| |
| |
| *** 72,82 **** |
| */ |
| struct block_def |
| { |
| ! int startspaces; /* 'extra' cols of first char */ |
| ! int endspaces; /* 'extra' cols of first char */ |
| int textlen; /* chars in block */ |
| ! char_u *textstart; /* pointer to 1st char in block */ |
| ! colnr_T textcol; /* cols of chars (at least part.) in block */ |
| colnr_T start_vcol; /* start col of 1st char wholly inside block */ |
| colnr_T end_vcol; /* start col of 1st char wholly after block */ |
| #ifdef FEAT_VISUALEXTRA |
| --- 72,82 ---- |
| */ |
| struct block_def |
| { |
| ! int startspaces; /* 'extra' cols before first char */ |
| ! int endspaces; /* 'extra' cols after last char */ |
| int textlen; /* chars in block */ |
| ! char_u *textstart; /* pointer to 1st char (partially) in block */ |
| ! colnr_T textcol; /* index of chars (partially) in block */ |
| colnr_T start_vcol; /* start col of 1st char wholly inside block */ |
| colnr_T end_vcol; /* start col of 1st char wholly after block */ |
| #ifdef FEAT_VISUALEXTRA |
| |
| *** 382,396 **** |
| { |
| int left = (oap->op_type == OP_LSHIFT); |
| int oldstate = State; |
| ! int total, split; |
| ! char_u *newp, *oldp, *midp, *ptr; |
| int oldcol = curwin->w_cursor.col; |
| int p_sw = (int)curbuf->b_p_sw; |
| int p_ts = (int)curbuf->b_p_ts; |
| struct block_def bd; |
| - int internal = 0; |
| int incr; |
| ! colnr_T vcol, col = 0, ws_vcol; |
| int i = 0, j = 0; |
| int len; |
| |
| --- 382,395 ---- |
| { |
| int left = (oap->op_type == OP_LSHIFT); |
| int oldstate = State; |
| ! int total; |
| ! char_u *newp, *oldp; |
| int oldcol = curwin->w_cursor.col; |
| int p_sw = (int)curbuf->b_p_sw; |
| int p_ts = (int)curbuf->b_p_ts; |
| struct block_def bd; |
| int incr; |
| ! colnr_T ws_vcol; |
| int i = 0, j = 0; |
| int len; |
| |
| |
| *** 456,522 **** |
| } |
| else /* left */ |
| { |
| ! vcol = oap->start_vcol; |
| ! /* walk vcol past ws to be removed */ |
| ! for (midp = oldp + bd.textcol; |
| ! vcol < (oap->start_vcol + total) && vim_iswhite(*midp); ) |
| ! { |
| ! incr = lbr_chartabsize_adv(&midp, (colnr_T)vcol); |
| ! vcol += incr; |
| ! } |
| ! /* internal is the block-internal ws replacing a split TAB */ |
| ! if (vcol > (oap->start_vcol + total)) |
| ! { |
| ! /* we have to split the TAB *(midp-1) */ |
| ! internal = vcol - (oap->start_vcol + total); |
| ! } |
| ! /* if 'expandtab' is not set, use TABs */ |
| |
| ! split = bd.startspaces + internal; |
| ! if (split > 0) |
| ! { |
| ! if (!curbuf->b_p_et) |
| ! { |
| ! for (ptr = oldp, col = 0; ptr < oldp+bd.textcol; ) |
| ! col += lbr_chartabsize_adv(&ptr, (colnr_T)col); |
| |
| ! /* col+1 now equals the start col of the first char of the |
| ! * block (may be < oap.start_vcol if we're splitting a TAB) */ |
| ! i = ((col % p_ts) + split) / p_ts; /* number of tabs */ |
| ! } |
| ! if (i) |
| ! j = ((col % p_ts) + split) % p_ts; /* number of spp */ |
| ! else |
| ! j = split; |
| ! } |
| |
| ! newp = alloc_check(bd.textcol + i + j + (unsigned)STRLEN(midp) + 1); |
| ! if (newp == NULL) |
| ! return; |
| ! vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + STRLEN(midp) + 1)); |
| |
| ! /* copy first part we want to keep */ |
| ! mch_memmove(newp, oldp, (size_t)bd.textcol); |
| ! /* Now copy any TABS and spp to ensure correct alignment! */ |
| ! while (vim_iswhite(*midp)) |
| { |
| ! if (*midp == TAB) |
| ! i++; |
| ! else /*space */ |
| ! j++; |
| ! midp++; |
| } |
| ! /* We might have an extra TAB worth of spp now! */ |
| ! if (j / p_ts && !curbuf->b_p_et) |
| { |
| ! i++; |
| ! j -= p_ts; |
| } |
| - copy_chars(newp + bd.textcol, (size_t)i, TAB); |
| - copy_spaces(newp + bd.textcol + i, (size_t)j); |
| |
| ! /* the end */ |
| ! STRMOVE(newp + STRLEN(newp), midp); |
| } |
| /* replace the line */ |
| ml_replace(curwin->w_cursor.lnum, newp, FALSE); |
| --- 455,543 ---- |
| } |
| else /* left */ |
| { |
| ! colnr_T destination_col; /* column to which text in block will |
| ! be shifted */ |
| ! char_u *verbatim_copy_end; /* end of the part of the line which is |
| ! copied verbatim */ |
| ! colnr_T verbatim_copy_width;/* the (displayed) width of this part |
| ! of line */ |
| ! unsigned fill; /* nr of spaces that replace a TAB */ |
| ! unsigned new_line_len; /* the length of the line after the |
| ! block shift */ |
| ! size_t block_space_width; |
| ! size_t shift_amount; |
| ! char_u *non_white = bd.textstart; |
| ! colnr_T non_white_col; |
| |
| ! /* |
| ! * Firstly, let's find the first non-whitespace character that is |
| ! * displayed after the block's start column and the character's column |
| ! * number. Also, let's calculate the width of all the whitespace |
| ! * characters that are displayed in the block and precede the searched |
| ! * non-whitespace character. |
| ! */ |
| |
| ! /* If "bd.startspaces" is set, "bd.textstart" points to the character, |
| ! * the part of which is displayed at the block's beginning. Let's start |
| ! * searching from the next character. */ |
| ! if (bd.startspaces) |
| ! mb_ptr_adv(non_white); |
| |
| ! /* The character's column is in "bd.start_vcol". */ |
| ! non_white_col = bd.start_vcol; |
| |
| ! while (vim_iswhite(*non_white)) |
| { |
| ! incr = lbr_chartabsize_adv(&non_white, non_white_col); |
| ! non_white_col += incr; |
| } |
| ! |
| ! block_space_width = non_white_col - oap->start_vcol; |
| ! /* We will shift by "total" or "block_space_width", whichever is less. |
| ! */ |
| ! shift_amount = (block_space_width < total? block_space_width: total); |
| ! |
| ! /* The column to which we will shift the text. */ |
| ! destination_col = non_white_col - shift_amount; |
| ! |
| ! /* Now let's find out how much of the beginning of the line we can |
| ! * reuse without modification. */ |
| ! verbatim_copy_end = bd.textstart; |
| ! verbatim_copy_width = bd.start_vcol; |
| ! |
| ! /* If "bd.startspaces" is set, "bd.textstart" points to the character |
| ! * preceding the block. We have to subtract its width to obtain its |
| ! * column number. */ |
| ! if (bd.startspaces) |
| ! verbatim_copy_width -= bd.start_char_vcols; |
| ! while (verbatim_copy_width < destination_col) |
| { |
| ! incr = lbr_chartabsize(verbatim_copy_end, verbatim_copy_width); |
| ! if (verbatim_copy_width + incr > destination_col) |
| ! break; |
| ! verbatim_copy_width += incr; |
| ! mb_ptr_adv(verbatim_copy_end); |
| } |
| |
| ! /* If "destination_col" is different from the width of the initial |
| ! * part of the line that will be copied, it means we encountered a tab |
| ! * character, which we will have to partly replace with spaces. */ |
| ! fill = destination_col - verbatim_copy_width; |
| ! |
| ! /* The replacement line will consist of: |
| ! * - the beginning of the original line up to "verbatim_copy_end", |
| ! * - "fill" number of spaces, |
| ! * - the rest of the line, pointed to by non_white. */ |
| ! new_line_len = (unsigned)(verbatim_copy_end - oldp) |
| ! + fill |
| ! + (unsigned)STRLEN(non_white) + 1; |
| ! |
| ! newp = alloc_check(new_line_len); |
| ! if (newp == NULL) |
| ! return; |
| ! mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); |
| ! copy_spaces(newp + (verbatim_copy_end - oldp), (size_t)fill); |
| ! STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); |
| } |
| /* replace the line */ |
| ml_replace(curwin->w_cursor.lnum, newp, FALSE); |
| |
| *** 4851,4857 **** |
| * - textlen includes the first/last char to be (partly) deleted |
| * - start/endspaces is the number of columns that are taken by the |
| * first/last deleted char minus the number of columns that have to be |
| ! * deleted. for yank and tilde: |
| * - textlen includes the first/last char to be wholly yanked |
| * - start/endspaces is the number of columns of the first/last yanked char |
| * that are to be yanked. |
| --- 4872,4879 ---- |
| * - textlen includes the first/last char to be (partly) deleted |
| * - start/endspaces is the number of columns that are taken by the |
| * first/last deleted char minus the number of columns that have to be |
| ! * deleted. |
| ! * for yank and tilde: |
| * - textlen includes the first/last char to be wholly yanked |
| * - start/endspaces is the number of columns of the first/last yanked char |
| * that are to be yanked. |
| |
| |
| |
| *** 20,26 **** |
| test48.out test49.out test51.out test52.out test53.out \ |
| test54.out test55.out test56.out test57.out test58.out \ |
| test59.out test60.out test61.out test62.out test63.out \ |
| ! test64.out test65.out |
| |
| SCRIPTS_GUI = test16.out |
| |
| --- 20,26 ---- |
| test48.out test49.out test51.out test52.out test53.out \ |
| test54.out test55.out test56.out test57.out test58.out \ |
| test59.out test60.out test61.out test62.out test63.out \ |
| ! test64.out test65.out test66.out |
| |
| SCRIPTS_GUI = test16.out |
| |
| |
| |
| |
| |
| --- 1,25 ---- |
| + |
| + Test for visual block shift and tab characters. |
| + |
| + STARTTEST |
| + :so small.vim |
| + /^abcdefgh |
| + 4jI j<<11|D |
| + 7|a |
| + 7|a |
| + 7|a 4k13|4j< |
| + :$-4,$w! test.out |
| + :$-4,$s/\s\+//g |
| + 4kI j<< |
| + 7|a |
| + 7|a |
| + 7|a 4k13|4j3< |
| + :$-4,$w >> test.out |
| + :qa! |
| + ENDTEST |
| + |
| + abcdefghijklmnopqrstuvwxyz |
| + abcdefghijklmnopqrstuvwxyz |
| + abcdefghijklmnopqrstuvwxyz |
| + abcdefghijklmnopqrstuvwxyz |
| + abcdefghijklmnopqrstuvwxyz |
| |
| |
| |
| |
| --- 1,10 ---- |
| + abcdefghijklmnopqrstuvwxyz |
| + abcdefghij |
| + abc defghijklmnopqrstuvwxyz |
| + abc defghijklmnopqrstuvwxyz |
| + abc defghijklmnopqrstuvwxyz |
| + abcdefghijklmnopqrstuvwxyz |
| + abcdefghij |
| + abc defghijklmnopqrstuvwxyz |
| + abc defghijklmnopqrstuvwxyz |
| + abc defghijklmnopqrstuvwxyz |
| |
| |
| |
| *** 678,679 **** |
| --- 678,681 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 137, |
| /**/ |
| |
| -- |
| % cat /usr/include/sys/errno.h |
| #define EPERM 1 /* Operation not permitted */ |
| #define ENOENT 2 /* No such file or directory */ |
| #define ESRCH 3 /* No such process */ |
| [...] |
| #define EMACS 666 /* Too many macros */ |
| % |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ download, build and distribute -- http://www.A-A-P.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |