]> granicus.if.org Git - vim/commitdiff
updated for version 7.0141
authorBram Moolenaar <Bram@vim.org>
Mon, 5 Sep 2005 22:05:30 +0000 (22:05 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 5 Sep 2005 22:05:30 +0000 (22:05 +0000)
src/mark.c
src/normal.c
src/spell.c

index 1655e035783d4beefd25e06f824c1f4b4734897f..d3db4a601bbacc5579ecb577e5607794da314c0f 100644 (file)
@@ -318,7 +318,8 @@ getmark(c, changefile)
 
        pos = curwin->w_cursor;
        listcmd_busy = TRUE;        /* avoid that '' is changed */
-       if (findpar(&oa, c == '}' ? FORWARD : BACKWARD, 1L, NUL, FALSE))
+       if (findpar(&oa.inclusive,
+                              c == '}' ? FORWARD : BACKWARD, 1L, NUL, FALSE))
        {
            pos_copy = curwin->w_cursor;
            posp = &pos_copy;
index e7cfad6e7a8aa5169733e1f93b5197ba336adb9b..b184fd78341453e0ae75bf4e340def222532fcfd 100644 (file)
@@ -3921,23 +3921,45 @@ nv_page(cap)
  */
     static void
 nv_gd(oap, nchar)
-    oparg_T   *oap;
-    int            nchar;
+    oparg_T    *oap;
+    int                nchar;
 {
     int                len;
+    char_u     *ptr;
+
+    if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0
+           || find_decl(ptr, len, nchar == 'd', 0) == FAIL)
+       clearopbeep(oap);
+#ifdef FEAT_FOLDING
+    else if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP)
+       foldOpenCursor();
+#endif
+}
+
+/*
+ * Search for variable declaration of "ptr[len]".  When "locally" is TRUE in
+ * the current function ("gd"), otherwise in the current file ("gD").
+ * Return FAIL when not found.
+ */
+    int
+find_decl(ptr, len, locally, searchflags)
+    char_u     *ptr;
+    int                len;
+    int                locally;
+    int                searchflags;    /* flags passed to searchit() */
+{
     char_u     *pat;
     pos_T      old_pos;
+    pos_T      par_pos;
+    pos_T      found_pos;
     int                t;
     int                save_p_ws;
     int                save_p_scs;
-    char_u     *ptr;
+    int                retval = OK;
+    int                incl;
 
-    if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0
-           || (pat = alloc(len + 7)) == NULL)
-    {
-       clearopbeep(oap);
-       return;
-    }
+    if ((pat = alloc(len + 7)) == NULL)
+       return FAIL;
 
     /* Put "\V" before the pattern to avoid that the special meaning of "."
      * and "~" causes trouble. */
@@ -3954,42 +3976,70 @@ nv_gd(oap, nchar)
      * With "gd" Search back for the start of the current function, then go
      * back until a blank line.  If this fails go to line 1.
      */
-    if (nchar == 'D' || !findpar(oap, BACKWARD, 1L, '{', FALSE))
+    if (!locally || !findpar(&incl, BACKWARD, 1L, '{', FALSE))
     {
        setpcmark();                    /* Set in findpar() otherwise */
        curwin->w_cursor.lnum = 1;
     }
     else
     {
+       par_pos = curwin->w_cursor;
        while (curwin->w_cursor.lnum > 1 && *skipwhite(ml_get_curline()) != NUL)
            --curwin->w_cursor.lnum;
     }
     curwin->w_cursor.col = 0;
 
     /* Search forward for the identifier, ignore comment lines. */
-    while ((t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, pat, 1L, 0,
-                                                            RE_LAST)) != FAIL
+    found_pos.lnum = 0;
+    for (;;)
+    {
+       t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD,
+                                              pat, 1L, searchflags, RE_LAST);
+       if (curwin->w_cursor.lnum >= old_pos.lnum)
+           t = FAIL;   /* match after start is failure too */
+       if (t == FAIL)
+       {
+           /* If we previously found a valid position, use it. */
+           if (found_pos.lnum != 0)
+           {
+               curwin->w_cursor = found_pos;
+               t = OK;
+           }
+           break;
+       }
 #ifdef FEAT_COMMENTS
