summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-09-29 18:26:07 +0000
committerBram Moolenaar <Bram@vim.org>2005-09-29 18:26:07 +0000
commit482aaeb058a3c05235148d22f6c511416da009fb (patch)
treeb9c63e97ec2826bfeea041afe176a04763dbcfa8 /src
parent4463f296d0744915fa25dbd893821833043f9a25 (diff)
updated for version 7.0151v7.0151
Diffstat (limited to 'src')
-rw-r--r--src/eval.c26
-rw-r--r--src/ex_cmds2.c8
-rw-r--r--src/ex_docmd.c12
-rw-r--r--src/ex_getln.c10
-rw-r--r--src/globals.h5
-rw-r--r--src/main.c6
-rw-r--r--src/normal.c3
-rw-r--r--src/option.c7
-rw-r--r--src/proto/spell.pro4
-rw-r--r--src/screen.c54
-rw-r--r--src/search.c23
-rw-r--r--src/spell.c308
-rw-r--r--src/testdir/test58.ok8
-rw-r--r--src/testdir/test59.ok8
-rw-r--r--src/ui.c11
-rw-r--r--src/version.h4
-rw-r--r--src/vim.h4
17 files changed, 320 insertions, 181 deletions
diff --git a/src/eval.c b/src/eval.c
index 206bbfbfaf..e5212111ed 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -5571,8 +5571,8 @@ list_append_string(l, str, len)
list_append(l, li);
li->li_tv.v_type = VAR_STRING;
li->li_tv.v_lock = 0;
- if ((li->li_tv.vval.v_string = len >= 0 ? vim_strnsave(str, len)
- : vim_strsave(str)) == NULL)
+ if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
+ : vim_strsave(str))) == NULL)
return FAIL;
return OK;
}
@@ -8271,7 +8271,7 @@ f_diff_hlID(argvars, rettv)
static int fnum = 0;
static int change_start = 0;
static int change_end = 0;
- static enum hlf_value hlID = 0;
+ static hlf_T hlID = 0;
int filler_lines;
int col;
@@ -8298,7 +8298,7 @@ f_diff_hlID(argvars, rettv)
hlID = HLF_ADD; /* added line */
}
else
- hlID = (enum hlf_value)0;
+ hlID = (hlf_T)0;
prev_lnum = lnum;
changedtick = curbuf->b_changedtick;
fnum = curbuf->b_fnum;
@@ -8312,7 +8312,7 @@ f_diff_hlID(argvars, rettv)
else
hlID = HLF_CHD; /* changed line */
}
- rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
+ rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID;
#endif
}
@@ -13902,8 +13902,8 @@ f_spellbadword(argvars, rettv)
{
char_u *word = (char_u *)"";
#ifdef FEAT_SYN_HL
- int len;
- int attr = 0;
+ int len = 0;
+ hlf_T attr = HLF_COUNT;
list_T *l;
#endif
@@ -13933,7 +13933,7 @@ f_spellbadword(argvars, rettv)
while (*str != NUL)
{
len = spell_check(curwin, str, &attr, &capcol);
- if (attr != 0)
+ if (attr != HLF_COUNT)
{
word = str;
break;
@@ -13946,11 +13946,11 @@ f_spellbadword(argvars, rettv)
list_append_string(l, word, len);
list_append_string(l, (char_u *)(
- attr == highlight_attr[HLF_SPB] ? "bad" :
- attr == highlight_attr[HLF_SPR] ? "rare" :
- attr == highlight_attr[HLF_SPL] ? "local" :
- attr == highlight_attr[HLF_SPC] ? "caps" :
- ""), -1);
+ attr == HLF_SPB ? "bad" :
+ attr == HLF_SPR ? "rare" :
+ attr == HLF_SPL ? "local" :
+ attr == HLF_SPC ? "caps" :
+ ""), -1);
}
/*
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index c635bfc4ce..449b66c374 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -3901,7 +3901,15 @@ ex_language(eap)
* FEAT_GETTEXT isn't defined, so that shell commands use this
* value. */
if (what == LC_ALL)
+ {
vim_setenv((char_u *)"LANG", name);
+# ifdef WIN32
+ /* Apparently MS-Windows printf() may cause a crash when
+ * we give it 8-bit text while it's expecting text in the
+ * current locale. This call avoids that. */
+ setlocale(LC_CTYPE, "C");
+# endif
+ }
if (what != LC_CTYPE)
{
char_u *mname;
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index f88fbf815b..7242381795 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -5900,7 +5900,7 @@ parse_compl_arg(value, vallen, complp, argt, compl_arg)
for (i = 0; command_complete[i].expand != 0; ++i)
{
- if (STRLEN(command_complete[i].name) == valend
+ if ((int)STRLEN(command_complete[i].name) == valend
&& STRNCMP(value, command_complete[i].name, valend) == 0)
{
*complp = command_complete[i].expand;
@@ -9179,15 +9179,21 @@ makeopens(fd, dirnow)
*/
if (ssop_flags & SSOP_SESDIR)
{
- if (put_line(fd, "exe \"cd \" . expand(\"<sfile>:p:h\")") == FAIL)
+ if (put_line(fd, "exe \"cd \" . escape(expand(\"<sfile>:p:h\"), ' ')")
+ == FAIL)
return FAIL;
}
else if (ssop_flags & SSOP_CURDIR)
{
sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow);
if (sname == NULL
- || fprintf(fd, "cd %s", sname) < 0 || put_eol(fd) == FAIL)
+ || fputs("cd ", fd) < 0
+ || ses_put_fname(fd, sname, &ssop_flags) == FAIL
+ || put_eol(fd) == FAIL)
+ {
+ vim_free(sname);
return FAIL;
+ }
vim_free(sname);
}
diff --git a/src/ex_getln.c b/src/ex_getln.c
index a3fac10ac7..2748915be4 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1700,7 +1700,7 @@ cmdline_changed:
#ifdef FEAT_RIGHTLEFT
if (cmdmsg_rl
# ifdef FEAT_ARABIC
- || p_arshape
+ || (p_arshape && !p_tbidi && enc_utf8)
# endif
)
/* Always redraw the whole command line to fix shaping and
@@ -1873,7 +1873,11 @@ set_cmdspos_cursor()
set_cmdspos();
if (KeyTyped)
+ {
m = Columns * Rows;
+ if (m < 0) /* overflow, Columns or Rows at weird value */
+ m = MAXCOL;
+ }
else
m = MAXCOL;
for (i = 0; i < ccline.cmdlen && i < ccline.cmdpos; ++i)
@@ -2641,7 +2645,11 @@ put_on_cmdline(str, len, redraw)
#endif
{
if (KeyTyped)
+ {
m = Columns * Rows;
+ if (m < 0) /* overflow, Columns or Rows at weird value */
+ m = MAXCOL;
+ }
else
m = MAXCOL;
for (i = 0; i < len; ++i)
diff --git a/src/globals.h b/src/globals.h
index 4b916efd8a..3731f06731 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -35,6 +35,9 @@ EXTERN long Columns INIT(= 80); /* nr of columns in the screen */
*
* "LineOffset[n]" is the offset from ScreenLines[] for the start of line 'n'.
* The same value is used for ScreenLinesUC[] and ScreenAttrs[].
+ *
+ * Note: before the screen is initialized and when out of memory these can be
+ * NULL.
*/
EXTERN schar_T *ScreenLines INIT(= NULL);
EXTERN sattr_T *ScreenAttrs INIT(= NULL);
@@ -818,7 +821,7 @@ EXTERN int ins_at_eol INIT(= FALSE); /* put cursor after eol when
EXTERN char_u *edit_submode INIT(= NULL); /* msg for CTRL-X submode */
EXTERN char_u *edit_submode_pre INIT(= NULL); /* prepended to edit_submode */
EXTERN char_u *edit_submode_extra INIT(= NULL);/* appended to edit_submode */
-EXTERN enum hlf_value edit_submode_highl; /* highl. method for extra info */
+EXTERN hlf_T edit_submode_highl; /* highl. method for extra info */
EXTERN int ctrl_x_mode INIT(= 0); /* Which Ctrl-X mode are we in? */
#endif
diff --git a/src/main.c b/src/main.c
index 898205e280..f7e2b1bb92 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1236,6 +1236,12 @@ get_number_arg(p, idx, def)
init_locale()
{
setlocale(LC_ALL, "");
+# ifdef WIN32
+ /* Apparently MS-Windows printf() may cause a crash when we give it 8-bit
+ * text while it's expecting text in the current locale. This call avoids
+ * that. */
+ setlocale(LC_CTYPE, "C");
+# endif
# ifdef FEAT_GETTEXT
{
diff --git a/src/normal.c b/src/normal.c
index 84de270ea4..1e645e4476 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -4750,10 +4750,9 @@ dozet:
if (ptr == NULL)
{
pos_T pos = curwin->w_cursor;
- int attr;
/* Find bad word under the cursor. */
- len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
+ len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL);
if (len != 0 && curwin->w_cursor.col <= pos.col)
ptr = ml_get_pos(&curwin->w_cursor);
curwin->w_cursor = pos;
diff --git a/src/option.c b/src/option.c
index d547edc1e5..b3c80d6a4f 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3277,6 +3277,7 @@ set_init_2()
* "linux" Linux console
* "screen.linux" Linux console with screen
* "cygwin" Cygwin shell
+ * "putty" Putty program
* We also check the COLORFGBG environment variable, which is set by
* rxvt and derivatives. This variable contains either two or three
* values separated by semicolons; we want the last value in either
@@ -3287,6 +3288,7 @@ set_init_2()
&& (STRCMP(T_NAME, "linux") == 0
|| STRCMP(T_NAME, "screen.linux") == 0
|| STRCMP(T_NAME, "cygwin") == 0
+ || STRCMP(T_NAME, "putty") == 0
|| ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL
&& (p = vim_strrchr(p, ';')) != NULL
&& ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
@@ -7343,6 +7345,11 @@ set_num_option(opt_idx, varp, value, errbuf, errbuflen, opt_flags)
}
Columns = MIN_COLUMNS;
}
+ /* Limit the values to avoid an overflow in Rows * Columns. */
+ if (Columns > 10000)
+ Columns = 10000;
+ if (Rows > 1000)
+ Rows = 1000;
#ifdef DJGPP
/* avoid a crash by checking for a too large value of 'columns' */
diff --git a/src/proto/spell.pro b/src/proto/spell.pro
index 2adc137e96..facbfbc76f 100644
--- a/src/proto/spell.pro
+++ b/src/proto/spell.pro
@@ -1,6 +1,6 @@
/* spell.c */
-int spell_check __ARGS((win_T *wp, char_u *ptr, int *attrp, int *capcol));
-int spell_move_to __ARGS((win_T *wp, int dir, int allwords, int curline, int *attrp));
+int spell_check __ARGS((win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol));
+int spell_move_to __ARGS((win_T *wp, int dir, int allwords, int curline, hlf_T *attrp));
void spell_cat_line __ARGS((char_u *buf, char_u *line, int maxlen));
char_u *did_set_spelllang __ARGS((buf_T *buf));
void spell_free_all __ARGS((void));
diff --git a/src/screen.c b/src/screen.c
index f497f370de..fa13904249 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -128,7 +128,7 @@ static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
static schar_T *current_ScreenLine;
static void win_update __ARGS((win_T *wp));
-static void win_draw_end __ARGS((win_T *wp, int c1, int c2, int row, int endrow, enum hlf_value hl));
+static void win_draw_end __ARGS((win_T *wp, int c1, int c2, int row, int endrow, hlf_T hl));
#ifdef FEAT_FOLDING
static void fold_line __ARGS((win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row));
static void fill_foldcolumn __ARGS((char_u *p, win_T *wp, int closed, linenr_T lnum));
@@ -1904,7 +1904,7 @@ win_draw_end(wp, c1, c2, row, endrow, hl)
int c2;
int row;
int endrow;
- enum hlf_value hl;
+ hlf_T hl;
{
#if defined(FEAT_FOLDING) || defined(FEAT_SIGNS) || defined(FEAT_CMDWIN)
int n = 0;
@@ -2531,7 +2531,7 @@ win_line(wp, lnum, startrow, endrow)
#ifdef FEAT_DIFF
int filler_lines; /* nr of filler lines to be drawn */
int filler_todo; /* nr of filler lines still to do + 1 */
- enum hlf_value diff_hlf = (enum hlf_value)0; /* type of diff highlighting */
+ hlf_T diff_hlf = (hlf_T)0; /* type of diff highlighting */
int change_start = MAXCOL; /* first col of changed area */
int change_end = -1; /* last col of changed area */
#endif
@@ -2926,22 +2926,28 @@ win_line(wp, lnum, startrow, endrow)
if (has_spell)
{
int len;
+ hlf_T spell_hlf = HLF_COUNT;
pos = wp->w_cursor;
wp->w_cursor.lnum = lnum;
wp->w_cursor.col = ptr - line;
- len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_attr);
+ len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf);
if (len == 0 || (int)wp->w_cursor.col > ptr - line)
{
/* no bad word found at line start, don't check until end of a
* word */
- spell_attr = 0;
+ spell_hlf = HLF_COUNT;
word_end = spell_to_word_end(ptr, wp->w_buffer) - line + 1;
}
else
+ {
/* bad word found, use attributes until end of word */
word_end = wp->w_cursor.col + len + 1;
+ /* Turn index into actual attributes. */
+ if (spell_hlf != HLF_COUNT)
+ spell_attr = highlight_attr[spell_hlf];
+ }
wp->w_cursor = pos;
/* Need to restart syntax highlighting for this line. */
@@ -3353,7 +3359,7 @@ win_line(wp, lnum, startrow, endrow)
char_attr = search_attr;
#ifdef FEAT_DIFF
- if (diff_hlf != (enum hlf_value)0 && n_extra == 0)
+ if (diff_hlf != (hlf_T)0 && n_extra == 0)
{
if (diff_hlf == HLF_CHD && ptr - line >= change_start)
diff_hlf = HLF_TXD; /* changed text */
@@ -3719,6 +3725,7 @@ win_line(wp, lnum, startrow, endrow)
{
char_u *prev_ptr, *p;
int len;
+ hlf_T spell_hlf = HLF_COUNT;
# ifdef FEAT_MBYTE
if (has_mbyte)
{
@@ -3736,23 +3743,23 @@ win_line(wp, lnum, startrow, endrow)
else
p = prev_ptr;
cap_col -= (prev_ptr - line);
- len = spell_check(wp, p, &spell_attr, &cap_col);
+ len = spell_check(wp, p, &spell_hlf, &cap_col);
word_end = v + len;
/* In Insert mode only highlight a word that
* doesn't touch the cursor. */
- if (spell_attr != 0
+ if (spell_hlf != HLF_COUNT
&& (State & INSERT) != 0
&& wp->w_cursor.lnum == lnum
&& wp->w_cursor.col >=
(colnr_T)(prev_ptr - line)
&& wp->w_cursor.col < (colnr_T)word_end)
{
- spell_attr = 0;
+ spell_hlf = HLF_COUNT;
spell_redraw_lnum = lnum;
}
- if (spell_attr == 0 && p != prev_ptr
+ if (spell_hlf == HLF_COUNT && p != prev_ptr
&& (p - nextline) + len > nextline_idx)
{
/* Remember that the good word continues at the
@@ -3761,6 +3768,10 @@ win_line(wp, lnum, startrow, endrow)
checked_col = (p - nextline) + len - nextline_idx;
}
+ /* Turn index into actual attributes. */
+ if (spell_hlf != HLF_COUNT)
+ spell_attr = highlight_attr[spell_hlf];
+
if (cap_col > 0)
{
if (p != prev_ptr
@@ -3889,7 +3900,7 @@ win_line(wp, lnum, startrow, endrow)
* "$". */
if (
# ifdef FEAT_DIFF
- diff_hlf == (enum hlf_value)0
+ diff_hlf == (hlf_T)0
# ifdef LINE_ATTR
&&
# endif
@@ -3976,7 +3987,7 @@ win_line(wp, lnum, startrow, endrow)
#if defined(FEAT_DIFF) || defined(LINE_ATTR)
else if ((
# ifdef FEAT_DIFF
- diff_hlf != (enum hlf_value)0
+ diff_hlf != (hlf_T)0
# ifdef LINE_ATTR
||
# endif
@@ -6398,6 +6409,10 @@ screen_draw_rectangle(row, col, height, width, invert)
int r, c;
int off;
+ /* Can't use ScreenLines unless initialized */
+ if (ScreenLines == NULL)
+ return;
+
if (invert)
screen_char_attr = HL_INVERSE;
for (r = row; r < row + height; ++r)
@@ -6696,6 +6711,7 @@ screenalloc(clear)
unsigned *new_LineOffset;
char_u *new_LineWraps;
static int entered = FALSE; /* avoid recursiveness */
+ static int did_outofmem_msg = FALSE; /* did outofmem message */
/*
* Allocation of the screen buffers is done only when the size changes and
@@ -6790,7 +6806,15 @@ screenalloc(clear)
|| new_LineWraps == NULL
|| outofmem)
{
- do_outofmem_msg((long_u)((Rows + 1) * Columns)); /* guess the size */
+ if (ScreenLines != NULL || !did_outofmem_msg)
+ {
+ /* guess the size */
+ do_outofmem_msg((long_u)((Rows + 1) * Columns));
+
+ /* Remember we did this to avoid getting outofmem messages over
+ * and over again. */
+ did_outofmem_msg = TRUE;
+ }
vim_free(new_ScreenLines);
new_ScreenLines = NULL;
#ifdef FEAT_MBYTE
@@ -6812,6 +6836,8 @@ screenalloc(clear)
}
else
{
+ did_outofmem_msg = FALSE;
+
for (new_row = 0; new_row < Rows; ++new_row)
{
new_LineOffset[new_row] = new_row * Columns;
@@ -6844,7 +6870,7 @@ screenalloc(clear)
(void)vim_memset(new_ScreenAttrs + new_row * Columns,
0, (size_t)Columns * sizeof(sattr_T));
old_row = new_row + (screen_Rows - Rows);
- if (old_row >= 0)
+ if (old_row >= 0 && ScreenLines != NULL)
{
if (screen_Columns < Columns)
len = screen_Columns;
diff --git a/src/search.c b/src/search.c
index 2ed15df2b2..f4e8f611e3 100644
--- a/src/search.c
+++ b/src/search.c
@@ -4410,6 +4410,7 @@ find_pattern_in_path(ptr, dir, len, whole, skip_comments,
int i;
char_u *already = NULL;
char_u *startp = NULL;
+ char_u *inc_opt = NULL;
#ifdef RISCOS
int previous_munging = __riscosify_control;
#endif
@@ -4449,10 +4450,10 @@ find_pattern_in_path(ptr, dir, len, whole, skip_comments,
if (regmatch.regprog == NULL)
goto fpip_end;
}
- if (*curbuf->b_p_inc != NUL || *p_inc != NUL)
+ inc_opt = (*curbuf->b_p_inc == NUL) ? p_inc : curbuf->b_p_inc;
+ if (*inc_opt != NUL)
{
- incl_regmatch.regprog = vim_regcomp(*curbuf->b_p_inc == NUL
- ? p_inc : curbuf->b_p_inc, p_magic ? RE_MAGIC : 0);
+ incl_regmatch.regprog = vim_regcomp(inc_opt, p_magic ? RE_MAGIC : 0);
if (incl_regmatch.regprog == NULL)
goto fpip_end;
incl_regmatch.rm_ic = FALSE; /* don't ignore case in incl. pat. */
@@ -4484,10 +4485,18 @@ find_pattern_in_path(ptr, dir, len, whole, skip_comments,
if (incl_regmatch.regprog != NULL
&& vim_regexec(&incl_regmatch, line, (colnr_T)0))
{
- new_fname = file_name_in_line(incl_regmatch.endp[0],
- 0, FNAME_EXP|FNAME_INCL|FNAME_REL, 1L,
- curr_fname == curbuf->b_fname
- ? curbuf->b_ffname : curr_fname);
+ char_u *p_fname = (curr_fname == curbuf->b_fname)
+ ? curbuf->b_ffname : curr_fname;
+
+ if (inc_opt != NULL && strstr((char *)inc_opt, "\\zs") != NULL)
+ /* Use text from '\zs' to '\ze' (or end) of 'include'. */
+ new_fname = find_file_name_in_path(incl_regmatch.startp[0],
+ incl_regmatch.endp[0] - incl_regmatch.startp[0],
+ FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname);
+ else
+ /* Use text after match with 'include'. */
+ new_fname = file_name_in_line(incl_regmatch.endp[0], 0,
+ FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname);
already_searched = FALSE;
if (new_fname != NULL)
{
diff --git a/src/spell.c b/src/spell.c
index 53447afb9b..6076dfc86c 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -477,6 +477,8 @@ typedef struct suginfo_S
int su_badflags; /* caps flags for bad word */
char_u su_badword[MAXWLEN]; /* bad word truncated at su_badlen */
char_u su_fbadword[MAXWLEN]; /* su_badword case-folded */
+ char_u su_sal_badword[MAXWLEN]; /* su_badword soundfolded */
+ slang_T *su_slang_first; /* slang_T used for su_sal_badword */
hashtab_T su_banned; /* table with banned words */
slang_T *su_sallang; /* default language for sound folding */
} suginfo_T;
@@ -749,6 +751,7 @@ 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));
static void rescore_suggestions __ARGS((suginfo_T *su));
+static void rescore_one __ARGS((suginfo_T *su, suggest_T *stp));
static int cleanup_suggestions __ARGS((garray_T *gap, int maxscore, int keep));
static void spell_soundfold __ARGS((slang_T *slang, char_u *inword, int folded, char_u *res));
static void spell_soundfold_sofo __ARGS((slang_T *slang, char_u *inword, char_u *res));
@@ -815,8 +818,8 @@ static char *msg_compressing = N_("Compressing word tree...");
/*
* Main spell-checking function.
* "ptr" points to a character that could be the start of a word.
- * "*attrp" is set to the attributes for a badly spelled word. For a non-word
- * or when it's OK it remains unchanged.
+ * "*attrp" is set to the highlight index for a badly spelled word. For a
+ * non-word or when it's OK it remains unchanged.
* This must only be called when 'spelllang' is not empty.
*
* "capcol" is used to check for a Capitalised word after the end of a
@@ -831,7 +834,7 @@ static char *msg_compressing = N_("Compressing word tree...");
spell_check(wp, ptr, attrp, capcol)
win_T *wp; /* current window */
char_u *ptr;
- int *attrp;
+ hlf_T *attrp;
int *capcol; /* column to check for Capital */
{
matchinf_T mi; /* Most things are put in "mi" so that it can
@@ -1008,17 +1011,17 @@ spell_check(wp, ptr, attrp, capcol)
}
if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
- *attrp = highlight_attr[HLF_SPB];
+ *attrp = HLF_SPB;
else if (mi.mi_result == SP_RARE)
- *attrp = highlight_attr[HLF_SPR];
+ *attrp = HLF_SPR;
else
- *attrp = highlight_attr[HLF_SPL];
+ *attrp = HLF_SPL;
}
if (wrongcaplen > 0 && (mi.mi_result == SP_OK || mi.mi_result == SP_RARE))
{
/* Report SpellCap only when the word isn't badly spelled. */
- *attrp = highlight_attr[HLF_SPC];
+ *attrp = HLF_SPC;
return wrongcaplen;
}
@@ -1822,7 +1825,8 @@ spell_move_to(wp, dir, allwords, curline, attrp)
int dir; /* FORWARD or BACKWARD */
int allwords; /* TRUE for "[s"/"]s", FALSE for "[S"/"]S" */
int curline;
- int *attrp; /* return: attributes of bad word or NULL */
+ hlf_T *attrp; /* return: attributes of bad word or NULL
+ (only when "dir" is FORWARD) */
{
linenr_T lnum;
pos_T found_pos;
@@ -1830,7 +1834,7 @@ spell_move_to(wp, dir, allwords, curline, attrp)
char_u *line;
char_u *p;
char_u *endp;
- int attr;
+ hlf_T attr;
int len;
int has_syntax = syntax_present(wp->w_buffer);
int col;
@@ -1900,13 +1904,13 @@ spell_move_to(wp, dir, allwords, curline, attrp)
break;
/* start of word */
- attr = 0;
+ attr = HLF_COUNT;
len = spell_check(wp, p, &attr, &capcol);
- if (attr != 0)
+ if (attr != HLF_COUNT)
{
/* We found a bad word. Check the attribute. */
- if (allwords || attr == highlight_attr[HLF_SPB])
+ if (allwords || attr == HLF_SPB)
{
found_one = TRUE;
@@ -2017,7 +2021,7 @@ spell_move_to(wp, dir, allwords, curline, attrp)
/* Skip the characters at the start of the next line that were
* included in a match crossing line boundaries. */
- if (attr == 0)
+ if (attr == HLF_COUNT)
skip = p - endp;
else
skip = 0;
@@ -5098,7 +5102,9 @@ spell_read_aff(spin, fname)
ga_append(&spin->si_map, '/');
}
}
- else if (STRCMP(items[0], "SAL") == 0 && itemcnt == 3)
+ /* Accept "SAL from to" and "SAL from to # comment". */
+ else if (STRCMP(items[0], "SAL") == 0
+ && (itemcnt == 3 || (itemcnt > 3 && items[3][0] == '#')))
{
if (do_sal)
{
@@ -8769,7 +8775,7 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
int banbadword; /* don't include badword in suggestions */
int need_cap; /* word should start with capital */
{
- int attr = 0;
+ hlf_T attr = HLF_COUNT;
char_u buf[MAXPATHL];
char_u *p;
int do_combine = FALSE;
@@ -8821,11 +8827,17 @@ spell_find_suggest(badptr, su, maxcount, banbadword, need_cap)
}
}
+ /* Soundfold the bad word with the default sound folding, so that we don't
+ * have to do this many times. */
+ if (su->su_sallang != NULL)
+ spell_soundfold(su->su_sallang, su->su_fbadword, TRUE,
+ su->su_sal_badword);
+
/* 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. */
c = PTR2CHAR(su->su_badptr);
- if (!SPELL_ISUPPER(c) && attr == 0)
+ if (!SPELL_ISUPPER(c) && attr == HLF_COUNT)
{
make_case_word(su->su_badword, buf, WF_ONECAP);
add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE,
@@ -9173,8 +9185,11 @@ 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, su->su_sallang);
+
+ /* Give a soundalike score of 0, compute the score as if deleting one
+ * character. */
+ add_suggestion(su, &su->su_ga, word, su->su_badlen,
+ RESCORE(SCORE_REP, 0), 0, TRUE, su->su_sallang);
}
}
@@ -9226,6 +9241,8 @@ suggest_try_change(su)
slang_T *slang;
int fword_ends;
int lpi;
+ int maysplit;
+ int goodword_ends;
/* We make a copy of the case-folded bad word, so that we can modify it
* to find matches (esp. REP items). Append some more text, changing
@@ -9401,10 +9418,13 @@ suggest_try_change(su)
}
}
- /* Check NEEDCOMPOUND: can't use word without compounding. */
+ /* Check NEEDCOMPOUND: can't use word without compounding. Do
+ * try appending another compound word below. */
if (sp->ts_complen == sp->ts_compsplit && fword_ends
&& (flags & WF_NEEDCOMP))
- break;
+ goodword_ends = FALSE;
+ else
+ goodword_ends = TRUE;
if (sp->ts_complen > sp->ts_compsplit)
{
@@ -9508,9 +9528,15 @@ suggest_try_change(su)
add_banned(su, preword + sp->ts_prewordlen);
break;
}
- if (was_banned(su, preword + sp->ts_prewordlen)
+ if ((sp->ts_complen == sp->ts_compsplit
+ && was_banned(su, preword + sp->ts_prewordlen))
|| was_banned(su, preword))
- break;
+ {
+ if (slang->sl_compprog == NULL)
+ break;
+ /* the word so far was banned but we may try compounding */
+ goodword_ends = FALSE;
+ }
newscore = 0;
if ((flags & WF_REGION)
@@ -9523,7 +9549,9 @@ suggest_try_change(su)
captype(preword + sp->ts_prewordlen, NULL)))
newscore += SCORE_ICASE;
- if (fword_ends && sp->ts_fidx >= sp->ts_fidxtry)
+ maysplit = TRUE;
+ if (fword_ends && goodword_ends
+ && sp->ts_fidx >= sp->ts_fidxtry)
{
/* The badword also ends: add suggestions. Give a penalty
* when changing non-word char to word char, e.g., "thes,"
@@ -9549,11 +9577,20 @@ suggest_try_change(su)
}
add_suggestion(su, &su->su_ga, preword,
- sp->ts_fidx - repextra,
- sp->ts_score + newscore, 0, FALSE,
- lp->lp_sallang);
+ sp->ts_fidx - repextra,
+ sp->ts_score + newscore, 0, FALSE,
+ lp->lp_sallang);
+
+ /* When the bad word doesn't end yet, try changing the
+ * next word. E.g., find suggestions for "the the" where
+ * the second "the" is different. It's done like a split.
+ */
+ if (sp->ts_fidx - repextra >= su->su_badlen)
+ maysplit = FALSE;
}
- else if ((sp->ts_fidx >= sp->ts_fidxtry || fword_ends)
+
+ if (maysplit
+ && (sp->ts_fidx >= sp->ts_fidxtry || fword_ends)
#ifdef FEAT_MBYTE
/* Don't split halfway a character. */
&& (!has_mbyte || sp->ts_tcharlen == 0)
@@ -9574,7 +9611,7 @@ suggest_try_change(su)
* the following word is valid.
*/
try_compound = FALSE;
- if (!fword_ends
+ if ((!fword_ends || !goodword_ends)
&& slang->sl_compprog != NULL
&& ((unsigned)flags >> 24) != 0
&& sp->ts_twordlen - sp->ts_splitoff
@@ -9618,7 +9655,7 @@ suggest_try_change(su)
else
sp->ts_flags &= ~TSF_DIDSPLIT;
- if (!try_compound && !fword_ends)
+ if (!try_compound && (!fword_ends || !goodword_ends))
{
/* If we're going to split need to check that the
* words so far are valid for compounding. If there
@@ -9656,10 +9693,12 @@ suggest_try_change(su)
/* If the badword has a non-word character at this
* position skip it. That means replacing the
* non-word character with a space. Always skip a
- * character when the word ends. */
- if ((!try_compound
- && !spell_iswordp_nmw(fword + sp->ts_fidx))
+ * character when the word ends. But only when the
+ * good word can end. */
+ if (((!try_compound
+ && !spell_iswordp_nmw(fword + sp->ts_fidx))
|| fword_ends)
+ && goodword_ends)
{
int l;
@@ -10726,12 +10765,17 @@ stp_sal_score(stp, su, slang, badsound)
char_u *badsound; /* sound-folded badword */
{
char_u *p;
+ char_u *pbad;
+ char_u *pgood;
char_u badsound2[MAXWLEN];
char_u fword[MAXWLEN];
char_u goodsound[MAXWLEN];
+ char_u goodword[MAXWLEN];
+ int lendiff;
- if (stp->st_orglen <= su->su_badlen)
- p = badsound;
+ lendiff = (int)(su->su_badlen - stp->st_orglen);
+ if (lendiff >= 0)
+ pbad = badsound;
else
{
/* soundfold the bad word with more characters following */
@@ -10747,13 +10791,24 @@ stp_sal_score(stp, su, slang, badsound)
mch_memmove(p, p + 1, STRLEN(p));
spell_soundfold(slang, fword, TRUE, badsound2);
- p = badsound2;
+ pbad = badsound2;
}
+ if (lendiff > 0)
+ {
+ /* Add part of the bad word to the good word, so that we soundfold
+ * what replaces the bad word. */
+ STRCPY(goodword, stp->st_word);
+ STRNCAT(goodword, su->su_badptr + su->su_badlen - lendiff, lendiff);
+ pgood = goodword;
+ }
+ else
+ pgood = stp->st_word;
+
/* Sound-fold the word and compute the score for the difference. */
- spell_soundfold(slang, stp->st_word, FALSE, goodsound);
+ spell_soundfold(slang, pgood, FALSE, goodsound);
- return soundalike_score(goodsound, p);
+ return soundalike_score(goodsound, pbad);
}
/*
@@ -11081,23 +11136,24 @@ similar_chars(slang, c1, c2)
* with spell_edit_score().
*/
static void
-add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang)
+add_suggestion(su, gap, goodword, badlenarg, score, altscore, had_bonus, slang)
suginfo_T *su;
garray_T *gap;
char_u *goodword;
- int badlen; /* length of bad word used */
+ int badlenarg; /* len of bad word replaced with "goodword" */
int score;
int altscore;
int had_bonus; /* value for st_had_bonus */
slang_T *slang; /* language for sound folding */
{
- int goodlen = STRLEN(goodword);
+ int goodlen = STRLEN(goodword); /* len of goodword changed */
+ int badlen = badlenarg; /* len of bad word changed */
suggest_T *stp;
+ suggest_T new_sug;
int i;
- char_u *p = NULL;
- int c = 0;
- int attr = 0;
+ hlf_T attr = HLF_COUNT;
char_u longword[MAXWLEN + 1];
+ char_u *pgood, *pbad;
/* Check that the word really is valid. Esp. for banned words and for
* split words, such as "the the". Need to append what follows to check
@@ -11105,36 +11161,34 @@ add_suggestion(su, gap, goodword, badlen, score, altscore, had_bonus, slang)
STRCPY(longword, goodword);
vim_strncpy(longword + goodlen, su->su_badptr + badlen, MAXWLEN - goodlen);
(void)spell_check(curwin, longword, &attr, NULL);
- if (attr != 0)
+ if (attr != HLF_COUNT)
return;
- /* If past "su_badlen" and the rest is identical stop at "su_badlen".
- * Remove the common part from "goodword". */
- i = badlen - su->su_badlen;
- if (i > 0)
+ /* Minimize "badlen" for consistency. Avoids that changing "the the" to
+ * "thee the" is added next to changing the first "the" the "thee". */
+ pgood = goodword + STRLEN(goodword);
+ pbad = su->su_badptr + badlen;
+ while (pgood > goodword && pbad > su->su_badptr)
{
- /* This assumes there was no case folding or it didn't change the
- * length... */
- p = goodword + goodlen - i;
- if (p > goodword && STRNICMP(su->su_badptr + su->su_badlen, p, i) == 0)
+ mb_ptr_back(goodword, pgood);
+ mb_ptr_back(su->su_badptr, pbad);
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
{
- badlen = su->su_badlen;
- c = *p;
- *p = NUL;