summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-08-29 22:25:38 +0000
committerBram Moolenaar <Bram@vim.org>2005-08-29 22:25:38 +0000
commitac6e65f88da446bc764ff13a23d854fd72ffedcf (patch)
tree4c4cd8700dcb53ac3a236a056320e2caf062a23d /src
parent81f1ecbc4dc885a4757e5cc64002f4b22f397f18 (diff)
downloadvim-git-ac6e65f88da446bc764ff13a23d854fd72ffedcf.tar.gz
updated for version 7.0138v7.0138
Diffstat (limited to 'src')
-rw-r--r--src/eval.c3
-rw-r--r--src/feature.h3
-rw-r--r--src/fileio.c4
-rw-r--r--src/if_xcmdsrv.c16
-rw-r--r--src/mbyte.c28
-rw-r--r--src/misc2.c5
-rw-r--r--src/option.c22
-rw-r--r--src/proto/mbyte.pro1
-rw-r--r--src/spell.c306
-rw-r--r--src/testdir/test58.in247
-rw-r--r--src/testdir/test58.ok89
-rw-r--r--src/testdir/test59.in225
-rw-r--r--src/testdir/test59.ok122
-rw-r--r--src/version.h4
14 files changed, 732 insertions, 343 deletions
diff --git a/src/eval.c b/src/eval.c
index 01900713d..f14a69b38 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -10043,6 +10043,9 @@ f_has(argvars, rettv)
#ifdef FEAT_CSCOPE
"cscope",
#endif
+#ifdef CURSOR_SHAPE
+ "cursorshape",
+#endif
#ifdef DEBUG
"debug",
#endif
diff --git a/src/feature.h b/src/feature.h
index f007df69a..0ab57e93a 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -1081,7 +1081,8 @@
/* GUI and some consoles can change the shape of the cursor. The code is also
* needed for the 'mouseshape' option. */
-#if defined(FEAT_GUI) || defined(MCH_CURSOR_SHAPE) || defined(FEAT_MOUSESHAPE)
+#if defined(FEAT_GUI) || defined(MCH_CURSOR_SHAPE) || defined(FEAT_MOUSESHAPE) \
+ || (defined(UNIX) && defined(FEAT_NORMAL))
# define CURSOR_SHAPE
#endif
diff --git a/src/fileio.c b/src/fileio.c
index bb25ce7da..a34048cef 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -6865,6 +6865,10 @@ show_autocmd(ap, event)
if (got_int)
return;
msg_outtrans(ac->cmd);
+#ifdef FEAT_EVAL
+ if (p_verbose > 0)
+ last_set_msg(ac->scriptID);
+#endif
if (got_int)
return;
if (ac->next != NULL)
diff --git a/src/if_xcmdsrv.c b/src/if_xcmdsrv.c
index 4a091bd27..63faf0c18 100644
--- a/src/if_xcmdsrv.c
+++ b/src/if_xcmdsrv.c
@@ -460,10 +460,12 @@ serverSendToVim(dpy, name, cmd, result, server, asExpr, localLoop, silent)
/*
* Send the command to target interpreter by appending it to the
* comm window in the communication window.
+ * Length must be computed exactly!
*/
- length = STRLEN(name) + STRLEN(cmd) + 14;
#ifdef FEAT_MBYTE
- length += STRLEN(p_enc);
+ length = STRLEN(name) + STRLEN(p_enc) + STRLEN(cmd) + 14;
+#else
+ length = STRLEN(name) + STRLEN(cmd) + 10;
#endif
property = (char_u *)alloc((unsigned)length + 30);
@@ -480,6 +482,7 @@ serverSendToVim(dpy, name, cmd, result, server, asExpr, localLoop, silent)
serial++;
sprintf((char *)property + length, "%c-r %x %d",
0, (int_u)commWindow, serial);
+ /* Add length of what "-r %x %d" resulted in, skipping the NUL. */
length += STRLEN(property + length + 1) + 1;
res = AppendPropCarefully(dpy, w, commProperty, property, length + 1);
@@ -787,9 +790,10 @@ serverSendReply(name, str)
if (!WindowValid(dpy, win))
return -1;
- length = STRLEN(str) + 11;
#ifdef FEAT_MBYTE
- length += STRLEN(p_enc);
+ length = STRLEN(p_enc) + STRLEN(str) + 14;
+#else
+ length = STRLEN(str) + 10;
#endif
if ((property = (char_u *)alloc((unsigned)length + 30)) != NULL)
{
@@ -800,6 +804,7 @@ serverSendReply(name, str)
sprintf((char *)property, "%cn%c-n %s%c-w %x",
0, 0, str, 0, (unsigned int)commWindow);
#endif
+ /* Add length of what "%x" resulted in. */
length += STRLEN(property + length);
res = AppendPropCarefully(dpy, win, commProperty, property, length + 1);
vim_free(property);
@@ -1268,11 +1273,12 @@ serverEventProc(dpy, eventPtr)
ga_grow(&reply, 50 + STRLEN(p_enc));
sprintf(reply.ga_data, "%cr%c-E %s%c-s %s%c-r ",
0, 0, p_enc, 0, serial, 0);
+ reply.ga_len = 14 + STRLEN(serial);
#else
ga_grow(&reply, 50);
sprintf(reply.ga_data, "%cr%c-s %s%c-r ", 0, 0, serial, 0);
-#endif
reply.ga_len = 10 + STRLEN(serial);
+#endif
}
res = NULL;
if (serverName != NULL && STRICMP(name, serverName) == 0)
diff --git a/src/mbyte.c b/src/mbyte.c
index 9f2df3ad4..d446a5b41 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -2706,17 +2706,37 @@ mb_prevptr(line, p)
mb_charlen(str)
char_u *str;
{
- int count;
+ char_u *p = str;
+ int count;
- if (str == NULL)
+ if (p == NULL)
return 0;
- for (count = 0; *str != NUL; count++)
- str += (*mb_ptr2len)(str);
+ for (count = 0; *p != NUL; count++)
+ p += (*mb_ptr2len)(p);
return count;
}
+#if defined(FEAT_SYN_HL) || defined(PROTO)
+/*
+ * Like mb_charlen() but for a string with specified length.
+ */
+ int
+mb_charlen_len(str, len)
+ char_u *str;
+ int len;
+{
+ char_u *p = str;
+ int count;
+
+ for (count = 0; *p != NUL && p < str + len; count++)
+ p += (*mb_ptr2len)(p);
+
+ return count;
+}
+#endif
+
/*
* Try to un-escape a multi-byte character.
* Used for the "to" and "from" part of a mapping.
diff --git a/src/misc2.c b/src/misc2.c
index 58fb434d4..305741554 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1664,7 +1664,7 @@ vim_strbyte(string, c)
/*
* Search for last occurrence of "c" in "string".
- * return NULL if not found.
+ * Return NULL if not found.
* Does not handle multi-byte char for "c"!
*/
char_u *
@@ -3289,6 +3289,8 @@ parse_shape_opt(what)
return NULL;
}
+# if defined(MCH_CURSOR_SHAPE) || defined(FEAT_GUI) \
+ || defined(FEAT_MOUSESHAPE) || defined(PROTO)
/*
* Return the index into shape_table[] for the current mode.
* When "mouse" is TRUE, consider indexes valid for the mouse pointer.
@@ -3346,6 +3348,7 @@ get_shape_idx(mouse)
#endif
return SHAPE_IDX_N;
}
+#endif
# if defined(FEAT_MOUSESHAPE) || defined(PROTO)
static int old_mouse_shape = 0;
diff --git a/src/option.c b/src/option.c
index 9b0e6360e..98c0ad89a 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3257,6 +3257,8 @@ set_init_2()
#if !((defined(MSDOS) || defined(OS2) || defined(WIN3264)) && !defined(FEAT_GUI))
{
+ char_u *p;
+
/*
* If 'background' wasn't set by the user, try guessing the value,
* depending on the terminal name. Only need to check for terminals
@@ -3264,16 +3266,24 @@ set_init_2()
* "linux" Linux console
* "screen.linux" Linux console with screen
* "cygwin" Cygwin shell
+ * 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
+ * case. If this value is 0-6 or 8, our background is dark.
*/
idx = findoption((char_u *)"bg");
if (!(options[idx].flags & P_WAS_SET)
&& (STRCMP(T_NAME, "linux") == 0
|| STRCMP(T_NAME, "screen.linux") == 0
- || STRCMP(T_NAME, "cygwin") == 0))
+ || STRCMP(T_NAME, "cygwin") == 0
+ || ((p = mch_getenv("COLORFGBG")) != NULL
+ && (p = vim_strrchr(p, ';')) != NULL
+ && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
+ && p[2] == NUL)))
{
set_string_option_direct(NULL, idx, (char_u *)"dark", OPT_FREE);
- /* don't mark it as set, when starting the GUI it may be changed
- * again */
+ /* don't mark it as set, when starting the GUI it may be
+ * changed again */
options[idx].flags &= ~P_WAS_SET;
}
}
@@ -9777,15 +9787,15 @@ compatible_set()
static void
fill_breakat_flags()
{
- char_u *c;
+ char_u *p;
int i;
for (i = 0; i < 256; i++)
breakat_flags[i] = FALSE;
if (p_breakat != NULL)
- for (c = p_breakat; *c; c++)
- breakat_flags[*c] = TRUE;
+ for (p = p_breakat; *p; p++)
+ breakat_flags[*p] = TRUE;
}
# if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
diff --git a/src/proto/mbyte.pro b/src/proto/mbyte.pro
index 8af1cc227..9bff4d3db 100644
--- a/src/proto/mbyte.pro
+++ b/src/proto/mbyte.pro
@@ -55,6 +55,7 @@ void mb_adjust_cursor __ARGS((void));
void mb_adjustpos __ARGS((pos_T *lp));
char_u *mb_prevptr __ARGS((char_u *line, char_u *p));
int mb_charlen __ARGS((char_u *str));
+int mb_charlen_len __ARGS((char_u *str, int len));
char_u *mb_unescape __ARGS((char_u **pp));
int mb_lefthalve __ARGS((int row, int col));
int mb_fix_col __ARGS((int col, int row));
diff --git a/src/spell.c b/src/spell.c
index 26d80500f..2b04bf8b3 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -214,9 +214,9 @@
* WF_REGION <region> follows
* WF_AFX <affixID> follows
*
- * <flags2> 1 byte Only used when there are postponed prefixes.
- * Bitmask of:
+ * <flags2> 1 byte Bitmask of:
* WF_HAS_AFF >> 8 word includes affix
+ * WF_NEEDCOMP >> 8 word only valid in compound
*
* <pflags> 1 byte bitmask of:
* WFP_RARE rare prefix
@@ -273,6 +273,7 @@ typedef long idx_T;
/* for <flags2>, shifted up one byte to be used in wn_flags */
#define WF_HAS_AFF 0x0100 /* word includes affix */
+#define WF_NEEDCOMP 0x0200 /* word only valid in compound */
#define WF_CAPMASK (WF_ONECAP | WF_ALLCAP | WF_KEEPCAP | WF_FIXCAP)
@@ -754,7 +755,7 @@ static void spell_soundfold_wsal __ARGS((slang_T *slang, char_u *inword, char_u
static int soundalike_score __ARGS((char_u *goodsound, char_u *badsound));
static int spell_edit_score __ARGS((char_u *badword, char_u *goodword));
static void dump_word __ARGS((char_u *word, int round, int flags, linenr_T lnum));
-static linenr_T apply_prefixes __ARGS((slang_T *slang, char_u *word, int round, int flags, linenr_T startlnum));
+static linenr_T dump_prefixes __ARGS((slang_T *slang, char_u *word, int round, int flags, linenr_T startlnum));
/*
* Use our own character-case definitions, because the current locale may
@@ -834,6 +835,7 @@ spell_check(wp, ptr, attrp, capcol)
int nrlen = 0; /* found a number first */
int c;
int wrongcaplen = 0;
+ int lpi;
/* A word never starts at a space or a control character. Return quickly
* then, skipping over the character. */
@@ -907,9 +909,15 @@ spell_check(wp, ptr, attrp, capcol)
* We check them all, because a matching word may be longer than an
* already found matching word.
*/
- for (mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0);
- mi.mi_lp->lp_slang != NULL; ++mi.mi_lp)
+ for (lpi = 0; lpi < wp->w_buffer->b_langp.ga_len; ++lpi)
{
+ mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, lpi);
+
+ /* If reloading fails the language is still in the list but everything
+ * has been cleared. */
+ if (mi.mi_lp->lp_slang->sl_fidxs == NULL)
+ continue;
+
/* Check for a matching word in case-folded words. */
find_word(&mi, FIND_FOLDWORD);
@@ -973,23 +981,26 @@ spell_check(wp, ptr, attrp, capcol)
/* First language in 'spelllang' is NOBREAK. Find first position
* at which any word would be valid. */
mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0);
- p = mi.mi_word;
- fp = mi.mi_fword;
- for (;;)
+ if (mi.mi_lp->lp_slang->sl_fidxs != NULL)
{
- mb_ptr_adv(p);
- mb_ptr_adv(fp);
- if (p >= mi.mi_end)
- break;
- mi.mi_compoff = fp - mi.mi_fword;
- find_word(&mi, FIND_COMPOUND);
- if (mi.mi_result != SP_BAD)
+ p = mi.mi_word;
+ fp = mi.mi_fword;
+ for (;;)
{
- mi.mi_end = p;
- break;
+ mb_ptr_adv(p);
+ mb_ptr_adv(fp);
+ if (p >= mi.mi_end)
+ break;
+ mi.mi_compoff = fp - mi.mi_fword;
+ find_word(&mi, FIND_COMPOUND);
+ if (mi.mi_result != SP_BAD)
+ {
+ mi.mi_end = p;
+ break;
+ }
}
+ mi.mi_result = save_result;
}
- mi.mi_result = save_result;
}
if (mi.mi_result == SP_BAD || mi.mi_result == SP_BANNED)
@@ -1284,6 +1295,15 @@ find_word(mip, mode)
if (((unsigned)flags >> 24) == 0
|| wlen - mip->mi_compoff < slang->sl_compminlen)
continue;
+#ifdef FEAT_MBYTE
+ /* For multi-byte chars check character length against
+ * COMPOUNDMIN. */
+ if (has_mbyte
+ && slang->sl_compminlen < MAXWLEN
+ && mb_charlen_len(mip->mi_word + mip->mi_compoff,
+ wlen - mip->mi_compoff) < slang->sl_compminlen)
+ continue;
+#endif
/* Limit the number of compound words to COMPOUNDMAX if no
* maximum for syllables is specified. */
@@ -1358,6 +1378,10 @@ find_word(mip, mode)
}
}
+ /* Check NEEDCOMPOUND: can't use word without compounding. */
+ else if (flags & WF_NEEDCOMP)
+ continue;
+
nobreak_result = SP_OK;
if (!word_ends)
@@ -1762,7 +1786,8 @@ no_spell_checking(wp)
/*
* Move to next spell error.
- * "curline" is TRUE for "z?": find word under/after cursor in the same line.
+ * "curline" is FALSE for "[s", "]s", "[S" and "]S".
+ * "curline" is TRUE to find word under/after cursor in the same line.
* For Insert mode completion "dir" is BACKWARD and "curline" is TRUE: move
* to after badly spelled word before the cursor.
* Return 0 if not found, length of the badly spelled word otherwise.
@@ -1771,7 +1796,7 @@ no_spell_checking(wp)
spell_move_to(wp, dir, allwords, curline, attrp)
win_T *wp;
int dir; /* FORWARD or BACKWARD */
- int allwords; /* TRUE for "[s" and "]s" */
+ int allwords; /* TRUE for "[s"/"]s", FALSE for "[S"/"]S" */
int curline;
int *attrp; /* return: attributes of bad word or NULL */
{
@@ -1790,6 +1815,8 @@ spell_move_to(wp, dir, allwords, curline, attrp)
int buflen = 0;
int skip = 0;
int capcol = -1;
+ int found_one = FALSE;
+ int wrapped = FALSE;
if (no_spell_checking(wp))
return 0;
@@ -1840,9 +1867,11 @@ spell_move_to(wp, dir, allwords, curline, attrp)
endp = buf + len;
while (p < endp)
{
- /* When searching backward don't search after the cursor. */
+ /* When searching backward don't search after the cursor. Unless
+ * we wrapped around the end of the buffer. */
if (dir == BACKWARD
&& lnum == wp->w_cursor.lnum
+ && !wrapped
&& (colnr_T)(p - buf) >= wp->w_cursor.col)
break;
@@ -1855,14 +1884,17 @@ spell_move_to(wp, dir, allwords, curline, attrp)
/* We found a bad word. Check the attribute. */
if (allwords || attr == highlight_attr[HLF_SPB])
{
+ found_one = TRUE;
+
/* When searching forward only accept a bad word after
* the cursor. */
if (dir == BACKWARD
- || lnum > wp->w_cursor.lnum
+ || lnum != wp->w_cursor.lnum
|| (lnum == wp->w_cursor.lnum
- && (colnr_T)(curline ? p - buf + len
+ && (wrapped
+ || (colnr_T)(curline ? p - buf + len
: p - buf)
- > wp->w_cursor.col))
+ > wp->w_cursor.col)))
{
if (has_syntax)
{
@@ -1906,7 +1938,7 @@ spell_move_to(wp, dir, allwords, curline, attrp)
if (dir == BACKWARD && found_pos.lnum != 0)
{
- /* Use the last match in the line. */
+ /* Use the last match in the line (before the cursor). */
wp->w_cursor = found_pos;
vim_free(buf);
return found_len;
@@ -1918,16 +1950,42 @@ spell_move_to(wp, dir, allwords, curline, attrp)
/* Advance to next line. */
if (dir == BACKWARD)
{
- if (lnum == 1)
+ /* If we are back at the starting line and searched it again there
+ * is no match, give up. */
+ if (lnum == wp->w_cursor.lnum && wrapped)
break;
- --lnum;
+
+ if (lnum > 1)
+ --lnum;
+ else if (!p_ws)
+ break; /* at first line and 'nowrapscan' */
+ else
+ {
+ /* Wrap around to the end of the buffer. May search the
+ * starting line again and accept the last match. */
+ lnum = wp->w_buffer->b_ml.ml_line_count;
+ wrapped = TRUE;
+ }
capcol = -1;
}
else
{
- if (lnum == wp->w_buffer->b_ml.ml_line_count)
+ if (lnum < wp->w_buffer->b_ml.ml_line_count)
+ ++lnum;
+ else if (!p_ws)
+ break; /* at first line and 'nowrapscan' */
+ else
+ {
+ /* Wrap around to the start of the buffer. May search the
+ * starting line again and accept the first match. */
+ lnum = 1;
+ wrapped = TRUE;
+ }
+
+ /* If we are back at the starting line and there is no match then
+ * give up. */
+ if (lnum == wp->w_cursor.lnum && !found_one)
break;
- ++lnum;
/* Skip the characters at the start of the next line that were
* included in a match crossing line boundaries. */
@@ -2450,10 +2508,8 @@ endFAIL:
/* truncating the name signals the error to spell_load_lang() */
*lang = NUL;
if (lp != NULL && old_lp == NULL)
- {
slang_free(lp);
- lp = NULL;
- }
+ lp = NULL;
endOK:
if (fd != NULL)
@@ -2885,7 +2941,7 @@ read_compound(fd, slang, len)
--todo;
c = getc(fd); /* <compminlen> */
if (c < 1)
- c = 3;
+ c = MAXWLEN;
slang->sl_compminlen = c;
--todo;
@@ -2972,7 +3028,7 @@ read_compound(fd, slang, len)
}
else /* normal char, "[abc]" and '*' are copied as-is */
{
- if (c == '+')
+ if (c == '+' || c == '~')
*pp++ = '\\'; /* "a+" becomes "a\+" */
#ifdef FEAT_MBYTE
if (enc_utf8)
@@ -3594,10 +3650,11 @@ did_set_spelllang(buf)
/* If it was already found above then skip it. */
for (c = 0; c < ga.ga_len; ++c)
- if (fullpathcmp(spf_name,
- LANGP_ENTRY(ga, c)->lp_slang->sl_fname,
- FALSE) == FPC_SAME)
+ {
+ p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
+ if (p != NULL && fullpathcmp(spf_name, p, FALSE) == FPC_SAME)
break;
+ }
if (c < ga.ga_len)
continue;
}
@@ -3646,15 +3703,6 @@ did_set_spelllang(buf)
}
}
- /* Add a NULL entry to mark the end of the list. */
- if (ga_grow(&ga, 1) == FAIL)
- {
- ga_clear(&ga);
- return e_outofmem;
- }
- LANGP_ENTRY(ga, ga.ga_len)->lp_slang = NULL;
- ++ga.ga_len;
-
/* Everything is fine, store the new b_langp value. */
ga_clear(&buf->b_langp);
buf->b_langp = ga;
@@ -3934,13 +3982,17 @@ spell_reload_one(fname, added_word)
int didit = FALSE;
for (lp = first_lang; lp != NULL; lp = lp->sl_next)
+ {
if (fullpathcmp(fname, lp->sl_fname, FALSE) == FPC_SAME)
{
slang_clear(lp);
- (void)spell_load_file(fname, NULL, lp, FALSE);
+ if (spell_load_file(fname, NULL, lp, FALSE) == NULL)
+ /* reloading failed, clear the language */
+ slang_clear(lp);
redraw_all_later(NOT_VALID);
didit = TRUE;
}
+ }
/* When "zg" was used and the file wasn't loaded yet, should redo
* 'spelllang' to get it loaded. */
@@ -3967,6 +4019,7 @@ typedef struct afffile_S
unsigned af_kep; /* KEP ID for keep-case word */
unsigned af_bad; /* BAD ID for banned word */
unsigned af_needaffix; /* NEEDAFFIX ID */
+ unsigned af_needcomp; /* NEEDCOMPOUND ID */
int af_pfxpostpone; /* postpone prefixes without chop string */
hashtab_T af_pref; /* hashtable for prefixes, affheader_T */
hashtab_T af_suff; /* hashtable for suffixes, affheader_T */
@@ -4129,13 +4182,14 @@ typedef struct spellinfo_S
garray_T si_prefcond; /* table with conditions for postponed
* prefixes, each stored as a string */
int si_newprefID; /* current value for ah_newID */
- int si_compID; /* current value for compound ID */
+ int si_newcompID; /* current value for compound ID */
} spellinfo_T;
static afffile_T *spell_read_aff __ARGS((spellinfo_T *spin, char_u *fname));
static unsigned affitem2flag __ARGS((int flagtype, char_u *item, char_u *fname, int lnum));
static unsigned get_affitem __ARGS((int flagtype, char_u **pp));
static void process_compflags __ARGS((spellinfo_T *spin, afffile_T *aff, char_u *compflags));
+static void check_renumber __ARGS((spellinfo_T *spin));
static int flag_in_afflist __ARGS((int flagtype, char_u *afflist, unsigned flag));
static void aff_check_number __ARGS((int spinval, int affval, char *name));
static void aff_check_string __ARGS((char_u *spinval, char_u *affval, char *name));
@@ -4161,7 +4215,7 @@ static void free_wordnode __ARGS((spellinfo_T *spin, wordnode_T *n));
static void wordtree_compress __ARGS((spellinfo_T *spin, wordnode_T *root));
static int node_compress __ARGS((spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, int *tot));
static int node_equal __ARGS((wordnode_T *n1, wordnode_T *n2));
-static void write_vim_spell __ARGS((spellinfo_T *spin, char_u *fname));
+static int write_vim_spell __ARGS((spellinfo_T *spin, char_u *fname));
static void clear_node __ARGS((wordnode_T *node));
static int put_node __ARGS((FILE *fd, wordnode_T *node, int index, int regionmask, int prefixtree));
static void mkspell __ARGS((int fcount, char_u **fnames, int ascii, int overwrite, int added_word));
@@ -4445,7 +4499,9 @@ spell_read_aff(spin, fname)
smsg((char_u *)_("Invalid value for FLAG in %s line %d: %s"),
fname, lnum, items[1]);
if (aff->af_rar != 0 || aff->af_kep != 0 || aff->af_bad != 0
- || aff->af_needaffix != 0 || compflags != NULL
+ || aff->af_needaffix != 0
+ || aff->af_needcomp != 0
+ || compflags != NULL
|| aff->af_suff.ht_used > 0
|| aff->af_pref.ht_used > 0)
smsg((char_u *)_("FLAG after using flags in %s line %d: %s"),
@@ -4496,6 +4552,12 @@ spell_read_aff(spin, fname)
aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
fname, lnum);
}
+ else if (STRCMP(items[0], "NEEDCOMPOUND") == 0 && itemcnt == 2
+ && aff->af_needcomp == 0)
+ {
+ aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
+ fname, lnum);
+ }
else if (STRCMP(items[0], "COMPOUNDFLAG") == 0 && itemcnt == 2
&& compflags == NULL)
{
@@ -4608,8 +4670,9 @@ spell_read_aff(spin, fname)
if (cur_aff->ah_flag == aff->af_bad
|| cur_aff->ah_flag == aff->af_rar
|| cur_aff->ah_flag == aff->af_kep
- || cur_aff->ah_flag == aff->af_needaffix)
- smsg((char_u *)_("Affix also used for BAD/RAR/KEP/NEEDAFFIX in %s line %d: %s"),
+ || cur_aff->ah_flag == aff->af_needaffix
+ || cur_aff->ah_flag == aff->af_needcomp)
+ smsg((char_u *)_("Affix also used for BAD/RAR/KEP/NEEDAFFIX/NEEDCOMPOUND in %s line %d: %s"),
fname, lnum, items[1]);
STRCPY(cur_aff->ah_key, items[1]);
hash_add(tp, cur_aff->ah_key);
@@ -4643,6 +4706,7 @@ spell_read_aff(spin, fname)
{
/* Use a new number in the .spl file later, to be able
* to handle multiple .aff files. */
+ check_renumber(spin);
cur_aff->ah_newID = ++spin->si_newprefID;
/* We only really use ah_newID if the prefix is
@@ -5011,11 +5075,11 @@ spell_read_aff(spin, fname)
process_compflags(spin, aff, compflags);
/* Check that we didn't use too many renumbered flags. */
- if (spin->si_compID < spin->si_newprefID)
+ if (spin->si_newcompID < spin->si_newprefID)
{
- if (spin->si_compID == 255)
+ if (spin->si_newcompID == 127 || spin->si_newcompID == 255)
MSG(_("Too many postponed prefixes"));
- else if (spin->si_newprefID == 0)
+ else if (spin->si_newprefID == 0 || spin->si_newprefID == 127)
MSG(_("Too many compound flags"));
else
MSG(_("Too many posponed prefixes and/or compound flags"));
@@ -5199,8 +5263,9 @@ process_compflags(spin, aff, compflags)
* regexp (also inside []). */
do
{
- id = spin->si_compID--;
- } while (vim_strchr((char_u *)"/*+[]\\-^", id) != NULL);
+ check_renumber(spin);
+ id = spin->si_newcompID--;
+ } while (vim_strchr((char_u *)"/+*[]\\-^", id) != NULL);
ci->ci_newID = id;
hash_add(&aff->af_comp, ci->ci_key);
}
@@ -5215,6 +5280,23 @@ process_compflags(spin, aff, compflags)
}
/*
+ * Check that the new IDs for postponed affixes and compounding don't overrun
+ * each other. We have almost 255 available, but start at 0-127 to avoid
+ * using two bytes for utf-8. When the 0-127 range is used up go to 128-255.
+ * When that is used up an error message is given.
+ */
+ static void
+check_renumber(spin)
+ spellinfo_T *spin;
+{
+ if (spin->si_newprefID == spin->si_newcompID && spin->si_newcompID < 128)
+ {
+ spin->si_newprefID = 127;
+ spin->si_newcompID = 255;
+ }
+}
+
+/*
* Return TRUE if flag "flag" appears in affix list "afflist".
*/
static int
@@ -5579,6 +5661,9 @@ spell_read_dic(spin, fname, affile)
if (affile->af_needaffix != 0 && flag_in_afflist(
affile->af_flagtype, afflist, affile->af_needaffix))
need_affix = TRUE;
+ if (affile->af_needcomp != 0 && flag_in_afflist(
+ affile->af_flagtype, afflist, affile->af_needcomp))
+ flags |= WF_NEEDCOMP;
if (affile->af_pfxpostpone)
/* Need to store the list of prefix IDs with the word. */
@@ -6703,8 +6788,9 @@ rep_compare(s1, s2)
/*
* Write the Vim .spl file "fname".
+ * Return FAIL or OK;
*/
- static void
+ static int
write_vim_spell(spin, fname)
spellinfo_T *spin;
char_u *fname;
@@ -6720,18 +6806,22 @@ write_vim_spell(spin, fname)
fromto_T *ftp;
char_u *p;
int rr;
+ int retval = OK;
fd = mch_fopen((char *)fname, "w");
if (fd == NULL)
{
EMSG2(_(e_notopen), fname);
- return;
+ return FAIL;
}
/* <HEADER>: <fileID> <versionnr> */
/* <fileID> */
if (fwrite(VIMSPELLMAGIC, VIMSPELLMAGICL, (size_t)1, fd) != 1)
+ {
EMSG(_(e_write));
+ retval = FAIL;
+ }
putc(VIMSPELLVERSION, fd); /* <versionnr> */
/*
@@ -6995,7 +7085,14 @@ write_vim_spell(spin, fname)
(void)put_node(fd, tree, 0, regionmask, round == 3);
}
- fclose(fd);
+ /* Write another byte to check for errors. */
+ if (putc(0, fd) == EOF)
+ retval = FAIL;
+
+ if (fclose(fd) == EOF)
+ retval = FAIL;
+
+ return retval;
}
/*
@@ -7221,7 +7318,7 @@ mkspell(fcount, fnames, ascii, overwrite, added_word)
ga_init2(&spin.si_sal, (int)sizeof(fromto_T), 20);
ga_init2(&spin.si_map, (int)sizeof(char_u), 100);
ga_init2(&spin.si_prefcond, (int)sizeof(char_u *), 50);
- spin.si_compID = 255; /* start compound ID at maximum, going down */
+ spin.si_newcompID = 127; /* start compound ID at first maximum */
/* default: fnames[0] is output file, following are input files */
innames = &fnames[1];
@@ -7407,7 +7504,7 @@ mkspell(fcount, fnames, ascii, overwrite, added_word)
verbose_leave();
}
- write_vim_spell(&spin, wfname);
+ error = write_vim_spell(&spin, wfname) == FAIL;
if (spin.si_verbose || p_verbose > 2)
{
@@ -7422,7 +7519,8 @@ mkspell(fcount, fnames, ascii, overwrite, added_word)
}
/* If the file is loaded need to reload it. */
- spell_reload_one(wfname, added_word);
+ if (!error)
+ spell_reload_one(wfname, added_word);
}
/* Free the allocated memory. */
@@ -7602,7 +7700,7 @@ init_spellfile()
{
char_u buf[MAXPATHL];
int l;
- slang_T *sl;
+ char_u *fname;
char_u *rtp;
char_u *lend;
@@ -7624,12 +7722,14 @@ init_spellfile()
{
/* Use the first language name from 'spelllang' and the
* encoding used in the first loaded .spl file. */
- sl = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang;
+ fname = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang->sl_fname;
+ if (fname == NULL)
+ break;
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(sl->sl_fname), ".ascii.") != NULL
+ strstr((char *)gettail(fname), ".ascii.") != NULL
? (char_u *)"ascii" : spell_enc());
set_option_value((char_u *)"spellfile", 0L, buf, OPT_LOCAL);
break;
@@ -8976,6 +9076,7 @@ suggest_try_change(su)
int repextra = 0; /* extra bytes in fword[] from REP item */
slang_T *slang;
int fword_ends;
+ int lpi;
/* 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
@@ -8985,11 +9086,16 @@ suggest_try_change(su)
p = su->su_badptr + su->su_badlen;
(void)spell_casefold(p, STRLEN(p), fword + n, MAXWLEN - n);
- for (lp = LANGP_ENTRY(curwin->w_buffer->b_langp, 0);
- lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
{
+ lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
slang = lp->lp_slang;
+ /* If reloading a spell file fails it's still in the list but
+ * everything has been cleared. */
+ if (slang->sl_fbyts == NULL)
+ continue;
+
/*
* Go through the whole case-fold tree, try changes at each node.
* "tword[]" contains the word collected from nodes in the tree.
@@ -9146,6 +9252,11 @@ suggest_try_change(su)
}
}
+ /* Check NEEDCOMPOUND: can't use word without compounding. */
+ if (sp->ts_complen == sp->ts_compsplit && fword_ends
+ && (flags & WF_NEEDCOMP))
+ break;
+
if (sp->ts_complen > sp->ts_compsplit)
{
if (slang->sl_nobreak)
@@ -9178,6 +9289,16 @@ suggest_try_change(su)
|| sp->ts_twordlen - sp->ts_splitoff
< slang->sl_compminlen)
break;
+#ifdef FEAT_MBYTE
+ /* For multi-byte chars check character length against
+ * COMPOUNDMIN. */
+ if (has_mbyte
+ && slang->sl_compminlen < MAXWLEN
+ && mb_charlen(tword + sp->ts_splitoff)
+ < slang->sl_compminlen)
+ break;
+#endif
+
compflags[sp->ts_complen] = ((unsigned)flags >> 24);
compflags[sp->ts_complen + 1] = NUL;
vim_strncpy(preword + sp->ts_prewordlen,
@@ -9307,6 +9428,12 @@ suggest_try_change(su)
&& ((unsigned)flags >> 24) != 0
&& sp->ts_twordlen - sp->ts_splitoff
>= slang->sl_compminlen
+#ifdef FEAT_MBYTE
+ && (!has_mbyte
+ || slang->sl_compminlen == MAXWLEN
+ || mb_charlen(tword + sp->ts_splitoff)
+ >= slang->sl_compminlen)
+#endif
&& (slang->sl_compsylmax < MAXWLEN
|| sp->ts_complen + 1 - sp->ts_compsplit
< slang->sl_compmax)
@@ -10282,13 +10409,15 @@ score_comp_sal(su)
suggest_T *stp;
suggest_T *sstp;
int score;
+ int lpi;
if (ga_grow(&su->su_sga, su->su_ga.ga_len) == FAIL)
return;
/* Use the sound-folding of the first language that supports it. */
- for (lp = LANGP_ENTRY(curwin->w_buffer->b_langp, 0);
- lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+ {
+ lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
if (lp->lp_slang->sl_sal.ga_len > 0)
{
/* soundfold the bad word */
@@ -10317,6 +10446,7 @@ score_comp_sal(su)
}
break;
}
+ }
}
/*
@@ -10336,11 +10466,12 @@ score_combine(su)
char_u *p;
char_u badsound[MAXWLEN];
int round;
+ int lpi;
/* Add the alternate score to su_ga. */
- for (lp = LANGP_ENTRY(curwin->w_buffer->b_langp, 0);
- lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
{
+ lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
if (lp->lp_slang->sl_sal.ga_len > 0)
{
/* soundfold the bad word */
@@ -10483,11 +10614,12 @@ suggest_try_soundalike(su)
int flags;
int sound_score;
int local_score;
+ int lpi;
/* Do this for all languages that support sound folding. */
- for (lp = LANGP_ENTRY(curwin->w_buffer->b_langp, 0);
- lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
{
+ lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
if (lp->lp_slang->sl_sal.ga_len > 0)
{
/* soundfold the bad word */
@@ -10940,10 +11072,11 @@ rescore_suggestions(su)
suggest_T *stp;
char_u sal_badword[MAXWLEN];
int i;
+ int lpi;
- for (lp = LANGP_ENTRY(curwin->w_buffer->b_langp, 0);
- lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
{
+ lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
if (lp->lp_slang->sl_sal.ga_len > 0)
{
/* soundfold the bad word */
@@ -11032,17 +11165,20 @@ eval_soundfold(word)
{
langp_T *lp;
char_u sound[MAXWLEN];
+ int lpi;
if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
/* Use the sound-folding of the first language that supports it. */
- for (lp = LANGP_ENTRY(curwin->w_buffer->b_langp, 0);
- lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < curwin->w_buffer->b_langp.ga_len; ++lpi)
+ {
+ lp = LANGP_ENTRY(curwin->w_buffer->b_langp, lpi);
if (lp->lp_slang->sl_sal.ga_len > 0)
{
/* soundfold the word */
spell_soundfold(lp->lp_slang, word, FALSE, sound);
return vim_strsave(sound);
}
+ }
/* No language with sound folding, return word as-is. */
return vim_strsave(word);
@@ -12119,6 +12255,7 @@ ex_spelldump(eap)
char_u *region_names = NULL; /* region names being used */
int do_region = TRUE; /* dump region names and numbers */
char_u *p;
+ int lpi;
if (no_spell_checking(curwin))
return;
@@ -12130,8 +12267,9 @@ ex_spelldump(eap)
/* Find out if we can support regions: All languages must support the same
* regions or none at all. */
- for (lp = LANGP_ENTRY(buf->b_langp, 0); lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
{
+ lp = LANGP_ENTRY(buf->b_langp, lpi);
p = lp->lp_slang->sl_regions;
if (p[0] != 0)
{
@@ -12156,9 +12294,12 @@ ex_spelldump(eap)
/*
* Loop over all files loaded for the entries in 'spelllang'.
*/
- for (lp = LANGP_ENTRY(buf->b_langp, 0); lp->lp_slang != NULL; ++lp)
+ for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
{
+ lp = LANGP_ENTRY(buf->b_langp, lpi);
slang = lp->lp_slang;
+ if (slang->sl_fbyts == NULL) /* reloading failed */
+ continue;
vim_snprintf((char *)IObuff, IOSIZE, "# file: %s", slang->sl_fname);
ml_append(lnum++, IObuff, (colnr_T)0, FALSE);
@@ -12205,6 +12346,7 @@ ex_spelldump(eap)
* Only use the word when the region matches. */
flags = (int)idxs[n];
if ((round == 2 || (flags & WF_KEEPCAP) == 0)
+ && (flags & WF_NEEDCOMP) == 0
&& (do_region
|| (flags & WF_REGION) == 0
|| (((unsigned)flags >> 16)
@@ -12222,7 +12364,7 @@ ex_spelldump(eap)
/* Apply the prefix, if there is one. */
if (c != 0)
- lnum = apply_prefixes(slang, word, round,
+ lnum = dump_prefixes(slang, word, round,
flags, lnum);
}
}
@@ -12302,7 +12444,7 @@ dump_word(word, round, flags, lnum)
* Return the updated line number.
*/
static linenr_T
-apply_prefixes(slang, word, round, flags, startlnum)
+dump_prefixes(slang, word, round, flags, startlnum)
slang_T *slang;
char_u *word; /* case-folded word */
int round;
diff --git a/src/testdir/test58.in b/src/testdir/test58.in
index 530b27a05..8bb58bfee 100644
--- a/src/testdir/test58.in
+++ b/src/testdir/test58.in
@@ -6,63 +6,50 @@ STARTTEST
:" Don't want to depend on the locale from the environment
:set enc=latin1
:e!
-:" First generate a .spl file from a .dic and a .aff file.
-gg:/^affstart1/+1,/^affend1/-1w! Xtest.aff
-gg:/^dicstart/+1,/^dicend/-1w! Xtest.dic
-:mkspell! Xtest Xtest
:"
-:" use that spell file
-:set spl=Xtest.latin1.spl
-:set spell
-:func SpellTest()
-/^test1:
-normal ]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 4)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
+:" Function to test .aff/.dic with list of good and bad words.
+:func TestOne(aff, dic)
+ set spellfile=
+ $put =''
+ $put ='test '. a:aff . '-' . a:dic
+ " Generate a .spl file from a .dic and .aff file.
+ exe '1;/^' . a:aff . 'affstart/+1,/^' . a:aff . 'affend/-1w! Xtest.aff'
+ exe '1;/^' . a:dic . 'dicstart/+1,/^' . a:dic . 'dicend/-1w! Xtest.dic'
+ mkspell! Xtest Xtest
+ " use that spell file
+ set spl=Xtest.latin1.spl spell
+ " list all valid words
+ spelldump
+ %yank
+ quit
+ $put
+ $put ='-------'
+ " find all bad words and suggestions for them
+ exe '1;/^' . a:aff . 'good:'
+ normal 0f:]s
+ let prevbad = ''
+ while 1
+ let bad = spellbadword()
+ if bad == '' || bad == prevbad || bad == 'badend'
+ break
+ endif
+ let prevbad = bad
+ let lst = spellsuggest(bad, 3)
+ normal mm
+ $put =bad
+ $put =string(lst)
+ normal `m]s
+ endwhile
endfunc
-:call SpellTest()
-:spelldump
-1GyG:q
-:$put
+:"
+:call TestOne('1', '1')
:$put =soundfold('goobledygoook')
:$put =soundfold('kóopërÿnôven')
:$put =soundfold('oeverloos gezwets edale')
:"
+:"
:" and now with SAL instead of SOFO items; test automatic reloading
-gg:/^affstart2/+1,/^affend2/-1w! Xtest.aff
+gg:/^affstart_sal/+1,/^affend_sal/-1w! Xtest.aff
:mkspell! Xtest Xtest
:$put =soundfold('goobledygoook')
:$put =soundfold('kóopërÿnôven')
@@ -101,39 +88,16 @@ gg:/^addstart/+1,/^addend/-1w! Xtest.latin1.add
:$put =str
:"
:" Postponed prefixes
-gg:/^affstart3/+1,/^affend3/-1w! Xtest.aff
-:mkspell! Xtest Xtest
-:set spellfile=
-:set spl=Xtest.latin1.spl
-:spelldump
-1GyG:q
-:$put
-:call SpellTest()
+:call TestOne('2', '1')
:"
-:" Compounding
-gg:/^compaffstart/+1,/^compaffend/-1w! Xtest.aff
-gg:/^compdicstart/+1,/^compdicend/-1w! Xtest.dic
-:mkspell! Xtest Xtest
-:set spellfile=
-:set spl=Xtest.latin1.spl
-:spelldump
-1GyG:q
-:$put
-/^comptest:
-:for i in range(11)
-normal ]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 3)
-$put =string(lst)
-normal `m
-endfor
+:" Compound words
+:call TestOne('3', '3')
+:call TestOne('4', '4')
:"
gg:/^test output:/,$wq! test.out
ENDTEST
-affstart1
+1affstart
SET ISO8859-1
TRY esianrtolcdugmphbyfvkwjkqxz-ëéèêïîäàâöüû'ESIANRTOLCDUGMPHBYFVKWJKQXZ
@@ -182,9 +146,27 @@ MAP nñ
MAP cç
MAP yÿý
MAP sß
-affend1
+1affend
+
+1good: wrong OK puts. Test the end
+bad: inputs comment ok Ok. test déôl end the
+badend
+
+1dicstart
+123456
+test/NO
+# comment
+wrong
+Comment
+OK
+uk
+put/ISO
+the end
+deol
+déôr
+1dicend
-affstart2
+affstart_sal
SET ISO8859-1
TRY esianrtolcdugmphbyfvkwjkqxz-ëéèêïîäàâöüû'ESIANRTOLCDUGMPHBYFVKWJKQXZ
@@ -338,9 +320,9 @@ SAL X KS
SAL Y(AEIOU)- Y
SAL ZZ- _
SAL Z S
-affend2
+affend_sal
-affstart3
+2affstart
SET ISO8859-1
FOL àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþßÿ
@@ -387,23 +369,47 @@ MAP nñ
MAP cç
MAP yÿý
MAP sß
-affend3
+2affend
-dicstart
-123456
-test/NO
-# comment
-wrong
-Comment
-OK
-uk
-put/ISO
-the end
-deol
-déôr
-dicend
+2good: puts
+bad: inputs comment ok Ok end the. test déôl
+badend
-compaffstart
+addstart
+/regions=usgbnz
+elequint/2
+elekwint/3
+addend
+
+test2:
+elequint test elekwint test elekwent asdf
+
+Test rules for compounding.
+
+3affstart
+SET ISO8859-1
+
+COMPOUNDMIN 3
+COMPOUNDFLAGS m*
+NEEDCOMPOUND x
+3affend
+
+3dicstart
+1234
+foo/m
+bar/mx
+mï/m
+la/mx
+3dicend
+
+3good: foo mï foobar foofoobar barfoo barbarfoo
+bad: bar la foomï barmï mïfoo mïbar mïmï lala mïla lamï foola labar
+badend
+
+
+Tests for compounding.
+
+4affstart
SET ISO8859-1
FOL àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþßÿ
@@ -445,9 +451,9 @@ SFX a 0 ize . nocomp
PFX p N 1
PFX p 0 pre .
-compaffend
+4affend
-compdicstart
+4dicstart
1234
word/m
util/am
@@ -456,37 +462,16 @@ tomato/m
bork/mp
start/s
end/e
-compdicend
-
-addstart
-/regions=usgbnz
-elequint/2
-elekwint/3
-addend
-
-test1:
-inputs wrong
-comment wrong
-puts OK
-ok wrong
-Ok wrong
-the end. test wrong
-déôl
-
-test2:
-elequint test elekwint test elekwent asdf
-
-comptest:
-word util
-wordutil wordutils wordutilize
-pro pro-ok
-bork borkbork borkborkbork borkborkborkbork borkborkborkborkbork
-borkborkborkborkborkbork
-tomato tomatotomato tomatotomatotomato
-startend endstart endend startstart wordend
-startword startwordword wordstart startwordend startwordwordend
-startwordwordwordend startwordwordwordwordend
-prebork preborkprebork preborkborkprebork preborkpreborkbork
-borkpreborkpreborkbork
+4dicend
+
+4good: word util bork prebork start end wordutil wordutils pro-ok
+ bork borkbork borkborkbork borkborkborkbork borkborkborkborkbork
+ tomato tomatotomato startend startword startwordword startwordend
+ startwordwordend startwordwordwordend prebork preborkprebork
+ preborkborkprebork preborkpreborkbork
+bad: wordutilize pro borkborkborkborkborkbork tomatotomatotomato
+ endstart endend startstart wordend wordstart
+ startwordwordwordwordend borkpreborkpreborkbork
+badend
test output:
diff --git a/src/testdir/test58.ok b/src/testdir/test58.ok
index 570ab7d7e..67f1f9cac 100644
--- a/src/testdir/test58.ok
+++ b/src/testdir/test58.ok
@@ -1,16 +1,6 @@
test output:
-inputs
-['input', 'puts', 'outputs', 'put']
-comment
-['Comment']
-ok
-['OK', 'uk']
-Ok
-['OK', 'Uk']
-test
-['test', 'Test']
-déôl
-['deol', 'déôr']
+
+test 1-1
# file: Xtest.latin1.spl
Comment
deol
@@ -28,6 +18,25 @@ testn
the end
uk
wrong
+-------
+bad
+['put', 'OK', 'uk']
+inputs
+['input', 'puts', 'outputs']
+comment
+['Comment']
+ok
+['OK', 'uk', 'put']
+Ok
+['OK', 'Uk', 'Put']
+test
+['test', 'Test', 'testn']
+déôl
+['deol', 'déôr', 'test']
+end
+['put', 'test', 'uk']
+the
+['put', 'uk', 'test']
gebletegek
kepereneven
everles gesvets etele
@@ -43,6 +52,8 @@ elequint
elekwent
elequint
elekwint
+
+test 2-1
# file: Xtest.latin1.spl
Comment
deol
@@ -60,18 +71,59 @@ testn
the end
uk
wrong
+-------
+bad
+['put', 'uk', 'OK']
inputs
-['input', 'puts', 'put', 'outputs']
+['input', 'puts', 'put']
comment
['Comment']
ok
-['OK', 'uk']
+['OK', 'uk', 'put']
Ok
-['OK', 'Uk']
+['OK', 'Uk', 'Put']
+end
+['put', 'uk', 'deol']
+the
+['put', 'uk', 'test']
test
-['test', 'Test']
+['test', 'Test', 'testn']
déôl
-['deol', 'déôr']
+['deol', 'déôr', 'test']
+
+test 3-3
+# file: Xtest.latin1.spl
+foo
+mï
+-------
+bad
+['foo', 'mï']
+bar
+['foobar', 'foo', 'mï']
+la
+['mï', 'foo']
+foomï
+['foo mï', 'foo', 'foofoo']
+barmï
+['bar mï', 'barfoo', 'barbar']
+mïfoo
+['mï foo', 'foo', 'foofoo']
+mïbar
+['foobar', 'barbar', 'mï']
+mïmï
+['mï mï', 'mï', 'la mï']
+lala
+['la mï']
+mïla
+['mï', 'mï mï']
+lamï
+['la mï', 'mï', 'mï mï']
+foola
+['foo', 'foobar', 'foofoo']
+labar
+['barbar', 'foobar']
+
+test 4-4
# file: Xtest.latin1.spl
bork
prebork
@@ -83,6 +135,9 @@ util
utilize
utils
word
+-------
+bad
+['end', 'bork', 'word']
wordutilize
['word utilize', 'wordutils', 'wordutil']
pro
diff --git a/src/testdir/test59.in b/src/testdir/test59.in
index a49514fa5..aab48aeea 100644
--- a/src/testdir/test59.in
+++ b/src/testdir/test59.in
@@ -8,65 +8,52 @@ STARTTEST
:" text is in latin1, the test text is utf-8.
:set enc=latin1
:e!
-:set fenc=
-:" First generate a .spl file from a .dic and a .aff file.
-gg:/^affstart1/+1,/^affend1/-1w! Xtest.aff
-gg:/^dicstart/+1,/^dicend/-1w! Xtest.dic
:set enc=utf-8
-:mkspell! Xtest Xtest
+:set fenc=
:"
-:" use that spell file
-:set spl=Xtest.utf-8.spl
-:set spell
-:func SpellTest()
-/^test1:
-normal ]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 4)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
-normal `m]smm
-let str = spellbadword()
-$put =str
-normal `m
-let lst = spellsuggest(str, 2)
-$put =string(lst)
+:" Function to test .aff/.dic with list of good and bad words.
+:func TestOne(aff, dic)
+ set spellfile=
+ $put =''
+ $put ='test '. a:aff . '-' . a:dic
+ " Generate a .spl file from a .dic and .aff file.
+ exe '1;/^' . a:aff . 'affstart/+1,/^' . a:aff . 'affend/-1w! Xtest.aff'
+ exe '1;/^' . a:dic . 'dicstart/+1,/^' . a:dic . 'dicend/-1w! Xtest.dic'
+ mkspell! Xtest Xtest
+ " use that spell file
+ set spl=Xtest.utf-8.spl spell
+ " list all valid words
+ spelldump
+ %yank
+ quit
+ $put
+ $put ='-------'
+ " find all bad words and suggestions for them
+ exe '1;/^' . a:aff . 'good:'
+ normal 0f:]s
+ let prevbad = ''
+ while 1
+ let bad = spellbadword()
+ if bad == '' || bad == prevbad || bad == 'badend'
+ break
+ endif
+ let prevbad = bad
+ let lst = spellsuggest(bad, 3)
+ normal mm
+ $put =bad
+ $put =string(lst)
+ normal `m]s
+ endwhile
endfunc
-:call SpellTest()
-:spelldump
-1GyG:q
-:$put
+:"
+:call TestOne('1', '1')
:$put =soundfold('goobledygoook')
:$put =soundfold('kóopërÿnôven')
:$put =soundfold('oeverloos gezwets edale')
:"
+:"
:" and now with SAL instead of SOFO items; test automatic reloading
-gg:/^affstart2/+1,/^affend2/-1w! Xtest.aff
+gg:/^affstart_sal/+1,/^affend_sal/-1w! Xtest.aff
:mkspell! Xtest Xtest
:$put =soundfold('goobledygoook')
:$put =soundfold('kóopërÿnôven')
@@ -105,20 +92,16 @@ gg:/^addstart/+1,/^addend/-1w! Xtest.utf-8.add
:$put =str
:"
:" Postponed prefixes
-gg:/^affstart3/+1,/^affend3/-1w! Xtest.aff
-:mkspell! Xtest Xtest
-:set spellfile=
-:set spl=Xtest.utf-8.spl
-:mess
-:spelldump
-1GyG:q
-:$put
-:call SpellTest()
+:call TestOne('2', '1')
+:"
+:" Compound words
+:call TestOne('3', '3')
+:call TestOne('4', '4')
:"
gg:/^test output:/,$wq! test.out
ENDTEST
-affstart1
+1affstart
SET ISO8859-1
TRY esianrtolcdugmphbyfvkwjkqxz-ëéèêïîäàâöüû'ESIANRTOLCDUGMPHBYFVKWJKQXZ
@@ -167,9 +150,9 @@ MAP nñ
MAP cç
MAP yÿý
MAP sß
-affend1
+1affend
-affstart2
+affstart_sal
SET ISO8859-1
TRY esianrtolcdugmphbyfvkwjkqxz-ëéèêïîäàâöüû'ESIANRTOLCDUGMPHBYFVKWJKQXZ
@@ -323,9 +306,9 @@ SAL X KS
SAL Y(AEIOU)- Y
SAL ZZ- _
SAL Z S
-affend2
+affend_sal
-affstart3
+2affstart
SET ISO8859-1
FOL àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþßÿ
@@ -372,9 +355,9 @@ MAP nñ
MAP cç
MAP yÿý
MAP sß
-affend3
+2affend
-dicstart
+1dicstart
123456
test/NO
# comment
@@ -386,7 +369,7 @@ put/ISO
the end
deol
déôr
-dicend
+1dicend
addstart
/regions=usgbnz
@@ -394,17 +377,105 @@ elequint/2
elekwint/3
addend
-test1:
-inputs wrong
-comment wrong
-puts OK
-ok wrong
-Ok wrong
-the end. test wrong
-déôl
+1good: wrong OK puts. Test the end
+bad: inputs comment ok Ok. test déôl end the
+badend
+
+2good: puts
+bad: inputs comment ok Ok end the. test déôl
+badend
+
+Test rules for compounding.
+
+3affstart
+SET ISO8859-1
+
+COMPOUNDMIN 3
+COMPOUNDFLAGS m*
+NEEDCOMPOUND x
+3affend
+
+3dicstart
+1234
+foo/m
+bar/mx
+mï/m
+la/mx
+3dicend
+
+3good: foo mï foobar foofoobar barfoo barbarfoo
+bad: bar la foomï barmï mïfoo mïbar mïmï lala mïla lamï foola labar
+badend
+
+
+Tests for compounding.
+
+4affstart
+SET ISO8859-1
+
+FOL àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþßÿ
+LOW àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþßÿ
+UPP ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßÿ
+
+COMPOUNDFLAGS m+
+COMPOUNDFLAGS sm*e
+COMPOUNDFLAGS sm+
+COMPOUNDMIN 3
+COMPOUNDMAX 3
+
+COMPOUNDSYLMAX 5
+SYLLABLE aáeéiíoóöõuúüûy/aa/au/ea/ee/ei/ie/oa/oe/oo/ou/uu/ui
+
+MAP 9
+MAP aàáâãäå
+MAP eèéêë
+MAP iìíîï
+MAP oòóôõö
+MAP uùúûü
+MAP nñ
+MAP cç
+MAP yÿý
+MAP sß
+
+NEEDAFFIX x
+
+PFXPOSTPONE
+
+MIDWORD '-
+
+SFX q N 1
+SFX q 0 -ok .
+
+SFX a Y 2
+SFX a 0 s .
+SFX a 0 ize . nocomp
+
+PFX p N 1
+PFX p 0 pre .
+4affend
+
+4dicstart
+1234
+word/m
+util/am
+pro/xq
+tomato/m
+bork/mp
+start/s
+end/e
+4dicend
+
+4good: word util bork prebork start end wordutil wordutils pro-ok
+ bork borkbork borkborkbork borkborkborkbork borkborkborkborkbork
+ tomato tomatotomato startend startword startwordword startwordend
+ startwordwordend startwordwordwordend prebork preborkprebork
+ preborkborkprebork preborkpreborkbork
+bad: wordutilize pro borkborkborkborkborkbork tomatotomatotomato
+ endstart endend startstart wordend wordstart
+ startwordwordwordwordend borkpreborkpreborkbork
+badend
test2:
elequint test elekwint test elekwent asdf
-
test output:
diff --git a/src/testdir/test59.ok b/src/testdir/test59.ok
index 6bbed6e22..e09eaaceb 100644
--- a/src/testdir/test59.ok
+++ b/src/testdir/test59.ok
@@ -1,16 +1,6 @@
test output:
-inputs
-['input', 'puts', 'outputs', 'put']
-comment
-['Comment']
-ok
-['OK', 'uk']
-Ok
-['OK', 'Uk']
-test
-['test', 'Test']
-déôl
-['deol', 'déôr']
+
+test 1-1
# file: Xtest.utf-8.spl
Comment
deol
@@ -28,6 +18,25 @@ testn
the end
uk
wrong
+-------
+bad
+['put', 'OK', 'uk']
+inputs
+['input', 'puts', 'outputs']
+comment
+['Comment']
+ok
+['OK', 'uk', 'put']
+Ok
+['OK', 'Uk', 'Put']
+test
+['test', 'Test', 'testn']
+déôl
+['deol', 'déôr', 'test']
+end
+['put', 'test', 'uk']
+the
+['put', 'uk', 'test']
gebletegek
kepereneven
everles gesvets etele
@@ -43,6 +52,8 @@ elequint
elekwent
elequint
elekwint
+
+test 2-1
# file: Xtest.utf-8.spl
Comment
deol
@@ -60,15 +71,92 @@ testn
the end
uk
wrong
+-------
+bad
+['put', 'uk', 'OK']
inputs
-['input', 'puts', 'put', 'outputs']
+['input', 'puts', 'put']
comment
['Comment']
ok
-['OK', 'uk']
+['OK', 'uk', 'put']
Ok
-['OK', 'Uk']
+['OK', 'Uk', 'Put']
+end
+['put', 'uk', 'deol']
+the
+['put', 'uk', 'test']
test
-['test', 'Test']
+['test', 'Test', 'testn']
déôl
-['deol', 'déôr']
+['deol', 'déôr', 'test']
+
+test 3-3
+# file: Xtest.utf-8.spl
+foo
+mï
+-------
+bad
+['foo', 'mï']
+bar
+['foobar', 'foo', 'mï']
+la
+['foo', 'mï']
+foomï
+['foo mï', 'foo', 'foofoo']
+barmï
+['bar mï', 'barfoo', 'barbar']
+mïfoo
+['mï foo', 'foo', 'foofoo']
+mïbar
+['foobar', 'barbar', 'mï']
+mïmï
+['mï mï', 'mï', 'la mï']
+lala
+[]
+mïla
+['mï']
+lamï
+['la mï', 'mï', 'mï mï']
+foola
+['foo', 'foobar', 'foofoo']
+labar
+['barbar', 'foobar']
+
+test 4-4
+# file: Xtest.utf-8.spl
+bork
+prebork
+end
+pro-ok
+start
+tomato
+util
+utilize
+utils
+word
+-------
+bad
+['end', 'bork', 'word']
+wordutilize
+['word utilize', 'wordutils', 'wordutil']
+pro
+['bork', 'end', 'word']
+borkborkborkborkborkbork
+['borkbork borkborkborkbork', 'borkborkbork borkborkbork', 'borkborkborkborkbork bork']
+tomatotomatotomato
+['tomato tomatotomato', 'tomatotomato tomato', 'tomato tomato tomato']
+endstart
+['end start', 'start']
+endend
+['end end', 'end']
+startstart
+['start start']
+wordend
+['word end', 'wordword', 'word']
+wordstart
+['word start', 'bork start']
+startwordwordwordwordend
+['startwordwordwordword end', 'startwordwordwordword', 'start wordwordwordword end']
+borkpreborkpreborkbork
+['borkpreborkprebork bork', 'borkprebork preborkbork', 'bork preborkpreborkbork']
diff --git a/src/version.h b/src/version.h
index 13e407156..2317c87a2 100644
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
#define VIM_VERSION_NODOT "vim70aa"
#define VIM_VERSION_SHORT "7.0aa"
#define VIM_VERSION_MEDIUM "7.0aa ALPHA"
-#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Aug 26)"
-#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Aug 26, compiled "
+#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Aug 29)"
+#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Aug 29, compiled "