-           && get_leader_len(ml_get_curline(), NULL, FALSE) > 0
+       if (get_leader_len(ml_get_curline(), NULL, FALSE) > 0)
+       {
+           /* Ignore this line, continue at start of next line. */
+           ++curwin->w_cursor.lnum;
+           curwin->w_cursor.col = 0;
+           continue;
+       }
 #endif
-           && old_pos.lnum > curwin->w_cursor.lnum)
-    {
-       /* Ignore this line, continue at start of next line. */
-       ++curwin->w_cursor.lnum;
-       curwin->w_cursor.col = 0;
+       if (!locally)   /* global search: use first match found */
+           break;
+       if (curwin->w_cursor.lnum >= par_pos.lnum)
+       {
+           /* If we previously found a valid position, use it. */
+           if (found_pos.lnum != 0)
+               curwin->w_cursor = found_pos;
+           break;
+       }
+
+       /* For finding a local variable and the match is before the "{" search
+        * to find a later match.  For K&R style function declarations this
+        * skips the function header without types. */
+       found_pos = curwin->w_cursor;
     }
-    if (t == FAIL || old_pos.lnum <= curwin->w_cursor.lnum)
+
+    if (t == FAIL)
     {
-       clearopbeep(oap);
+       retval = FAIL;
        curwin->w_cursor = old_pos;
     }
     else
     {
        curwin->w_set_curswant = TRUE;
-#ifdef FEAT_FOLDING
-       if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP)
-           foldOpenCursor();
-#endif
        /* "n" searches forward now */
        reset_search_dir();
     }
@@ -3997,6 +4047,8 @@ nv_gd(oap, nchar)
     vim_free(pat);
     p_ws = save_p_ws;
     p_scs = save_p_scs;
+
+    return retval;
 }
 
 /*
@@ -6014,7 +6066,7 @@ nv_brackets(cap)
         * Imitate strange Vi behaviour: When using "]]" with an operator
         * we also stop at '}'.
         */
-       if (!findpar(cap->oap, cap->arg, cap->count1, flag,
+       if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, flag,
              (cap->oap->op_type != OP_NOP
                                      && cap->arg == FORWARD && flag == '{')))
            clearopbeep(cap->oap);
@@ -6239,7 +6291,7 @@ nv_findpar(cap)
     cap->oap->inclusive = FALSE;
     cap->oap->use_reg_one = TRUE;
     curwin->w_set_curswant = TRUE;
-    if (!findpar(cap->oap, cap->arg, cap->count1, NUL, FALSE))
+    if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, NUL, FALSE))
        clearopbeep(cap->oap);
     else
     {
index 2c21d94c801e4920b5f332267edf6ca28634be12..c3c54b767f9c5d7e147a602a5a1131deb295abd9 100644 (file)
@@ -423,7 +423,9 @@ static slang_T *first_lang = NULL;
  */
 typedef struct langp_S
 {
-    slang_T    *lp_slang;      /* info for this language (NULL for last one) */
+    slang_T    *lp_slang;      /* info for this language */
+    slang_T    *lp_sallang;    /* language used for sound folding or NULL */
+    slang_T    *lp_replang;    /* language used for REP items or NULL */
     int                lp_region;      /* bitmask for region or REGION_ALL */
 } langp_T;
 
@@ -476,6 +478,7 @@ typedef struct suginfo_S
     char_u     su_badword[MAXWLEN]; /* bad word truncated at su_badlen */
     char_u     su_fbadword[MAXWLEN]; /* su_badword case-folded */
     hashtab_T  su_banned;          /* table with banned words */
+    slang_T    *su_sallang;        /* default language for sound folding */
 } suginfo_T;
 
 /* One word suggestion.  Used in "si_ga". */
@@ -487,6 +490,7 @@ typedef struct suggest_S
     int                st_altscore;    /* used when st_score compares equal */
     int                st_salscore;    /* st_score is for soundalike */
     int                st_had_bonus;   /* bonus already included in score */
