To: [email protected]
Subject: patch 7.1a.001
Fcc: outbox
From: Bram Moolenaar <[email protected]>
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
------------

Patch 7.1a.001
Problem:    Crash when downloading a spell file.  (Szabolcs Horvat)
Solution:   Avoid that did_set_spelllang() is used recursively when a new
           window is opened for the download.
           Also avoid wiping out the wrong buffer.
Files:      runtime/autoload/spellfile.vim, src/buffer.c, src/ex_cmds.c,
           src/spell.c


*** ../vim-7.1a.000/runtime/autoload/spellfile.vim      Tue Aug 29 22:31:34 2006
--- runtime/autoload/spellfile.vim      Sun May  6 23:52:05 2007
***************
*** 1,6 ****
 " Vim script to download a missing spell file
 " Maintainer: Bram Moolenaar <[email protected]>
! " Last Change:        2006 Aug 29

 if !exists('g:spellfile_URL')
   let g:spellfile_URL = 'ftp://ftp.vim.org/pub/vim/runtime/spell'
--- 1,6 ----
 " Vim script to download a missing spell file
 " Maintainer: Bram Moolenaar <[email protected]>
! " Last Change:        2007 May 06

 if !exists('g:spellfile_URL')
   let g:spellfile_URL = 'ftp://ftp.vim.org/pub/vim/runtime/spell'
***************
*** 58,76 ****
     let fname = a:lang . '.' . enc . '.spl'

     " Split the window, read the file into a new buffer.
     new
     setlocal bin
     echo 'Downloading ' . fname . '...'
     call spellfile#Nread(fname)
     if getline(2) !~ 'VIMspell'
       " Didn't work, perhaps there is an ASCII one.
!       g/^/d
       let fname = a:lang . '.ascii.spl'
       echo 'Could not find it, trying ' . fname . '...'
       call spellfile#Nread(fname)
       if getline(2) !~ 'VIMspell'
       echo 'Sorry, downloading failed'
!       bwipe!
       return
       endif
     endif
--- 58,97 ----
     let fname = a:lang . '.' . enc . '.spl'

     " Split the window, read the file into a new buffer.
+     " Remember the buffer number, we check it below.
     new
+     let newbufnr = winbufnr(0)
     setlocal bin
     echo 'Downloading ' . fname . '...'
     call spellfile#Nread(fname)
     if getline(2) !~ 'VIMspell'
       " Didn't work, perhaps there is an ASCII one.
!       " Careful: Nread() may have opened a new window for the error message,
!       " we need to go back to our own buffer and window.
!       if newbufnr != winbufnr(0)
!       let winnr = bufwinnr(newbufnr)
!       if winnr == -1
!         " Our buffer has vanished!?  Open a new window.
!         echomsg "download buffer disappeared, opening a new one"
!         new
!         setlocal bin
!       else
!         exe winnr . "wincmd w"
!       endif
!       endif
!       if newbufnr == winbufnr(0)
!       " We are back the old buffer, remove any (half-finished) download.
!         g/^/d
!       else
!       let newbufnr = winbufnr(0)
!       endif
!
       let fname = a:lang . '.ascii.spl'
       echo 'Could not find it, trying ' . fname . '...'
       call spellfile#Nread(fname)
       if getline(2) !~ 'VIMspell'
       echo 'Sorry, downloading failed'
!       exe newbufnr . "bwipe!"
       return
       endif
     endif
***************
*** 96,112 ****
       let fname = substitute(fname, '\.spl$', '.sug', '')
       echo 'Downloading ' . fname . '...'
       call spellfile#Nread(fname)
!       if getline(2) !~ 'VIMsug'
!         echo 'Sorry, downloading failed'
!       else
         1d
         exe "write " . escape(dirlist[dirchoice], ' ') . '/' . fname
       endif
-       set nomod
       endif
     endif

!     bwipe
   endif
 endfunc

--- 117,145 ----
       let fname = substitute(fname, '\.spl$', '.sug', '')
       echo 'Downloading ' . fname . '...'
       call spellfile#Nread(fname)
!       if getline(2) =~ 'VIMsug'
         1d
         exe "write " . escape(dirlist[dirchoice], ' ') . '/' . fname
+         set nomod
+       else
+         echo 'Sorry, downloading failed'
+         " Go back to our own buffer/window, Nread() may have taken us to
+         " another window.
+         if newbufnr != winbufnr(0)
+           let winnr = bufwinnr(newbufnr)
+           if winnr != -1
+             exe winnr . "wincmd w"
+           endif
+         endif
+         if newbufnr == winbufnr(0)
+           set nomod
+         endif
       endif
       endif
     endif

!     " Wipe out the buffer we used.
!     exe newbufnr . "bwipe"
   endif
 endfunc

*** ../vim-7.1a.000/src/buffer.c        Thu Mar 15 22:53:25 2007
--- src/buffer.c        Sun May  6 15:44:08 2007
***************
*** 1426,1431 ****
--- 1426,1438 ----
     if (curbuf->b_kmap_state & KEYMAP_INIT)
       keymap_init();
 #endif
+ #ifdef FEAT_SPELL
+     /* May need to set the spell language.  Can only do this after the buffer
+      * has been properly setup. */
+     if (!curbuf->b_help && curwin->w_p_spell && *curbuf->b_p_spl != NUL)
+       did_set_spelllang(curbuf);
+ #endif
+
     redraw_later(NOT_VALID);
 }

