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


*** ../vim-7.2.136/src/ops.c    Wed Dec  3 13:38:00 2008
--- src/ops.c   Thu Mar  5 04:47:09 2009
***************
*** 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.
*** ../vim-7.2.136/src/testdir/Makefile Wed Sep 10 18:25:18 2008
--- src/testdir/Makefile        Thu Mar  5 04:53:58 2009
***************
*** 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
  
*** ../vim-7.2.136/src/testdir/test66.in        Wed Mar 11 16:24:44 2009
--- src/testdir/test66.in       Wed Mar 11 11:52:57 2009
***************
*** 0 ****
--- 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
*** ../vim-7.2.136/src/testdir/test66.ok        Wed Mar 11 16:24:44 2009
--- src/testdir/test66.ok       Thu Mar  5 04:39:36 2009
***************
*** 0 ****
--- 1,10 ----
+     abcdefghijklmnopqrstuvwxyz
+ abcdefghij
+     abc           defghijklmnopqrstuvwxyz
+     abc           defghijklmnopqrstuvwxyz
+     abc           defghijklmnopqrstuvwxyz
+     abcdefghijklmnopqrstuvwxyz
+ abcdefghij
+     abc           defghijklmnopqrstuvwxyz
+     abc               defghijklmnopqrstuvwxyz
+     abc           defghijklmnopqrstuvwxyz
*** ../vim-7.2.136/src/version.c        Wed Mar 11 15:36:01 2009
--- src/version.c       Wed Mar 11 16:23:07 2009
***************
*** 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 -- [email protected] -- 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    ///

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Raspunde prin e-mail lui