diff options
Diffstat (limited to 'src/nvim/spell.c')
-rw-r--r-- | src/nvim/spell.c | 181 |
1 files changed, 81 insertions, 100 deletions
diff --git a/src/nvim/spell.c b/src/nvim/spell.c index d7a6adef58..8ec28c7f61 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -72,6 +72,7 @@ #include "nvim/decoration.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" @@ -230,14 +231,6 @@ char *repl_to = NULL; /// caller can skip over the word. size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount) { - matchinf_T mi; // Most things are put in "mi" so that it can - // be passed to functions quickly. - size_t nrlen = 0; // found a number first - size_t wrongcaplen = 0; - bool count_word = docount; - bool use_camel_case = (wp->w_s->b_p_spo_flags & SPO_CAMEL) != 0; - bool is_camel_case = false; - // A word never starts at a space or a control character. Return quickly // then, skipping over the character. if ((uint8_t)(*ptr) <= ' ') { @@ -249,6 +242,13 @@ size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount return 1; } + size_t nrlen = 0; // found a number first + size_t wrongcaplen = 0; + bool count_word = docount; + bool use_camel_case = (wp->w_s->b_p_spo_flags & SPO_CAMEL) != 0; + bool is_camel_case = false; + + matchinf_T mi; // Most things are put in "mi" so that it can be passed to functions quickly. CLEAR_FIELD(mi); // A number is always OK. Also skip hexadecimal numbers 0xFF99 and @@ -540,7 +540,6 @@ static void find_word(matchinf_T *mip, int mode) int endlen[MAXWLEN]; // length at possible word endings idx_T endidx[MAXWLEN]; // possible word endings int endidxcnt = 0; - int c; // Repeat advancing in the tree until: // - there is a byte that doesn't match, @@ -582,7 +581,7 @@ static void find_word(matchinf_T *mip, int mode) } // Perform a binary search in the list of accepted bytes. - c = (uint8_t)ptr[wlen]; + int c = (uint8_t)ptr[wlen]; if (c == TAB) { // <Tab> is handled like <Space> c = ' '; } @@ -626,9 +625,6 @@ static void find_word(matchinf_T *mip, int mode) } } - char *p; - bool word_ends; - // Verify that one of the possible endings is valid. Try the longest // first. while (endidxcnt > 0) { @@ -639,6 +635,7 @@ static void find_word(matchinf_T *mip, int mode) if (utf_head_off(ptr, ptr + wlen) > 0) { continue; // not at first byte of character } + bool word_ends; if (spell_iswordp(ptr + wlen, mip->mi_win)) { if (slang->sl_compprog == NULL && !slang->sl_nobreak) { continue; // next char is a word character @@ -655,7 +652,7 @@ static void find_word(matchinf_T *mip, int mode) // Compute byte length in original word, length may change // when folding case. This can be slow, take a shortcut when the // case-folded word is equal to the keep-case word. - p = mip->mi_word; + char *p = mip->mi_word; if (strncmp(ptr, p, (size_t)wlen) != 0) { for (char *s = ptr; s < ptr + wlen; MB_PTR_ADV(s)) { MB_PTR_ADV(p); @@ -691,10 +688,10 @@ static void find_word(matchinf_T *mip, int mode) // When mode is FIND_PREFIX the word must support the prefix: // check the prefix ID and the condition. Do that for the list at // mip->mi_prefarridx that find_prefix() filled. - c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx, - (int)flags, - mip->mi_word + mip->mi_cprefixlen, slang, - false); + int c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx, + (int)flags, + mip->mi_word + mip->mi_cprefixlen, slang, + false); if (c == 0) { continue; } @@ -765,6 +762,7 @@ static void find_word(matchinf_T *mip, int mode) if (mode == FIND_COMPOUND) { int capflags; + char *p; // Need to check the caps type of the appended compound // word. @@ -851,7 +849,7 @@ static void find_word(matchinf_T *mip, int mode) // byte length in keep-case word. Length may change when // folding case. This can be slow, take a shortcut when // the case-folded word is equal to the keep-case word. - p = mip->mi_fword; + char *p = mip->mi_fword; if (strncmp(ptr, p, (size_t)wlen) != 0) { for (char *s = ptr; s < ptr + wlen; MB_PTR_ADV(s)) { MB_PTR_ADV(p); @@ -1296,12 +1294,14 @@ static inline bool can_syn_spell(win_T *wp, linenr_T lnum, int col) /// @return 0 if not found, length of the badly spelled word otherwise. size_t spell_move_to(win_T *wp, int dir, smt_T behaviour, bool curline, hlf_T *attrp) { + if (no_spell_checking(wp)) { + return 0; + } + pos_T found_pos; size_t found_len = 0; hlf_T attr = HLF_COUNT; - size_t len; bool has_syntax = syntax_present(wp); - colnr_T col; char *buf = NULL; size_t buflen = 0; int skip = 0; @@ -1309,10 +1309,6 @@ size_t spell_move_to(win_T *wp, int dir, smt_T behaviour, bool curline, hlf_T *a bool found_one = false; bool wrapped = false; - if (no_spell_checking(wp)) { - return 0; - } - size_t ret = 0; // Start looking for bad word at the start of the line, because we can't @@ -1342,7 +1338,7 @@ size_t spell_move_to(win_T *wp, int dir, smt_T behaviour, bool curline, hlf_T *a while (!got_int) { char *line = ml_get_buf(wp->w_buffer, lnum); - len = (size_t)ml_get_buf_len(wp->w_buffer, lnum); + size_t len = (size_t)ml_get_buf_len(wp->w_buffer, lnum); if (buflen < len + MAXWLEN + 2) { xfree(buf); buflen = len + MAXWLEN + 2; @@ -1360,7 +1356,7 @@ size_t spell_move_to(win_T *wp, int dir, smt_T behaviour, bool curline, hlf_T *a capcol = (colnr_T)getwhitecols(line); } else if (curline && wp == curwin) { // For spellbadword(): check if first word needs a capital. - col = (colnr_T)getwhitecols(line); + colnr_T col = (colnr_T)getwhitecols(line); if (check_need_cap(curwin, lnum, col)) { capcol = col; } @@ -1409,7 +1405,7 @@ size_t spell_move_to(win_T *wp, int dir, smt_T behaviour, bool curline, hlf_T *a || ((colnr_T)(curline ? p - buf + (ptrdiff_t)len : p - buf) > wp->w_cursor.col)) { - col = (colnr_T)(p - buf); + colnr_T col = (colnr_T)(p - buf); bool no_plain_buffer = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) != 0; bool can_spell = !no_plain_buffer; @@ -1816,17 +1812,16 @@ void count_common_word(slang_T *lp, char *word, int len, uint8_t count) p = buf; } - wordcount_T *wc; hash_T hash = hash_hash(p); const size_t p_len = strlen(p); hashitem_T *hi = hash_lookup(&lp->sl_wordcount, p, p_len, hash); if (HASHITEM_EMPTY(hi)) { - wc = xmalloc(offsetof(wordcount_T, wc_word) + p_len + 1); + wordcount_T *wc = xmalloc(offsetof(wordcount_T, wc_word) + p_len + 1); memcpy(wc->wc_word, p, p_len + 1); wc->wc_count = count; hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash); } else { - wc = HI2WC(hi); + wordcount_T *wc = HI2WC(hi); wc->wc_count = (uint16_t)(wc->wc_count + count); if (wc->wc_count < count) { // check for overflow wc->wc_count = MAXWORDCOUNT; @@ -1882,14 +1877,14 @@ int init_syl_tab(slang_T *slang) static int count_syllables(slang_T *slang, const char *word) FUNC_ATTR_NONNULL_ALL { - int cnt = 0; - bool skip = false; - int len; - if (slang->sl_syllable == NULL) { return 0; } + int cnt = 0; + bool skip = false; + int len; + for (const char *p = word; *p != NUL; p += len) { // When running into a space reset counter. if (*p == ' ') { @@ -1929,25 +1924,14 @@ static int count_syllables(slang_T *slang, const char *word) /// @return NULL if it's OK, an untranslated error message otherwise. char *parse_spelllang(win_T *wp) { - garray_T ga; - char *splp; - char *region; char region_cp[3]; - bool filename; - int region_mask; - slang_T *slang; - int c; char lang[MAXWLEN + 1]; char spf_name[MAXPATHL]; - char *p; - int round; - char *spf; char *use_region = NULL; bool dont_use_region = false; bool nobreak = false; static bool recursive = false; char *ret_msg = NULL; - char *spl_copy; bufref_T bufref; set_bufref(&bufref, wp->w_buffer); @@ -1960,20 +1944,21 @@ char *parse_spelllang(win_T *wp) } recursive = true; + garray_T ga; ga_init(&ga, sizeof(langp_T), 2); clear_midword(wp); // Make a copy of 'spelllang', the SpellFileMissing autocommands may change // it under our fingers. - spl_copy = xstrdup(wp->w_s->b_p_spl); + char *spl_copy = xstrdup(wp->w_s->b_p_spl); wp->w_s->b_cjk = 0; // Loop over comma separated language names. - for (splp = spl_copy; *splp != NUL;) { + for (char *splp = spl_copy; *splp != NUL;) { // Get one language name. copy_option_part(&splp, lang, MAXWLEN, ","); - region = NULL; + char *region = NULL; int len = (int)strlen(lang); if (!valid_spelllang(lang)) { @@ -1985,6 +1970,8 @@ char *parse_spelllang(win_T *wp) continue; } + slang_T *slang; + bool filename; // If the name ends in ".spl" use it as the name of the spell file. // If there is a region name let "region" point to it and remove it // from the name. @@ -1992,7 +1979,7 @@ char *parse_spelllang(win_T *wp) filename = true; // Locate a region and remove it from the file name. - p = vim_strchr(path_tail(lang), '_'); + char *p = vim_strchr(path_tail(lang), '_'); if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2]) && !ASCII_ISALPHA(p[3])) { xstrlcpy(region_cp, p + 1, 3); @@ -2055,10 +2042,10 @@ char *parse_spelllang(win_T *wp) if (filename ? path_full_compare(lang, slang->sl_fname, false, true) == kEqualFiles : STRICMP(lang, slang->sl_name) == 0) { - region_mask = REGION_ALL; + int region_mask = REGION_ALL; if (!filename && region != NULL) { // find region in sl_regions - c = find_region(slang->sl_regions, region); + int c = find_region(slang->sl_regions, region); if (c == REGION_ALL) { if (slang->sl_add) { if (*slang->sl_regions != NUL) { @@ -2094,8 +2081,8 @@ char *parse_spelllang(win_T *wp) // round 1: load first name in 'spellfile'. // round 2: load second name in 'spellfile. // etc. - spf = curwin->w_s->b_p_spf; - for (round = 0; round == 0 || *spf != NUL; round++) { + char *spf = curwin->w_s->b_p_spf; + for (int round = 0; round == 0 || *spf != NUL; round++) { if (round == 0) { // Internal wordlist, if there is one. if (int_wordlist == NULL) { @@ -2105,11 +2092,12 @@ char *parse_spelllang(win_T *wp) } else { // One entry in 'spellfile'. copy_option_part(&spf, spf_name, MAXPATHL - 5, ","); - STRCAT(spf_name, ".spl"); + strcat(spf_name, ".spl"); + int c; // If it was already found above then skip it. for (c = 0; c < ga.ga_len; c++) { - p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname; + char *p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname; if (p != NULL && path_full_compare(spf_name, p, false, true) == kEqualFiles) { break; @@ -2120,6 +2108,8 @@ char *parse_spelllang(win_T *wp) } } + slang_T *slang; + // Check if it was loaded already. for (slang = first_lang; slang != NULL; slang = slang->sl_next) { if (path_full_compare(spf_name, slang->sl_fname, false, true) @@ -2135,7 +2125,7 @@ char *parse_spelllang(win_T *wp) STRCPY(lang, "internal wordlist"); } else { xstrlcpy(lang, path_tail(spf_name), MAXWLEN + 1); - p = vim_strchr(lang, '.'); + char *p = vim_strchr(lang, '.'); if (p != NULL) { *p = NUL; // truncate at ".encoding.add" } @@ -2149,10 +2139,10 @@ char *parse_spelllang(win_T *wp) } } if (slang != NULL) { - region_mask = REGION_ALL; + int region_mask = REGION_ALL; if (use_region != NULL && !dont_use_region) { // find region in sl_regions - c = find_region(slang->sl_regions, use_region); + int c = find_region(slang->sl_regions, use_region); if (c != REGION_ALL) { region_mask = 1 << c; } else if (*slang->sl_regions != NUL) { @@ -2687,7 +2677,7 @@ void ex_spellrepall(exarg_T *eap) char *p = xmalloc((size_t)get_cursor_line_len() + (size_t)addlen + 1); memmove(p, line, (size_t)curwin->w_cursor.col); STRCPY(p + curwin->w_cursor.col, repl_to); - STRCAT(p, line + curwin->w_cursor.col + repl_from_len); + strcat(p, line + curwin->w_cursor.col + repl_from_len); ml_replace(curwin->w_cursor.lnum, p, false); inserted_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col, (int)repl_from_len, (int)repl_to_len); @@ -2902,19 +2892,7 @@ static void spell_soundfold_sofo(slang_T *slang, const char *inword, char *res) // Multi-byte version of spell_soundfold(). static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) { - salitem_T *smp = (salitem_T *)slang->sl_sal.ga_data; int word[MAXWLEN] = { 0 }; - int wres[MAXWLEN] = { 0 }; - int *ws; - int *pf; - int j, z; - int reslen; - int k = 0; - int k0; - int n0; - int pri; - int p0 = -333; - int c0; bool did_white = false; // Convert the multi-byte string to a wide-character string. @@ -2942,17 +2920,24 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) } word[wordlen] = NUL; + salitem_T *smp = (salitem_T *)slang->sl_sal.ga_data; + int wres[MAXWLEN] = { 0 }; + int k = 0; + int p0 = -333; int c; // This algorithm comes from Aspell phonet.cpp. // Converted from C++ to C. Added support for multi-byte chars. // Changed to keep spaces. - int i = reslen = z = 0; + int i = 0; + int reslen = 0; + int z = 0; while ((c = word[i]) != NUL) { // Start with the first rule that has the character in the word. int n = slang->sl_sal_first[c & 0xff]; int z0 = 0; if (n >= 0) { + int *ws; // Check all rules for the same index byte. // If c is 0x300 need extra check for the end of the array, as // (c & 0xff) is NUL. @@ -2969,6 +2954,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) continue; } if (k > 2) { + int j; for (j = 2; j < k; j++) { if (word[i + j] != ws[j]) { break; @@ -2980,6 +2966,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) } } + int *pf; if ((pf = smp[n].sm_oneof_w) != NULL) { // Check for match with one of the chars in "sm_oneof". while (*pf != NUL && *pf != word[i + k]) { @@ -2991,10 +2978,10 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) k++; } char *s = smp[n].sm_rules; - pri = 5; // default priority + int pri = 5; // default priority p0 = (uint8_t)(*s); - k0 = k; + int k0 = k; while (*s == '-' && k > 1) { k--; s++; @@ -3022,8 +3009,8 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) && (!spell_iswordp_w(word + i + k0, curwin)))) { // search for followup rules, if: // followup and k > 1 and NO '-' in searchstring - c0 = word[i + k - 1]; - n0 = slang->sl_sal_first[c0 & 0xff]; + int c0 = word[i + k - 1]; + int n0 = slang->sl_sal_first[c0 & 0xff]; if (slang->sl_followup && k > 1 && n0 >= 0 && p0 != '-' && word[i + k] != NUL) { @@ -3042,6 +3029,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) } if (k0 > 2) { pf = word + i + k + 1; + int j; for (j = 2; j < k0; j++) { if (*pf++ != ws[j]) { break; @@ -3262,23 +3250,13 @@ void ex_spelldump(exarg_T *eap) /// @param dumpflags_arg DUMPFLAG_* void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) { - langp_T *lp; - slang_T *slang; idx_T arridx[MAXWLEN]; int curi[MAXWLEN]; char word[MAXWLEN]; - int c; - uint8_t *byts; - idx_T *idxs; linenr_T lnum = 0; - int depth; - int n; - int flags; char *region_names = NULL; // region names being used bool do_region = true; // dump region names and numbers - char *p; int dumpflags = dumpflags_arg; - int patlen; // When ignoring case or when the pattern starts with capital pass this on // to dump_word(). @@ -3286,7 +3264,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) if (ic) { dumpflags |= DUMPFLAG_ICASE; } else { - n = captype(pat, NULL); + int n = captype(pat, NULL); if (n == WF_ONECAP) { dumpflags |= DUMPFLAG_ONECAP; } else if (n == WF_ALLCAP @@ -3299,8 +3277,8 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) // Find out if we can support regions: All languages must support the same // regions or none at all. for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); - p = lp->lp_slang->sl_regions; + langp_T *lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + char *p = lp->lp_slang->sl_regions; if (p[0] != 0) { if (region_names == NULL) { // first language with regions region_names = p; @@ -3320,8 +3298,8 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) // Loop over all files loaded for the entries in 'spelllang'. for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) { - lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); - slang = lp->lp_slang; + langp_T *lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); + slang_T *slang = lp->lp_slang; if (slang->sl_fbyts == NULL) { // reloading failed continue; } @@ -3331,6 +3309,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) ml_append(lnum++, IObuff, 0, false); } + int patlen; // When matching with a pattern and there are no prefixes only use // parts of the tree that match "pat". if (pat != NULL && slang->sl_pbyts == NULL) { @@ -3342,6 +3321,8 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) // round 1: case-folded tree // round 2: keep-case tree for (int round = 1; round <= 2; round++) { + uint8_t *byts; + idx_T *idxs; if (round == 1) { dumpflags &= ~DUMPFLAG_KEEPCASE; byts = slang->sl_fbyts; @@ -3354,7 +3335,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) if (byts == NULL) { continue; // array is empty } - depth = 0; + int depth = 0; arridx[0] = 0; curi[0] = 1; while (depth >= 0 && !got_int @@ -3366,16 +3347,16 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) ins_compl_check_keys(50, false); } else { // Do one more byte at this node. - n = arridx[depth] + curi[depth]; + int n = arridx[depth] + curi[depth]; curi[depth]++; - c = byts[n]; + int c = byts[n]; if (c == 0 || depth >= MAXWLEN - 1) { // End of word or reached maximum length, deal with the // word. // Don't use keep-case words in the fold-case tree, // they will appear in the keep-case tree. // Only use the word when the region matches. - flags = (int)idxs[n]; + int flags = (int)idxs[n]; if ((round == 2 || (flags & WF_KEEPCAP) == 0) && (flags & WF_NEEDCOMP) == 0 && (do_region @@ -3463,14 +3444,14 @@ static void dump_word(slang_T *slang, char *word, char *pat, Direction *dir, int // Add flags and regions after a slash. if ((flags & (WF_BANNED | WF_RARE | WF_REGION)) || keepcap) { STRCPY(badword, p); - STRCAT(badword, "/"); + strcat(badword, "/"); if (keepcap) { - STRCAT(badword, "="); + strcat(badword, "="); } if (flags & WF_BANNED) { - STRCAT(badword, "!"); + strcat(badword, "!"); } else if (flags & WF_RARE) { - STRCAT(badword, "?"); + strcat(badword, "?"); } if (flags & WF_REGION) { for (int i = 0; i < 7; i++) { |