***************
*** 2414,2424 ****
     /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
     if (p_fdls >= 0)
       curwin->w_p_fdl = p_fdls;
- #endif
-
- #ifdef FEAT_SPELL
-     if (curwin->w_p_spell && *buf->b_p_spl != NUL)
-       did_set_spelllang(buf);
 #endif
 }

--- 2421,2426 ----
*** ../vim-7.1a.000/src/ex_cmds.c       Thu Mar 15 21:38:26 2007
--- src/ex_cmds.c       Sun May  6 15:38:25 2007
***************
*** 3088,3093 ****
--- 3088,3096 ----
     char_u    *cp;
 #endif
     char_u    *command = NULL;
+ #ifdef FEAT_SPELL
+     int               did_get_winopts = FALSE;
+ #endif

     if (eap != NULL)
       command = eap->do_ecmd_cmd;
***************
*** 3365,3370 ****
--- 3368,3376 ----
                * before, reset the local window options to the global
                * values.  Also restores old folding stuff. */
               get_winopts(buf);
+ #ifdef FEAT_SPELL
+               did_get_winopts = TRUE;
+ #endif

 #ifdef FEAT_AUTOCMD
           }
***************
*** 3638,3643 ****
--- 3644,3656 ----
       diff_buf_add(curbuf);
       diff_invalidate(curbuf);
     }
+ #endif
+
+ #ifdef FEAT_SPELL
+     /* If the window options were changed may need to set the spell language.
+      * Can only do this after the buffer has been properly setup. */
+     if (did_get_winopts && curwin->w_p_spell && *buf->b_p_spl != NUL)
+       did_set_spelllang(buf);
 #endif

     if (command == NULL)
*** ../vim-7.1a.000/src/spell.c Thu Mar  8 14:49:18 2007
--- src/spell.c Sun May  6 17:08:06 2007
***************
*** 4105,4116 ****
     int               nobreak = FALSE;
     int               i, j;
     langp_T   *lp, *lp2;

     ga_init2(&ga, sizeof(langp_T), 2);
     clear_midword(buf);

     /* loop over comma separated language names. */
!     for (splp = buf->b_p_spl; *splp != NUL; )
     {
       /* Get one language name. */
       copy_option_part(&splp, lang, MAXWLEN, ",");
--- 4105,4132 ----
     int               nobreak = FALSE;
     int               i, j;
     langp_T   *lp, *lp2;
+     static int        recursive = FALSE;
+     char_u    *ret_msg = NULL;
+     char_u    *spl_copy;
+
+     /* We don't want to do this recursively.  May happen when a language is
+      * not available and the SpellFileMissing autocommand opens a new buffer
+      * in which 'spell' is set. */
+     if (recursive)
+       return NULL;
+     recursive = TRUE;

     ga_init2(&ga, sizeof(langp_T), 2);
     clear_midword(buf);

+     /* Make a copy of 'spellang', the SpellFileMissing autocommands may change
+      * it under our fingers. */
+     spl_copy = vim_strsave(buf->b_p_spl);
+     if (spl_copy == NULL)
+       goto theend;
+
     /* loop over comma separated language names. */
!     for (splp = spl_copy; *splp != NUL; )
     {
       /* Get one language name. */
       copy_option_part(&splp, lang, MAXWLEN, ",");
***************
*** 4176,4182 ****
--- 4192,4209 ----
           if (filename)
               (void)spell_load_file(lang, lang, NULL, FALSE);
           else
+           {
               spell_load_lang(lang);
+ #ifdef FEAT_AUTOCMD
+               /* SpellFileMissing autocommands may do anything, including
+                * destroying the buffer we are using... */
+               if (!buf_valid(buf))
+               {
+                   ret_msg = (char_u *)"E797: SpellFileMissing autocommand deleted buffer";
+                   goto theend;
+               }
+ #endif
+           }
       }

       /*
***************
*** 4215,4221 ****
                   if (ga_grow(&ga, 1) == FAIL)
                   {
                       ga_clear(&ga);
!                       return e_outofmem;
                   }
                   LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
                   LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
--- 4242,4249 ----
                   if (ga_grow(&ga, 1) == FAIL)
                   {
                       ga_clear(&ga);
!                       ret_msg = e_outofmem;
!                       goto theend;
                   }
                   LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
                   LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
***************
*** 4231,4237 ****
      * round 1: load first name in 'spellfile'.
      * round 2: load second name in 'spellfile.
      * etc. */
!     spf = curbuf->b_p_spf;
     for (round = 0; round == 0 || *spf != NUL; ++round)
     {
       if (round == 0)
--- 4259,4265 ----
      * round 1: load first name in 'spellfile'.
      * round 2: load second name in 'spellfile.
      * etc. */
!     spf = buf->b_p_spf;
     for (round = 0; round == 0 || *spf != NUL; ++round)
     {
       if (round == 0)
***************
*** 4357,4363 ****
           }
     }

!     return NULL;
 }

 /*
--- 4385,4394 ----
           }
     }

! theend:
!     vim_free(spl_copy);
!     recursive = FALSE;
!     return ret_msg;
 }

 /*
*** ../vim-7.1a.000/src/version.c       Sun May  6 15:28:50 2007
--- src/version.c       Sun May  6 23:50:00 2007
***************
*** 668,669 ****
--- 668,671 ----
 {   /* Add new patch number below this line */
+ /**/
+     1,
 /**/

--
hundred-and-one symptoms of being an internet addict:
69. Yahoo welcomes you with your own start page

/// 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    ///