+    slang_T    *st_slang;      /* language used for sound folding */
 } suggest_T;
 
 #define SUG(ga, i) (((suggest_T *)(ga).ga_data)[i])
@@ -740,7 +744,7 @@ static void suggest_try_soundalike __ARGS((suginfo_T *su));
 static void make_case_word __ARGS((char_u *fword, char_u *cword, int flags));
 static void set_map_str __ARGS((slang_T *lp, char_u *map));
 static int similar_chars __ARGS((slang_T *slang, int c1, int c2));
-static void add_suggestion __ARGS((suginfo_T *su, garray_T *gap, char_u *goodword, int badlen, int score, int altscore, int had_bonus));
+static void add_suggestion __ARGS((suginfo_T *su, garray_T *gap, char_u *goodword, int badlen, int score, int altscore, int had_bonus, slang_T *slang));
 static void add_banned __ARGS((suginfo_T *su, char_u *word));
 static int was_banned __ARGS((suginfo_T *su, char_u *word));
 static void free_banned __ARGS((suginfo_T *su));
@@ -1985,6 +1989,8 @@ spell_move_to(wp, dir, allwords, curline, attrp)
                 * starting line again and accept the last match. */
                lnum = wp->w_buffer->b_ml.ml_line_count;
                wrapped = TRUE;
+               if (!shortmess(SHM_SEARCH))
+                   give_warning((char_u *)_(top_bot_msg), TRUE);
            }
            capcol = -1;
        }
@@ -2000,6 +2006,8 @@ spell_move_to(wp, dir, allwords, curline, attrp)
                 * starting line again and accept the first match. */
                lnum = 1;
                wrapped = TRUE;
+               if (!shortmess(SHM_SEARCH))
+                   give_warning((char_u *)_(bot_top_msg), TRUE);
            }
 
            /* If we are back at the starting line and there is no match then
@@ -3540,7 +3548,7 @@ did_set_spelllang(buf)
     char_u     region_cp[3];
     int                filename;
     int                region_mask;
-    slang_T    *lp;
+    slang_T    *slang;
     int                c;
     char_u     lang[MAXWLEN + 1];
     char_u     spf_name[MAXPATHL];
@@ -3551,6 +3559,8 @@ did_set_spelllang(buf)
     char_u     *use_region = NULL;
     int                dont_use_region = FALSE;
     int                nobreak = FALSE;
+    int                i, j;
+    langp_T    *lp, *lp2;
 
     ga_init2(&ga, sizeof(langp_T), 2);
     clear_midword(buf);
@@ -3585,8 +3595,8 @@ did_set_spelllang(buf)
                dont_use_region = TRUE;
 
            /* Check if we loaded this language before. */
-           for (lp = first_lang; lp != NULL; lp = lp->sl_next)
-               if (fullpathcmp(lang, lp->sl_fname, FALSE) == FPC_SAME)
+           for (slang = first_lang; slang != NULL; slang = slang->sl_next)
+               if (fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME)
                    break;
        }
        else
@@ -3602,8 +3612,8 @@ did_set_spelllang(buf)
                dont_use_region = TRUE;
 
            /* Check if we loaded this language before. */
-           for (lp = first_lang; lp != NULL; lp = lp->sl_next)
-               if (STRICMP(lang, lp->sl_name) == 0)
+           for (slang = first_lang; slang != NULL; slang = slang->sl_next)
+               if (STRICMP(lang, slang->sl_name) == 0)
                    break;
        }
 
@@ -3617,7 +3627,7 @@ did_set_spelllang(buf)
        }
 
        /* If not found try loading the language now. */
