0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

updated for version 7.0141

This commit is contained in:
Bram Moolenaar
2005-09-05 22:05:30 +00:00
parent e344bead3e
commit 8b96d64cb5
3 changed files with 277 additions and 113 deletions

View File

@@ -318,7 +318,8 @@ getmark(c, changefile)
pos = curwin->w_cursor; pos = curwin->w_cursor;
listcmd_busy = TRUE; /* avoid that '' is changed */ 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; pos_copy = curwin->w_cursor;
posp = &pos_copy; posp = &pos_copy;

View File

@@ -3921,23 +3921,45 @@ nv_page(cap)
*/ */
static void static void
nv_gd(oap, nchar) nv_gd(oap, nchar)
oparg_T *oap; oparg_T *oap;
int nchar; int nchar;
{ {
int len; int len;
char_u *pat;
pos_T old_pos;
int t;
int save_p_ws;
int save_p_scs;
char_u *ptr; char_u *ptr;
if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0 if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0
|| (pat = alloc(len + 7)) == NULL) || find_decl(ptr, len, nchar == 'd', 0) == FAIL)
{
clearopbeep(oap); clearopbeep(oap);
return; #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;
int retval = OK;
int incl;
if ((pat = alloc(len + 7)) == NULL)
return FAIL;
/* Put "\V" before the pattern to avoid that the special meaning of "." /* Put "\V" before the pattern to avoid that the special meaning of "."
* and "~" causes trouble. */ * and "~" causes trouble. */
@@ -3954,42 +3976,70 @@ nv_gd(oap, nchar)
* With "gd" Search back for the start of the current function, then go * 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. * 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 */ setpcmark(); /* Set in findpar() otherwise */
curwin->w_cursor.lnum = 1; curwin->w_cursor.lnum = 1;
} }
else else
{ {
par_pos = curwin->w_cursor;
while (curwin->w_cursor.lnum > 1 && *skipwhite(ml_get_curline()) != NUL) while (curwin->w_cursor.lnum > 1 && *skipwhite(ml_get_curline()) != NUL)
--curwin->w_cursor.lnum; --curwin->w_cursor.lnum;
} }
curwin->w_cursor.col = 0; curwin->w_cursor.col = 0;
/* Search forward for the identifier, ignore comment lines. */ /* Search forward for the identifier, ignore comment lines. */
while ((t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, pat, 1L, 0, found_pos.lnum = 0;
RE_LAST)) != FAIL 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 #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 #endif
&& old_pos.lnum > curwin->w_cursor.lnum) if (!locally) /* global search: use first match found */
{ break;
/* Ignore this line, continue at start of next line. */ if (curwin->w_cursor.lnum >= par_pos.lnum)
++curwin->w_cursor.lnum; {
curwin->w_cursor.col = 0; /* 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; curwin->w_cursor = old_pos;
} }
else else
{ {
curwin->w_set_curswant = TRUE; 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 */ /* "n" searches forward now */
reset_search_dir(); reset_search_dir();
} }
@@ -3997,6 +4047,8 @@ nv_gd(oap, nchar)
vim_free(pat); vim_free(pat);
p_ws = save_p_ws; p_ws = save_p_ws;
p_scs = save_p_scs; p_scs = save_p_scs;
return retval;
} }
/* /*
@@ -6014,7 +6066,7 @@ nv_brackets(cap)
* Imitate strange Vi behaviour: When using "]]" with an operator * Imitate strange Vi behaviour: When using "]]" with an operator
* we also stop at '}'. * 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->oap->op_type != OP_NOP
&& cap->arg == FORWARD && flag == '{'))) && cap->arg == FORWARD && flag == '{')))
clearopbeep(cap->oap); clearopbeep(cap->oap);
@@ -6239,7 +6291,7 @@ nv_findpar(cap)
cap->oap->inclusive = FALSE; cap->oap->inclusive = FALSE;
cap->oap->use_reg_one = TRUE; cap->oap->use_reg_one = TRUE;
curwin->w_set_curswant = 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); clearopbeep(cap->oap);
else else
{ {

View File

@@ -423,7 +423,9 @@ static slang_T *first_lang = NULL;
*/ */
typedef struct langp_S 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 */ int lp_region; /* bitmask for region or REGION_ALL */
} langp_T; } langp_T;
@@ -476,6 +478,7 @@ typedef struct suginfo_S
char_u su_badword[MAXWLEN]; /* bad word truncated at su_badlen */ char_u su_badword[MAXWLEN]; /* bad word truncated at su_badlen */
char_u su_fbadword[MAXWLEN]; /* su_badword case-folded */ char_u su_fbadword[MAXWLEN]; /* su_badword case-folded */
hashtab_T su_banned; /* table with banned words */ hashtab_T su_banned; /* table with banned words */
slang_T *su_sallang; /* default language for sound folding */
} suginfo_T; } suginfo_T;
/* One word suggestion. Used in "si_ga". */ /* 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_altscore; /* used when st_score compares equal */
int st_salscore; /* st_score is for soundalike */ int st_salscore; /* st_score is for soundalike */
int st_had_bonus; /* bonus already included in score */ int st_had_bonus; /* bonus already included in score */
slang_T *st_slang; /* language used for sound folding */
} suggest_T; } suggest_T;
#define SUG(ga, i) (((suggest_T *)(ga).ga_data)[i]) #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 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 void set_map_str __ARGS((slang_T *lp, char_u *map));
static int similar_chars __ARGS((slang_T *slang, int c1, int c2)); 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 void add_banned __ARGS((suginfo_T *su, char_u *word));
static int was_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)); 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. */ * starting line again and accept the last match. */
lnum = wp->w_buffer->b_ml.ml_line_count; lnum = wp->w_buffer->b_ml.ml_line_count;
wrapped = TRUE; wrapped = TRUE;
if (!shortmess(SHM_SEARCH))
give_warning((char_u *)_(top_bot_msg), TRUE);
} }
capcol = -1; capcol = -1;
} }
@@ -2000,6 +2006,8 @@ spell_move_to(wp, dir, allwords, curline, attrp)
* starting line again and accept the first match. */ * starting line again and accept the first match. */
lnum = 1; lnum = 1;
wrapped = TRUE; 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 /* 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]; char_u region_cp[3];
int filename; int filename;
int region_mask; int region_mask;
slang_T *lp; slang_T *slang;
int c; int c;
char_u lang[MAXWLEN + 1]; char_u lang[MAXWLEN + 1];
char_u spf_name[MAXPATHL]; char_u spf_name[MAXPATHL];
@@ -3551,6 +3559,8 @@ did_set_spelllang(buf)
char_u *use_region = NULL; char_u *use_region = NULL;
int dont_use_region = FALSE; int dont_use_region = FALSE;
int nobreak = FALSE; int nobreak = FALSE;
int i, j;
langp_T *lp, *lp2;
ga_init2(&ga, sizeof(langp_T), 2); ga_init2(&ga, sizeof(langp_T), 2);
clear_midword(buf); clear_midword(buf);
@@ -3585,8 +3595,8 @@ did_set_spelllang(buf)
dont_use_region = TRUE; dont_use_region = TRUE;
/* Check if we loaded this language before. */ /* Check if we loaded this language before. */
for (lp = first_lang; lp != NULL; lp = lp->sl_next) for (slang = first_lang; slang != NULL; slang = slang->sl_next)
if (fullpathcmp(lang, lp->sl_fname, FALSE) == FPC_SAME) if (fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME)
break; break;
} }
else else
@@ -3602,8 +3612,8 @@ did_set_spelllang(buf)
dont_use_region = TRUE; dont_use_region = TRUE;
/* Check if we loaded this language before. */ /* Check if we loaded this language before. */
for (lp = first_lang; lp != NULL; lp = lp->sl_next) for (slang = first_lang; slang != NULL; slang = slang->sl_next)
if (STRICMP(lang, lp->sl_name) == 0) if (STRICMP(lang, slang->sl_name) == 0)
break; break;
} }
@@ -3617,7 +3627,7 @@ did_set_spelllang(buf)
} }
/* If not found try loading the language now. */ /* If not found try loading the language now. */
if (lp == NULL) if (slang == NULL)
{ {
if (filename) if (filename)
(void)spell_load_file(lang, lang, NULL, FALSE); (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". * Loop over the languages, there can be several files for "lang".
*/ */
for (lp = first_lang; lp != NULL; lp = lp->sl_next) for (slang = first_lang; slang != NULL; slang = slang->sl_next)
if (filename ? fullpathcmp(lang, lp->sl_fname, FALSE) == FPC_SAME if (filename ? fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME
: STRICMP(lang, lp->sl_name) == 0) : STRICMP(lang, slang->sl_name) == 0)
{ {
region_mask = REGION_ALL; region_mask = REGION_ALL;
if (!filename && region != NULL) if (!filename && region != NULL)
{ {
/* find region in sl_regions */ /* find region in sl_regions */
c = find_region(lp->sl_regions, region); c = find_region(slang->sl_regions, region);
if (c == REGION_ALL) 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. */ /* This addition file is for other regions. */
region_mask = 0; region_mask = 0;
} }
@@ -3663,11 +3673,11 @@ did_set_spelllang(buf)
ga_clear(&ga); ga_clear(&ga);
return e_outofmem; 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; LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
++ga.ga_len; ++ga.ga_len;
use_midword(lp, buf); use_midword(slang, buf);
if (lp->sl_nobreak) if (slang->sl_nobreak)
nobreak = TRUE; nobreak = TRUE;
} }
} }
@@ -3705,10 +3715,10 @@ did_set_spelllang(buf)
} }
/* Check if it was loaded already. */ /* Check if it was loaded already. */
for (lp = first_lang; lp != NULL; lp = lp->sl_next) for (slang = first_lang; slang != NULL; slang = slang->sl_next)
if (fullpathcmp(spf_name, lp->sl_fname, FALSE) == FPC_SAME) if (fullpathcmp(spf_name, slang->sl_fname, FALSE) == FPC_SAME)
break; break;
if (lp == NULL) if (slang == NULL)
{ {
/* Not loaded, try loading it now. The language name includes the /* Not loaded, try loading it now. The language name includes the
* region name, the region is ignored otherwise. for int_wordlist * region name, the region is ignored otherwise. for int_wordlist
@@ -3722,33 +3732,35 @@ did_set_spelllang(buf)
if (p != NULL) if (p != NULL)
*p = NUL; /* truncate at ".encoding.add" */ *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 /* If one of the languages has NOBREAK we assume the addition
* files also have this. */ * files also have this. */
if (lp != NULL && nobreak) if (slang != NULL && nobreak)
lp->sl_nobreak = TRUE; slang->sl_nobreak = TRUE;
} }
if (lp != NULL && ga_grow(&ga, 1) == OK) if (slang != NULL && ga_grow(&ga, 1) == OK)
{ {
region_mask = REGION_ALL; region_mask = REGION_ALL;
if (use_region != NULL && !dont_use_region) if (use_region != NULL && !dont_use_region)
{ {
/* find region in sl_regions */ /* 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) if (c != REGION_ALL)
region_mask = 1 << c; region_mask = 1 << c;
else if (*lp->sl_regions != NUL) else if (*slang->sl_regions != NUL)
/* This spell file is for other regions. */ /* This spell file is for other regions. */
region_mask = 0; region_mask = 0;
} }
if (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; LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
++ga.ga_len; ++ga.ga_len;
use_midword(lp, buf); use_midword(slang, buf);
} }
} }
} }
@@ -3757,6 +3769,50 @@ did_set_spelllang(buf)
ga_clear(&buf->b_langp); ga_clear(&buf->b_langp);
buf->b_langp = ga; 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; return NULL;
} }
@@ -3954,7 +4010,7 @@ badword_captype(word, end)
void void
spell_free_all() spell_free_all()
{ {
slang_T *lp; slang_T *slang;
buf_T *buf; buf_T *buf;
char_u fname[MAXPATHL]; char_u fname[MAXPATHL];
@@ -3964,9 +4020,9 @@ spell_free_all()
while (first_lang != NULL) while (first_lang != NULL)
{ {
lp = first_lang; slang = first_lang;
first_lang = lp->sl_next; first_lang = slang->sl_next;
slang_free(lp); slang_free(slang);
} }
if (int_wordlist != NULL) if (int_wordlist != NULL)
@@ -4028,17 +4084,17 @@ spell_reload_one(fname, added_word)
char_u *fname; char_u *fname;
int added_word; /* invoked through "zg" */ int added_word; /* invoked through "zg" */
{ {
slang_T *lp; slang_T *slang;
int didit = FALSE; 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); slang_clear(slang);
if (spell_load_file(fname, NULL, lp, FALSE) == NULL) if (spell_load_file(fname, NULL, slang, FALSE) == NULL)
/* reloading failed, clear the language */ /* reloading failed, clear the language */
slang_clear(lp); slang_clear(slang);
redraw_all_later(NOT_VALID); redraw_all_later(NOT_VALID);
didit = TRUE; didit = TRUE;
} }
@@ -8712,6 +8768,8 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
static int expr_busy = FALSE; static int expr_busy = FALSE;
#endif #endif
int c; int c;
int i;
langp_T *lp;
/* /*
* Set the info in "*su". * Set the info in "*su".
@@ -8739,6 +8797,20 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
if (need_cap) if (need_cap)
su->su_badflags |= WF_ONECAP; 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 /* 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 * word to be bad then it might need to be capitalised. Add a suggestion
* for that. */ * for that. */
@@ -8747,7 +8819,7 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
{ {
make_case_word(su->su_badword, buf, WF_ONECAP); make_case_word(su->su_badword, buf, WF_ONECAP);
add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE, 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. */ /* 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); score = get_spellword(li->li_tv.vval.v_list, &p);
if (score >= 0) if (score >= 0)
add_suggestion(su, &su->su_ga, p, 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); list_unref(list);
} }
@@ -8882,7 +8954,7 @@ spell_suggest_file(su, fname)
} }
add_suggestion(su, &su->su_ga, p, su->su_badlen, 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; su->su_fbadword[len] = NUL;
make_case_word(su->su_fbadword, word, su->su_badflags); make_case_word(su->su_fbadword, word, su->su_badflags);
su->su_fbadword[len] = c; 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; p = su->su_badptr + su->su_badlen;
(void)spell_casefold(p, STRLEN(p), fword + n, MAXWLEN - n); (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; slang = lp->lp_slang;
/* If reloading a spell file fails it's still in the list but /* 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; preword[sp->ts_prewordlen] = NUL;
add_suggestion(su, &su->su_ga, preword, add_suggestion(su, &su->su_ga, preword,
sp->ts_splitfidx - repextra, sp->ts_splitfidx - repextra,
sp->ts_score, 0, FALSE); sp->ts_score, 0, FALSE,
lp->lp_sallang);
break; break;
} }
} }
@@ -9466,7 +9540,8 @@ suggest_try_change(su)
add_suggestion(su, &su->su_ga, preword, add_suggestion(su, &su->su_ga, preword,
sp->ts_fidx - repextra, 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) else if ((sp->ts_fidx >= sp->ts_fidxtry || fword_ends)
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
@@ -10161,19 +10236,22 @@ suggest_try_change(su)
case STATE_REP_INI: case STATE_REP_INI:
/* Check if matching with REP items from the .aff file would /* Check if matching with REP items from the .aff file would
* work. Quickly skip if there are no REP items or the score * work. Quickly skip if:
* is going to be too high anyway. */ * - there are no REP items
gap = &slang->sl_rep; * - the score is going to be too high anyway
if (gap->ga_len == 0 * - already applied a REP item or swapped here */
|| sp->ts_score + SCORE_REP >= su->su_maxscore) if (lp->lp_replang == NULL
|| sp->ts_score + SCORE_REP >= su->su_maxscore
|| sp->ts_fidx < sp->ts_fidxtry)
{ {
sp->ts_state = STATE_FINAL; sp->ts_state = STATE_FINAL;
break; break;
} }
gap = &lp->lp_replang->sl_rep;
/* Use the first byte to quickly find the first entry that /* Use the first byte to quickly find the first entry that
* may match. If the index is -1 there is none. */ * 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) if (sp->ts_curi < 0)
{ {
sp->ts_state = STATE_FINAL; sp->ts_state = STATE_FINAL;
@@ -10189,7 +10267,7 @@ suggest_try_change(su)
* word is valid. */ * word is valid. */
p = fword + sp->ts_fidx; p = fword + sp->ts_fidx;
gap = &slang->sl_rep; gap = &lp->lp_replang->sl_rep;
while (sp->ts_curi < gap->ga_len) while (sp->ts_curi < gap->ga_len)
{ {
ftp = (fromto_T *)gap->ga_data + sp->ts_curi++; 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. */ /* No (more) matches. */
sp->ts_state = STATE_FINAL; sp->ts_state = STATE_FINAL;
@@ -10231,7 +10309,8 @@ suggest_try_change(su)
case STATE_REP_UNDO: case STATE_REP_UNDO:
/* Undo a REP replacement and continue with the next one. */ /* 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); fl = STRLEN(ftp->ft_from);
tl = STRLEN(ftp->ft_to); tl = STRLEN(ftp->ft_to);
p = fword + sp->ts_fidx; p = fword + sp->ts_fidx;
@@ -10490,9 +10569,9 @@ score_comp_sal(su)
return; return;
/* Use the sound-folding of the first language that supports it. */ /* 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) if (lp->lp_slang->sl_sal.ga_len > 0)
{ {
/* soundfold the bad word */ /* soundfold the bad word */
@@ -10544,9 +10623,9 @@ score_combine(su)
int lpi; int lpi;
/* Add the alternate score to su_ga. */ /* 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) if (lp->lp_slang->sl_sal.ga_len > 0)
{ {
/* soundfold the bad word */ /* 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. * Find suggestions by comparing the word in a sound-a-like form.
* Note: This doesn't support postponed prefixes.
*/ */
static void static void
suggest_try_soundalike(su) suggest_try_soundalike(su)
@@ -10690,15 +10770,17 @@ suggest_try_soundalike(su)
int sound_score; int sound_score;
int local_score; int local_score;
int lpi; int lpi;
slang_T *slang;
/* Do this for all languages that support sound folding. */ /* 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); lp = LANGP_ENTRY(curbuf->b_langp, lpi);
if (lp->lp_slang->sl_sal.ga_len > 0) slang = lp->lp_slang;
if (slang->sl_sal.ga_len > 0)
{ {
/* soundfold the bad word */ /* 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. * Go through the whole tree, soundfold each word and compare.
@@ -10709,13 +10791,13 @@ suggest_try_soundalike(su)
{ {
if (round == 1) if (round == 1)
{ {
byts = lp->lp_slang->sl_fbyts; byts = slang->sl_fbyts;
idxs = lp->lp_slang->sl_fidxs; idxs = slang->sl_fidxs;
} }
else else
{ {
byts = lp->lp_slang->sl_kbyts; byts = slang->sl_kbyts;
idxs = lp->lp_slang->sl_kidxs; idxs = slang->sl_kidxs;
if (byts == NULL) /* no keep-case words */ if (byts == NULL) /* no keep-case words */
continue; continue;
} }
@@ -10746,7 +10828,7 @@ suggest_try_soundalike(su)
tword[depth] = NUL; tword[depth] = NUL;
/* Sound-fold. Only in keep-case tree need to /* Sound-fold. Only in keep-case tree need to
* case-fold the word. */ * case-fold the word. */
spell_soundfold(lp->lp_slang, tword, spell_soundfold(slang, tword,
round == 1, tsalword); round == 1, tsalword);
/* Compute the edit distance between the /* Compute the edit distance between the
@@ -10782,7 +10864,8 @@ suggest_try_soundalike(su)
if (sps_flags & SPS_DOUBLE) if (sps_flags & SPS_DOUBLE)
add_suggestion(su, &su->su_sga, p, add_suggestion(su, &su->su_sga, p,
su->su_badlen, su->su_badlen,
sound_score, 0, FALSE); sound_score, 0, FALSE,
lp->lp_sallang);
else else
{ {
/* Compute the score. */ /* Compute the score. */
@@ -10796,11 +10879,14 @@ suggest_try_soundalike(su)
add_suggestion(su, &su->su_ga, p, add_suggestion(su, &su->su_ga, p,
su->su_badlen, su->su_badlen,
RESCORE(score, sound_score), RESCORE(score, sound_score),
sound_score, TRUE); sound_score, TRUE,
lp->lp_sallang);
else else
add_suggestion(su, &su->su_ga, p, add_suggestion(su, &su->su_ga, p,
su->su_badlen, 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(). * with spell_edit_score().
*/ */
static void 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; suginfo_T *su;
garray_T *gap; garray_T *gap;
char_u *goodword; char_u *goodword;
@@ -10993,6 +11079,7 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus)
int score; int score;
int altscore; int altscore;
int had_bonus; /* value for st_had_bonus */ int had_bonus; /* value for st_had_bonus */
slang_T *slang; /* language for sound folding */
{ {
suggest_T *stp; suggest_T *stp;
int i; int i;
@@ -11048,6 +11135,8 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus)
stp[i].st_altscore = altscore; stp[i].st_altscore = altscore;
stp[i].st_had_bonus = had_bonus; stp[i].st_had_bonus = had_bonus;
} }
if (stp[i].st_slang == NULL)
stp[i].st_slang = slang;
break; break;
} }
@@ -11062,6 +11151,7 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus)
stp->st_altscore = altscore; stp->st_altscore = altscore;
stp->st_had_bonus = had_bonus; stp->st_had_bonus = had_bonus;
stp->st_orglen = badlen; stp->st_orglen = badlen;
stp->st_slang = slang;
++gap->ga_len; ++gap->ga_len;
/* If we have too many suggestions now, sort the list and keep /* If we have too many suggestions now, sort the list and keep
@@ -11146,30 +11236,51 @@ rescore_suggestions(su)
langp_T *lp; langp_T *lp;
suggest_T *stp; suggest_T *stp;
char_u sal_badword[MAXWLEN]; char_u sal_badword[MAXWLEN];
char_u sal_badword2[MAXWLEN];
int i; int i;
int lpi; 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) if (lp->lp_slang->sl_sal.ga_len > 0)
{ {
/* soundfold the bad word */ /* 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); slang = stp->st_slang;
if (!stp->st_had_bonus) if (slang->sl_sal.ga_len > 0)
{ {
stp->st_altscore = stp_sal_score(stp, su, if (slang == slang_first)
lp->lp_slang, sal_badword); 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) if (stp->st_altscore == SCORE_MAXMAX)
stp->st_altscore = SCORE_BIG; stp->st_altscore = SCORE_BIG;
stp->st_score = RESCORE(stp->st_score, stp->st_altscore); 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) if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
/* Use the sound-folding of the first language that supports it. */ /* 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) if (lp->lp_slang->sl_sal.ga_len > 0)
{ {
/* soundfold the word */ /* soundfold the word */