Patch 8.2.3410
Problem:    Crash with linebreak, listchars and large tabstop.
Solution:   Account for different size listchars for a tab. (closes #8841)
Files:      src/drawline.c, src/testdir/test_listlbr_utf8.vim


*** ../vim-8.2.3409/src/drawline.c      2021-08-31 20:57:51.193860845 +0200
--- src/drawline.c      2021-09-07 20:44:19.204314055 +0200
***************
*** 2109,2163 ****
                        int     i;
                        int     saved_nextra = n_extra;
  
! #ifdef FEAT_CONCEAL
                        if (vcol_off > 0)
                            // there are characters to conceal
                            tab_len += vcol_off;
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
                                                        && old_boguscols > 0
                                                        && n_extra > tab_len)
                            tab_len += n_extra - tab_len;
! #endif
! 
!                       // if n_extra > 0, it gives the number of chars, to
                        // use for a tab, else we need to calculate the width
!                       // for a tab
                        len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
                        if (n_extra > 0)
                            len += n_extra - tab_len;
                        c = wp->w_lcs_chars.tab1;
                        p = alloc(len + 1);
!                       vim_memset(p, ' ', len);
!                       p[len] = NUL;
!                       vim_free(p_extra_free);
!                       p_extra_free = p;
!                       for (i = 0; i < tab_len; i++)
                        {
!                           int lcs = wp->w_lcs_chars.tab2;
! 
!                           if (*p == NUL)
                            {
!                               tab_len = i;
!                               break;
!                           }
  
!                           // if tab3 is given, need to change the char
!                           // for tab
!                           if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
!                               lcs = wp->w_lcs_chars.tab3;
!                           mb_char2bytes(lcs, p);
!                           p += mb_char2len(lcs);
!                           n_extra += mb_char2len(lcs)
                                                  - (saved_nextra > 0 ? 1 : 0);
                        }
-                       p_extra = p_extra_free;
- #ifdef FEAT_CONCEAL
-                       // n_extra will be increased by FIX_FOX_BOGUSCOLS
-                       // macro below, so need to adjust for that here
-                       if (vcol_off > 0)
-                           n_extra -= vcol_off;
- #endif
                    }
  #endif
  #ifdef FEAT_CONCEAL
--- 2109,2168 ----
                        int     i;
                        int     saved_nextra = n_extra;
  
! # ifdef FEAT_CONCEAL
                        if (vcol_off > 0)
                            // there are characters to conceal
                            tab_len += vcol_off;
+ 
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
                                                        && old_boguscols > 0
                                                        && n_extra > tab_len)
                            tab_len += n_extra - tab_len;
! # endif
!                       // If n_extra > 0, it gives the number of chars, to
                        // use for a tab, else we need to calculate the width
!                       // for a tab.
                        len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
+                       if (wp->w_lcs_chars.tab3)
+                           len += mb_char2len(wp->w_lcs_chars.tab3);
                        if (n_extra > 0)
                            len += n_extra - tab_len;
                        c = wp->w_lcs_chars.tab1;
                        p = alloc(len + 1);
!                       if (p == NULL)
!                           n_extra = 0;
!                       else
                        {
!                           vim_memset(p, ' ', len);
!                           p[len] = NUL;
!                           vim_free(p_extra_free);
!                           p_extra_free = p;
!                           for (i = 0; i < tab_len; i++)
                            {
!                               int lcs = wp->w_lcs_chars.tab2;
  
!                               if (*p == NUL)
!                               {
!                                   tab_len = i;
!                                   break;
!                               }
! 
!                               // if tab3 is given, use it for the last char
!                               if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
!                                   lcs = wp->w_lcs_chars.tab3;
!                               p += mb_char2bytes(lcs, p);
!                               n_extra += mb_char2len(lcs)
                                                  - (saved_nextra > 0 ? 1 : 0);
+                           }
+                           p_extra = p_extra_free;
+ # ifdef FEAT_CONCEAL
+                           // n_extra will be increased by FIX_FOX_BOGUSCOLS
+                           // macro below, so need to adjust for that here
+                           if (vcol_off > 0)
+                               n_extra -= vcol_off;
+ # endif
                        }
                    }
  #endif
  #ifdef FEAT_CONCEAL
*** ../vim-8.2.3409/src/testdir/test_listlbr_utf8.vim   2020-08-12 
18:50:31.879655802 +0200
--- src/testdir/test_listlbr_utf8.vim   2021-09-07 20:41:48.852648856 +0200
***************
*** 70,75 ****
--- 70,85 ----
    call s:close_windows()
  endfunc
  
+ " this was causing a crash
+ func Test_linebreak_with_list_and_tabs()
+   set linebreak list listchars=tab:⇤\ ⇥ tabstop=100
+   new
+   call setline(1, "\t\t\ttext")
+   redraw
+   bwipe!
+   set nolinebreak nolist listchars&vim tabstop=8
+ endfunc
+ 
  func Test_linebreak_with_nolist()
    call s:test_windows('setl nolist')
    call setline(1, "\t*mask = nil;")
*** ../vim-8.2.3409/src/version.c       2021-09-07 19:26:46.114706317 +0200
--- src/version.c       2021-09-07 20:42:56.164499501 +0200
***************
*** 757,758 ****
--- 757,760 ----
  {   /* Add new patch number below this line */
+ /**/
+     3410,
  /**/

-- 
A)bort, R)etry, P)lease don't bother me again

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202109071852.187IqMLs1693152%40masaka.moolenaar.net.

Raspunde prin e-mail lui