-       if (lp == NULL)
+       if (slang == NULL)
        {
            if (filename)
                (void)spell_load_file(lang, lang, NULL, FALSE);
@@ -3628,20 +3638,20 @@ did_set_spelllang(buf)
        /*
         * Loop over the languages, there can be several files for "lang".
         */
-       for (lp = first_lang; lp != NULL; lp = lp->sl_next)
-           if (filename ? fullpathcmp(lang, lp->sl_fname, FALSE) == FPC_SAME
-                        : STRICMP(lang, lp->sl_name) == 0)
+       for (slang = first_lang; slang != NULL; slang = slang->sl_next)
+           if (filename ? fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME
+                        : STRICMP(lang, slang->sl_name) == 0)
            {
                region_mask = REGION_ALL;
                if (!filename && region != NULL)
                {
                    /* find region in sl_regions */
-                   c = find_region(lp->sl_regions, region);
+                   c = find_region(slang->sl_regions, region);
                    if (c == REGION_ALL)
                    {
-                       if (lp->sl_add)
+                       if (slang->sl_add)
                        {
-                           if (*lp->sl_regions != NUL)
+                           if (*slang->sl_regions != NUL)
                                /* This addition file is for other regions. */
                                region_mask = 0;
                        }
@@ -3663,11 +3673,11 @@ did_set_spelllang(buf)
                        ga_clear(&ga);
                        return e_outofmem;
                    }
-                   LANGP_ENTRY(ga, ga.ga_len)->lp_slang = lp;
+                   LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
                    LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
                    ++ga.ga_len;
-                   use_midword(lp, buf);
-                   if (lp->sl_nobreak)
+                   use_midword(slang, buf);
+                   if (slang->sl_nobreak)
                        nobreak = TRUE;
                }
            }
@@ -3705,10 +3715,10 @@ did_set_spelllang(buf)
        }
 
        /* Check if it was loaded already. */
-       for (lp = first_lang; lp != NULL; lp = lp->sl_next)
-           if (fullpathcmp(spf_name, lp->sl_fname, FALSE) == FPC_SAME)
+       for (slang = first_lang; slang != NULL; slang = slang->sl_next)
+           if (fullpathcmp(spf_name, slang->sl_fname, FALSE) == FPC_SAME)
                break;
-       if (lp == NULL)
+       if (slang == NULL)
        {
            /* Not loaded, try loading it now.  The language name includes the
             * region name, the region is ignored otherwise.  for int_wordlist
@@ -3722,33 +3732,35 @@ did_set_spelllang(buf)
                if (p != NULL)
                    *p = NUL;   /* truncate at ".encoding.add" */
            }
-           lp = spell_load_file(spf_name, lang, NULL, TRUE);
+           slang = spell_load_file(spf_name, lang, NULL, TRUE);
 
            /* If one of the languages has NOBREAK we assume the addition
             * files also have this. */
-           if (lp != NULL && nobreak)
-               lp->sl_nobreak = TRUE;
+           if (slang != NULL && nobreak)
+               slang->sl_nobreak = TRUE;
        }
-       if (lp != NULL && ga_grow(&ga, 1) == OK)
+       if (slang != NULL && ga_grow(&ga, 1) == OK)
        {
            region_mask = REGION_ALL;
            if (use_region != NULL && !dont_use_region)
            {
                /* find region in sl_regions */
-               c = find_region(lp->sl_regions, use_region);
+               c = find_region(slang->sl_regions, use_region);
                if (c != REGION_ALL)
                    region_mask = 1 << c;
-               else if (*lp->sl_regions != NUL)
+               else if (*slang->sl_regions != NUL)
                    /* This spell file is for other regions. */
                    region_mask = 0;
            }
 
            if (region_mask != 0)
            {
-               LANGP_ENTRY(ga, ga.ga_len)->lp_slang = lp;
+               LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
+               LANGP_ENTRY(ga, ga.ga_len)->lp_sallang = NULL;
+               LANGP_ENTRY(ga, ga.ga_len)->lp_replang = NULL;
                LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
                ++ga.ga_len;
-               use_midword(lp, buf);
+               use_midword(slang, buf);
            }
        }
     }
@@ -3757,6 +3769,50 @@ did_set_spelllang(buf)
     ga_clear(&buf->b_langp);
     buf->b_langp = ga;
 
