diff options
Diffstat (limited to 'src/spell.c')
-rw-r--r-- | src/spell.c | 163 |
1 files changed, 119 insertions, 44 deletions
diff --git a/src/spell.c b/src/spell.c index 2b04bf8b3..56c891d82 100644 --- a/src/spell.c +++ b/src/spell.c @@ -375,7 +375,7 @@ struct slang_S char_u *sl_midword; /* MIDWORD string or NULL */ int sl_compmax; /* COMPOUNDMAX (default: MAXWLEN) */ - int sl_compminlen; /* COMPOUNDMIN (default: MAXWLEN) */ + int sl_compminlen; /* COMPOUNDMIN (default: 0) */ int sl_compsylmax; /* COMPOUNDSYLMAX (default: MAXWLEN) */ regprog_T *sl_compprog; /* COMPOUNDFLAGS turned into a regexp progrm * (NULL when no compounding) */ @@ -1299,7 +1299,7 @@ find_word(mip, mode) /* For multi-byte chars check character length against * COMPOUNDMIN. */ if (has_mbyte - && slang->sl_compminlen < MAXWLEN + && slang->sl_compminlen > 0 && mb_charlen_len(mip->mi_word + mip->mi_compoff, wlen - mip->mi_compoff) < slang->sl_compminlen) continue; @@ -1388,6 +1388,8 @@ find_word(mip, mode) { int save_result = mip->mi_result; char_u *save_end = mip->mi_end; + langp_T *save_lp = mip->mi_lp; + int lpi; /* Check that a valid word follows. If there is one and we * are compounding, it will set "mi_result", thus we are @@ -1417,25 +1419,43 @@ find_word(mip, mode) #endif c = mip->mi_compoff; ++mip->mi_complen; - find_word(mip, FIND_COMPOUND); - /* When NOBREAK any word that matches is OK. Otherwise we - * need to find the longest match, thus try with keep-case and - * prefix too. */ - if (!slang->sl_nobreak || mip->mi_result == SP_BAD) + /* For NOBREAK we need to try all NOBREAK languages, at least + * to find the ".add" file(s). */ + for (lpi = 0; lpi < mip->mi_buf->b_langp.ga_len; ++lpi) { - /* Find following word in keep-case tree. */ - mip->mi_compoff = wlen; - find_word(mip, FIND_KEEPCOMPOUND); + if (slang->sl_nobreak) + { + mip->mi_lp = LANGP_ENTRY(mip->mi_buf->b_langp, lpi); + if (mip->mi_lp->lp_slang->sl_fidxs == NULL + || !mip->mi_lp->lp_slang->sl_nobreak) + continue; + } + + find_word(mip, FIND_COMPOUND); + /* When NOBREAK any word that matches is OK. Otherwise we + * need to find the longest match, thus try with keep-case + * and prefix too. */ if (!slang->sl_nobreak || mip->mi_result == SP_BAD) { - /* Check for following word with prefix. */ - mip->mi_compoff = c; - find_prefix(mip, FIND_COMPOUND); + /* Find following word in keep-case tree. */ + mip->mi_compoff = wlen; + find_word(mip, FIND_KEEPCOMPOUND); + + if (!slang->sl_nobreak || mip->mi_result == SP_BAD) + { + /* Check for following word with prefix. */ + mip->mi_compoff = c; + find_prefix(mip, FIND_COMPOUND); + } } + + if (!slang->sl_nobreak) + break; } --mip->mi_complen; + mip->mi_lp = save_lp; if (slang->sl_nobreak) { @@ -2037,6 +2057,13 @@ spell_cat_line(buf, line, maxlen) } } +typedef struct spelload_S +{ + char_u sl_lang[MAXWLEN + 1]; /* language name */ + slang_T *sl_slang; /* resulting slang_T struct */ + int sl_nobreak; /* NOBREAK language found */ +} spelload_T; + /* * Load word list(s) for "lang" from Vim spell file(s). * "lang" must be the language without the region: e.g., "en". @@ -2047,35 +2074,37 @@ spell_load_lang(lang) { char_u fname_enc[85]; int r; - char_u langcp[MAXWLEN + 1]; + spelload_T sl; /* Copy the language name to pass it to spell_load_cb() as a cookie. * It's truncated when an error is detected. */ - STRCPY(langcp, lang); + STRCPY(sl.sl_lang, lang); + sl.sl_slang = NULL; + sl.sl_nobreak = FALSE; /* * Find the first spell file for "lang" in 'runtimepath' and load it. */ vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5, "spell/%s.%s.spl", lang, spell_enc()); - r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &langcp); + r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl); - if (r == FAIL && *langcp != NUL) + if (r == FAIL && *sl.sl_lang != NUL) { /* Try loading the ASCII version. */ vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5, "spell/%s.ascii.spl", lang); - r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &langcp); + r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl); } if (r == FAIL) smsg((char_u *)_("Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""), lang, spell_enc(), lang); - else if (*langcp != NUL) + else if (sl.sl_slang != NULL) { - /* Load all the additions. */ + /* At least one file was loaded, now load all the additions. */ STRCPY(fname_enc + STRLEN(fname_enc) - 3, "add.spl"); - do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &langcp); + do_in_runtimepath(fname_enc, TRUE, spell_load_cb, &sl); } } @@ -2122,7 +2151,6 @@ slang_alloc(lang) lp->sl_name = vim_strsave(lang); ga_init2(&lp->sl_rep, sizeof(fromto_T), 10); lp->sl_compmax = MAXWLEN; - lp->sl_compminlen = MAXWLEN; lp->sl_compsylmax = MAXWLEN; } return lp; @@ -2237,7 +2265,7 @@ slang_clear(lp) #endif lp->sl_compmax = MAXWLEN; - lp->sl_compminlen = MAXWLEN; + lp->sl_compminlen = 0; lp->sl_compsylmax = MAXWLEN; lp->sl_regions[0] = NUL; } @@ -2249,9 +2277,23 @@ slang_clear(lp) static void spell_load_cb(fname, cookie) char_u *fname; - void *cookie; /* points to the language name */ + void *cookie; { - (void)spell_load_file(fname, (char_u *)cookie, NULL, FALSE); + spelload_T *slp = (spelload_T *)cookie; + slang_T *slang; + + slang = spell_load_file(fname, slp->sl_lang, NULL, FALSE); + if (slang != NULL) + { + /* When a previously loaded file has NOBREAK also use it for the + * ".add" files. */ + if (slp->sl_nobreak && slang->sl_add) + slang->sl_nobreak = TRUE; + else if (slang->sl_nobreak) + slp->sl_nobreak = TRUE; + + slp->sl_slang = slang; + } } /* @@ -2941,7 +2983,7 @@ read_compound(fd, slang, len) --todo; c = getc(fd); /* <compminlen> */ if (c < 1) - c = MAXWLEN; + c = 0; slang->sl_compminlen = c; --todo; @@ -3508,6 +3550,7 @@ did_set_spelllang(buf) char_u *spf; char_u *use_region = NULL; int dont_use_region = FALSE; + int nobreak = FALSE; ga_init2(&ga, sizeof(langp_T), 2); clear_midword(buf); @@ -3624,6 +3667,8 @@ did_set_spelllang(buf) LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask; ++ga.ga_len; use_midword(lp, buf); + if (lp->sl_nobreak) + nobreak = TRUE; } } } @@ -3678,6 +3723,11 @@ did_set_spelllang(buf) *p = NUL; /* truncate at ".encoding.add" */ } lp = 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 (lp != NULL && ga_grow(&ga, 1) == OK) { @@ -5229,8 +5279,6 @@ process_compflags(spin, aff, compflags) STRCPY(p, spin->si_compflags); STRCAT(p, "/"); } - else - *p = NUL; spin->si_compflags = p; tp = p + STRLEN(p); @@ -7703,37 +7751,55 @@ init_spellfile() char_u *fname; char_u *rtp; char_u *lend; + int aspath = FALSE; + char_u *lstart = curbuf->b_p_spl; if (*curbuf->b_p_spl != NUL && curbuf->b_langp.ga_len > 0) { - /* Find the end of the language name. Exclude the region. */ + /* Find the end of the language name. Exclude the region. If there + * is a path separator remember the start of the tail. */ for (lend = curbuf->b_p_spl; *lend != NUL && vim_strchr((char_u *)",._", *lend) == NULL; ++lend) - ; + if (vim_ispathsep(*lend)) + { + aspath = TRUE; + lstart = lend + 1; + } /* Loop over all entries in 'runtimepath'. Use the first one where we * are allowed to write. */ rtp = p_rtp; while (*rtp != NUL) { - /* Copy the path from 'runtimepath' to buf[]. */ - copy_option_part(&rtp, buf, MAXPATHL, ","); + if (aspath) + /* Use directory of an entry with path, e.g., for + * "/dir/lg.utf-8.spl" use "/dir". */ + vim_strncpy(buf, curbuf->b_p_spl, lstart - curbuf->b_p_spl - 1); + else + /* Copy the path from 'runtimepath' to buf[]. */ + copy_option_part(&rtp, buf, MAXPATHL, ","); if (filewritable(buf) == 2) { /* Use the first language name from 'spelllang' and the * encoding used in the first loaded .spl file. */ - fname = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang->sl_fname; - if (fname == NULL) - break; + if (aspath) + vim_strncpy(buf, curbuf->b_p_spl, lend - curbuf->b_p_spl); + else + { + l = STRLEN(buf); + vim_snprintf((char *)buf + l, MAXPATHL - l, + "/spell/%.*s", (int)(lend - lstart), lstart); + } l = STRLEN(buf); - vim_snprintf((char *)buf + l, MAXPATHL - l, - "/spell/%.*s.%s.add", - (int)(lend - curbuf->b_p_spl), curbuf->b_p_spl, - strstr((char *)gettail(fname), ".ascii.") != NULL - ? (char_u *)"ascii" : spell_enc()); + fname = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang->sl_fname; + vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", + fname != NULL + && strstr((char *)gettail(fname), ".ascii.") != NULL + ? (char_u *)"ascii" : spell_enc()); set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL); break; } + aspath = FALSE; } } } @@ -9293,7 +9359,7 @@ suggest_try_change(su) /* For multi-byte chars check character length against * COMPOUNDMIN. */ if (has_mbyte - && slang->sl_compminlen < MAXWLEN + && slang->sl_compminlen > 0 && mb_charlen(tword + sp->ts_splitoff) < slang->sl_compminlen) break; @@ -9430,7 +9496,7 @@ suggest_try_change(su) >= slang->sl_compminlen #ifdef FEAT_MBYTE && (!has_mbyte - || slang->sl_compminlen == MAXWLEN + || slang->sl_compminlen == 0 || mb_charlen(tword + sp->ts_splitoff) >= slang->sl_compminlen) #endif @@ -9470,7 +9536,12 @@ suggest_try_change(su) if (!try_compound && !fword_ends) { /* If we're going to split need to check that the - * words so far are valid for compounding. */ + * words so far are valid for compounding. If there + * is only one word it must not have the NEEDCOMPOUND + * flag. */ + if (sp->ts_complen == sp->ts_compsplit + && (flags & WF_NEEDCOMP)) + break; p = preword; while (*skiptowhite(p) != NUL) p = skipwhite(skiptowhite(p)); @@ -9576,7 +9647,11 @@ suggest_try_change(su) case STATE_ENDNUL: /* Past the NUL bytes in the node. */ su->su_badflags = sp->ts_save_badflags; - if (fword[sp->ts_fidx] == NUL) + if (fword[sp->ts_fidx] == NUL +#ifdef FEAT_MBYTE + && sp->ts_tcharlen == 0 +#endif + ) { /* The badword ends, can't use the bytes in this node. */ sp->ts_state = STATE_DEL; |