+    /* For each language figure out what language to use for sound folding and
+     * REP items.  If the language doesn't support it itself use another one
+     * with the same name.  E.g. for "en-math" use "en". */
+    for (i = 0; i < ga.ga_len; ++i)
+    {
+       lp = LANGP_ENTRY(ga, i);
+
+       /* sound folding */
+       if (lp->lp_slang->sl_sal.ga_len > 0)
+           /* language does sound folding itself */
+           lp->lp_sallang = lp->lp_slang;
+       else
+           /* find first similar language that does sound folding */
+           for (j = 0; j < ga.ga_len; ++j)
+           {
+               lp2 = LANGP_ENTRY(ga, j);
+               if (lp2->lp_slang->sl_sal.ga_len > 0
+                       && STRNCMP(lp->lp_slang->sl_name,
+                                             lp2->lp_slang->sl_name, 2) == 0)
+               {
+                   lp->lp_sallang = lp2->lp_slang;
+                   break;
+               }
+           }
+
+       /* REP items */
+       if (lp->lp_slang->sl_rep.ga_len > 0)
+           /* language has REP items itself */
+           lp->lp_replang = lp->lp_slang;
+       else
+           /* find first similar language that does sound folding */
+           for (j = 0; j < ga.ga_len; ++j)
+           {
+               lp2 = LANGP_ENTRY(ga, j);
+               if (lp2->lp_slang->sl_rep.ga_len > 0
+                       && STRNCMP(lp->lp_slang->sl_name,
+                                             lp2->lp_slang->sl_name, 2) == 0)
+               {
+                   lp->lp_replang = lp2->lp_slang;
+                   break;
+               }
+           }
+    }
+
     return NULL;
 }
 
@@ -3954,7 +4010,7 @@ badword_captype(word, end)
     void
 spell_free_all()
 {
-    slang_T    *lp;
+    slang_T    *slang;
     buf_T      *buf;
     char_u     fname[MAXPATHL];
 
@@ -3964,9 +4020,9 @@ spell_free_all()
 
     while (first_lang != NULL)
     {
-       lp = first_lang;
-       first_lang = lp->sl_next;
-       slang_free(lp);
+       slang = first_lang;
+       first_lang = slang->sl_next;
+       slang_free(slang);
     }
 
     if (int_wordlist != NULL)
@@ -4028,17 +4084,17 @@ spell_reload_one(fname, added_word)
     char_u     *fname;
     int                added_word;     /* invoked through "zg" */
 {
-    slang_T    *lp;
+    slang_T    *slang;
     int                didit = FALSE;
 
-    for (lp = first_lang; lp != NULL; lp = lp->sl_next)
+    for (slang = first_lang; slang != NULL; slang = slang->sl_next)
     {
-       if (fullpathcmp(fname, lp->sl_fname, FALSE) == FPC_SAME)
+       if (fullpathcmp(fname, slang->sl_fname, FALSE) == FPC_SAME)
        {
-           slang_clear(lp);
-           if (spell_load_file(fname, NULL, lp, FALSE) == NULL)
+           slang_clear(slang);
+           if (spell_load_file(fname, NULL, slang, FALSE) == NULL)
                /* reloading failed, clear the language */
-               slang_clear(lp);
+               slang_clear(slang);
            redraw_all_later(NOT_VALID);
            didit = TRUE;
        }
@@ -8712,6 +8768,8 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
     static int expr_busy = FALSE;
 #endif
     int                c;
+    int                i;
+    langp_T    *lp;
 
     /*
      * Set the info in "*su".
@@ -8739,6 +8797,20 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
     if (need_cap)
        su->su_badflags |= WF_ONECAP;
 
+    /* Find the default language for sound folding.  We simply use the first
+     * one in 'spelllang' that supports sound folding.  That's good for when
+     * using multiple files for one language, it's not that bad when mixing
+     * languages (e.g., "pl,en"). */
+    for (i = 0; i < curbuf->b_langp.ga_len; ++i)
+    {
+       lp = LANGP_ENTRY(curbuf->b_langp, i);
+       if (lp->lp_sallang != NULL)
+       {
+           su->su_sallang = lp->lp_sallang;
+           break;
+       }
+    }
+
     /* If the word is not capitalised and spell_check() doesn't consider the
      * word to be bad then it might need to be capitalised.  Add a suggestion
      * for that. */
@@ -8747,7 +8819,7 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
     {
        make_case_word(su->su_badword, buf, WF_ONECAP);
        add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE,
-                                                                    0, TRUE);
+                                                    0, TRUE, su->su_sallang);
     }
 
     /* Ban the bad word itself.  It may appear in another region. */
@@ -8825,7 +8897,7 @@ spell_suggest_expr(su, expr)
                score = get_spellword(li->li_tv.vval.v_list, &p);
                if (score >= 0)
                    add_suggestion(su, &su->su_ga, p,
-                                              su->su_badlen, score, 0, TRUE);
+                              su->su_badlen, score, 0, TRUE, su->su_sallang);
            }
        list_unref(list);
     }
@@ -8882,7 +8954,7 @@ spell_suggest_file(su, fname)
            }
 
            add_suggestion(su, &su->su_ga, p, su->su_badlen,
-                                                        SCORE_FILE, 0, TRUE);
+                                        SCORE_FILE, 0, TRUE, su->su_sallang);
        }
     }
 
@@ -9091,7 +9163,8 @@ suggest_try_special(su)
        su->su_fbadword[len] = NUL;
        make_case_word(su->su_fbadword, word, su->su_badflags);
        su->su_fbadword[len] = c;
-       add_suggestion(su, &su->su_ga, word, su->su_badlen, SCORE_DEL, 0, TRUE);
+       add_suggestion(su, &su->su_ga, word, su->su_badlen, SCORE_DEL,
+                                                    0, TRUE, su->su_sallang);
     }
 }
 
@@ -9152,9 +9225,9 @@ suggest_try_change(su)
     p = su->su_badptr + su->su_badlen;
     (void)spell_casefold(p, STRLEN(p), fword + n, MAXWLEN - n);
 
-    for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
+       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
        slang = lp->lp_slang;
 
        /* If reloading a spell file fails it's still in the list but
@@ -9340,8 +9413,9 @@ suggest_try_change(su)
                        {
                            preword[sp->ts_prewordlen] = NUL;
                            add_suggestion(su, &su->su_ga, preword,
-                                       sp->ts_splitfidx - repextra,
-                                                     sp->ts_score, 0, FALSE);
+                                   sp->ts_splitfidx - repextra,
+                                   sp->ts_score, 0, FALSE,
+                                   lp->lp_sallang);
                            break;
                        }
                    }
@@ -9466,7 +9540,8 @@ suggest_try_change(su)
 
                    add_suggestion(su, &su->su_ga, preword,
                            sp->ts_fidx - repextra,
-                                          sp->ts_score + newscore, 0, FALSE);
+                                    sp->ts_score + newscore, 0, FALSE,
+                                    lp->lp_sallang);
                }
                else if ((sp->ts_fidx >= sp->ts_fidxtry || fword_ends)
 #ifdef FEAT_MBYTE
@@ -10161,19 +10236,22 @@ suggest_try_change(su)
 
            case STATE_REP_INI:
                /* Check if matching with REP items from the .aff file would
-                * work.  Quickly skip if there are no REP items or the score
-                * is going to be too high anyway. */
-               gap = &slang->sl_rep;
-               if (gap->ga_len == 0
-                              || sp->ts_score + SCORE_REP >= su->su_maxscore)
+                * work.  Quickly skip if:
+                * - there are no REP items
+                * - the score is going to be too high anyway
+                * - already applied a REP item or swapped here  */
+               if (lp->lp_replang == NULL
+                       || sp->ts_score + SCORE_REP >= su->su_maxscore
+                       || sp->ts_fidx < sp->ts_fidxtry)
                {
                    sp->ts_state = STATE_FINAL;
                    break;
                }
+               gap = &lp->lp_replang->sl_rep;
 
                /* Use the first byte to quickly find the first entry that
                 * may match.  If the index is -1 there is none. */
-               sp->ts_curi = slang->sl_rep_first[fword[sp->ts_fidx]];
+               sp->ts_curi = lp->lp_replang->sl_rep_first[fword[sp->ts_fidx]];
                if (sp->ts_curi < 0)
                {
                    sp->ts_state = STATE_FINAL;
@@ -10189,7 +10267,7 @@ suggest_try_change(su)
                 * word is valid. */
                p = fword + sp->ts_fidx;
 
-               gap = &slang->sl_rep;
+               gap = &lp->lp_replang->sl_rep;
                while (sp->ts_curi < gap->ga_len)
                {
                    ftp = (fromto_T *)gap->ga_data + sp->ts_curi++;
@@ -10223,7 +10301,7 @@ suggest_try_change(su)
                    }
                }
 
-               if (sp->ts_curi >= gap->ga_len)
+               if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP)
                    /* No (more) matches. */
                    sp->ts_state = STATE_FINAL;
 
@@ -10231,7 +10309,8 @@ suggest_try_change(su)
 
            case STATE_REP_UNDO:
                /* Undo a REP replacement and continue with the next one. */
-               ftp = (fromto_T *)slang->sl_rep.ga_data + sp->ts_curi - 1;
+               ftp = (fromto_T *)lp->lp_replang->sl_rep.ga_data
+                                                           + sp->ts_curi - 1;
                fl = STRLEN(ftp->ft_from);
                tl = STRLEN(ftp->ft_to);
                p = fword + sp->ts_fidx;
@@ -10490,9 +10569,9 @@ score_comp_sal(su)
        return;
 
     /* Use the sound-folding of the first language that supports it. */
-    for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
+       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
        if (lp->lp_slang->sl_sal.ga_len > 0)
        {
            /* soundfold the bad word */
@@ -10544,9 +10623,9 @@ score_combine(su)
     int                lpi;
 
     /* Add the alternate score to su_ga. */
-    for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
+       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
        if (lp->lp_slang->sl_sal.ga_len > 0)
        {
            /* soundfold the bad word */
@@ -10669,6 +10748,7 @@ stp_sal_score(stp, su, slang, badsound)
 
 /*
  * Find suggestions by comparing the word in a sound-a-like form.
+ * Note: This doesn't support postponed prefixes.
  */
     static void
 suggest_try_soundalike(su)
@@ -10690,15 +10770,17 @@ suggest_try_soundalike(su)
     int                sound_score;
     int                local_score;
     int                lpi;
+    slang_T    *slang;
 
     /* Do this for all languages that support sound folding. */
-    for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
-       if (lp->lp_slang->sl_sal.ga_len > 0)
+       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       slang = lp->lp_slang;
+       if (slang->sl_sal.ga_len > 0)
        {
            /* soundfold the bad word */
-           spell_soundfold(lp->lp_slang, su->su_fbadword, TRUE, salword);
+           spell_soundfold(slang, su->su_fbadword, TRUE, salword);
 
            /*
             * Go through the whole tree, soundfold each word and compare.
@@ -10709,13 +10791,13 @@ suggest_try_soundalike(su)
            {
                if (round == 1)
                {
-                   byts = lp->lp_slang->sl_fbyts;
-                   idxs = lp->lp_slang->sl_fidxs;
+                   byts = slang->sl_fbyts;
+                   idxs = slang->sl_fidxs;
                }
                else
                {
-                   byts = lp->lp_slang->sl_kbyts;
-                   idxs = lp->lp_slang->sl_kidxs;
+                   byts = slang->sl_kbyts;
+                   idxs = slang->sl_kidxs;
                    if (byts == NULL)       /* no keep-case words */
                        continue;
                }
@@ -10746,7 +10828,7 @@ suggest_try_soundalike(su)
                                tword[depth] = NUL;
                                /* Sound-fold.  Only in keep-case tree need to
                                 * case-fold the word. */
-                               spell_soundfold(lp->lp_slang, tword,
+                               spell_soundfold(slang, tword,
                                                        round == 1, tsalword);
 
                                /* Compute the edit distance between the
@@ -10782,7 +10864,8 @@ suggest_try_soundalike(su)
                                    if (sps_flags & SPS_DOUBLE)
                                        add_suggestion(su, &su->su_sga, p,
                                                su->su_badlen,
-                                                      sound_score, 0, FALSE);
+                                               sound_score, 0, FALSE,
+                                               lp->lp_sallang);
                                    else
                                    {
                                        /* Compute the score. */
@@ -10796,11 +10879,14 @@ suggest_try_soundalike(su)
                                            add_suggestion(su, &su->su_ga, p,
                                                    su->su_badlen,
                                                  RESCORE(score, sound_score),
-                                                          sound_score, TRUE);
+                                                   sound_score, TRUE,
+                                                   lp->lp_sallang);
                                        else
                                            add_suggestion(su, &su->su_ga, p,
                                                    su->su_badlen,
-                                              score + sound_score, 0, FALSE);
+                                                   score + sound_score,
+                                                   0, FALSE,
+                                                   lp->lp_sallang);
                                    }
                                }
                            }
@@ -10985,7 +11071,7 @@ similar_chars(slang, c1, c2)
  * with spell_edit_score().
  */
     static void
-add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus)
+add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang)
     suginfo_T  *su;
     garray_T   *gap;
     char_u     *goodword;
@@ -10993,6 +11079,7 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus)
     int                score;
     int                altscore;
     int                had_bonus;      /* value for st_had_bonus */
+    slang_T    *slang;         /* language for sound folding */
 {
     suggest_T   *stp;
     int                i;
@@ -11048,6 +11135,8 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus)
                    stp[i].st_altscore = altscore;
                    stp[i].st_had_bonus = had_bonus;
                }
+               if (stp[i].st_slang == NULL)
+                   stp[i].st_slang = slang;
                break;
            }
 
@@ -11062,6 +11151,7 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus)
                stp->st_altscore = altscore;
                stp->st_had_bonus = had_bonus;
                stp->st_orglen = badlen;
+               stp->st_slang = slang;
                ++gap->ga_len;
 
                /* If we have too many suggestions now, sort the list and keep
@@ -11146,30 +11236,51 @@ rescore_suggestions(su)
     langp_T    *lp;
     suggest_T  *stp;
     char_u     sal_badword[MAXWLEN];
+    char_u     sal_badword2[MAXWLEN];
     int                i;
     int                lpi;
+    slang_T    *slang_first = NULL;
+    slang_T    *slang;
 
-    for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
+       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
        if (lp->lp_slang->sl_sal.ga_len > 0)
        {
            /* soundfold the bad word */
-           spell_soundfold(lp->lp_slang, su->su_fbadword, TRUE, sal_badword);
+           slang_first = lp->lp_slang;
+           spell_soundfold(slang_first, su->su_fbadword, TRUE, sal_badword);
+           break;
+       }
+    }
 
-           for (i = 0; i < su->su_ga.ga_len; ++i)
+    if (slang_first != NULL)
+    {
+       for (i = 0; i < su->su_ga.ga_len; ++i)
+       {
+           /* Only rescore suggestions that have no sal score yet and do have
+            * a language. */
+           stp = &SUG(su->su_ga, i);
+           if (!stp->st_had_bonus && stp->st_slang != NULL)
            {
-               stp = &SUG(su->su_ga, i);
-               if (!stp->st_had_bonus)
+               slang = stp->st_slang;
+               if (slang->sl_sal.ga_len > 0)
                {
-                   stp->st_altscore = stp_sal_score(stp, su,
-                                                  lp->lp_slang, sal_badword);
+                   if (slang == slang_first)
+                       stp->st_altscore = stp_sal_score(stp, su,
+                                                         slang, sal_badword);
+                   else
+                   {
+                       spell_soundfold(slang, su->su_fbadword,
+                                                         TRUE, sal_badword2);
+                       stp->st_altscore = stp_sal_score(stp, su,
+                                                        slang, sal_badword2);
+                   }
                    if (stp->st_altscore == SCORE_MAXMAX)
                        stp->st_altscore = SCORE_BIG;
                    stp->st_score = RESCORE(stp->st_score, stp->st_altscore);
                }
            }
-           break;
        }
     }
 }
@@ -11244,9 +11355,9 @@ eval_soundfold(word)
 
     if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
        /* Use the sound-folding of the first language that supports it. */
-       for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+       for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
        {
-           lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
+           lp = LANGP_ENTRY(curbuf->b_langp, lpi);
            if (lp->lp_slang->sl_sal.ga_len > 0)
            {
                /* soundfold the word */